From edfc13137ba904f5260790dee3746cf7ab5cc041 Mon Sep 17 00:00:00 2001 From: Olivier Sallou Date: Sun, 15 Jan 2017 17:12:04 +0000 Subject: [PATCH] New upstream version 2.6.0 --- c++/compilers/unix/GCC.sh | 2 +- c++/compilers/unix/ICC.sh | 2 +- c++/compilers/vs2013/build_exec.bat | 3 +- c++/compilers/vs2013/configure.bat | 2 +- .../vs2013/dll/build/gbench/ncbi_gbench.sln | 32 +- .../vs2013/dll/build/gui/ncbi_gui_dll.sln | 32 +- .../vs2013/dll/build/ncbi_cpp_dll.sln | 32 +- c++/compilers/vs2013/make.bat | 12 +- c++/compilers/vs2013/ptb.bat | 12 +- .../vs2013/static/build/gui/ncbi_gui.sln | 32 +- .../vs2013/static/build/ncbi_cpp.sln | 20 +- c++/compilers/vs2013/user/build/ncbi_user.sln | 32 +- .../vs2015/Makefile.WinMain.app.msvc | 11 + .../vs2015/Makefile.wxWidgets.app.msvc | 11 + c++/compilers/vs2015/build.sh | 264 + c++/compilers/vs2015/build_exec.bat | 51 + c++/compilers/vs2015/build_util.sh | 67 + c++/compilers/vs2015/check.sh | 276 + c++/compilers/vs2015/configure.bat | 384 + c++/compilers/vs2015/datatool.bat | 188 + .../build/UtilityProjects/_CONFIGURE_.vcxproj | 144 + .../_CONFIGURE_DIALOG_.vcxproj | 144 + .../dll/build/UtilityProjects/configure._ | 4 + .../build/UtilityProjects/configure_dialog._ | 4 + c++/compilers/vs2015/dll/build/all.bat | 42 + c++/compilers/vs2015/dll/build/all_gbench.bat | 75 + c++/compilers/vs2015/dll/build/all_gui.bat | 75 + c++/compilers/vs2015/dll/build/all_ncbi.bat | 75 + .../UtilityProjects/_CONFIGURE_.vcxproj | 148 + .../_CONFIGURE_DIALOG_.vcxproj | 148 + .../build/gbench/UtilityProjects/configure._ | 5 + .../gbench/UtilityProjects/configure_dialog._ | 5 + .../dll/build/gbench/configure_prebuild.bat | 48 + .../gbench_install/gbench-install.vcxproj | 218 + .../vs2015/dll/build/gbench/ncbi_gbench.sln | 35 + .../gui/UtilityProjects/_CONFIGURE_.vcxproj | 144 + .../_CONFIGURE_DIALOG_.vcxproj | 144 + .../dll/build/gui/UtilityProjects/configure._ | 4 + .../gui/UtilityProjects/configure_dialog._ | 4 + .../vs2015/dll/build/gui/ncbi_gui_dll.sln | 35 + .../gbench-install-internal.vcxproj | 218 + .../vs2015/dll/build/ncbi_cpp_dll.sln | 35 + c++/compilers/vs2015/dll/dll_main.cpp | 18 + .../vs2015/dll/third_party_dll_install.mak | 62 + .../dll/third_party_dll_install.vcxproj | 433 + .../dll/third_party_msvcdll_install.vcxproj | 433 + c++/compilers/vs2015/install.sh | 186 + c++/compilers/vs2015/lock_ptb_config.bat | 94 + c++/compilers/vs2015/make.bat | 223 + c++/compilers/vs2015/make_ncbi.bat | 60 + c++/compilers/vs2015/msvcvars.bat | 14 + c++/compilers/vs2015/ncbi.rc | 1 + c++/compilers/vs2015/ncbilogo.ico | Bin 0 -> 766 bytes c++/compilers/vs2015/ptb.bat | 288 + .../static/build/UtilityProjects/PTB.sln | 79 + .../build/UtilityProjects/_CONFIGURE_.vcxproj | 144 + .../_CONFIGURE_DIALOG_.vcxproj | 144 + .../static/build/UtilityProjects/configure._ | 4 + .../build/UtilityProjects/configure_dialog._ | 4 + c++/compilers/vs2015/static/build/all.bat | 39 + c++/compilers/vs2015/static/build/all_gui.bat | 79 + .../vs2015/static/build/all_ncbi.bat | 79 + .../msbuild/msbuild_dataobj.lib.vcxproj | 149 + .../project_tree_builder.exe.vcxproj | 415 + .../static/build/corelib/xncbi.lib.vcxproj | 509 + .../gui/UtilityProjects/_CONFIGURE_.vcxproj | 144 + .../_CONFIGURE_DIALOG_.vcxproj | 144 + .../build/gui/UtilityProjects/configure._ | 4 + .../gui/UtilityProjects/configure_dialog._ | 4 + .../vs2015/static/build/gui/ncbi_gui.sln | 35 + .../vs2015/static/build/ncbi_cpp.sln | 35 + .../serial/datatool/datatool.exe.vcxproj | 506 + .../static/build/serial/xser.lib.vcxproj | 533 + .../build/util/regexp/regexp.lib.vcxproj | 363 + .../build/util/xregexp/xregexp.lib.vcxproj | 176 + .../static/build/util/xutil.lib.vcxproj | 308 + .../third_party_msvcstatic_install.vcxproj | 433 + .../static/third_party_static_install.mak | 62 + .../static/third_party_static_install.vcxproj | 433 + .../vs2015/third_party_install.meta.mk | 330 + .../build/UtilityProjects/_CONFIGURE_.vcxproj | 144 + .../_CONFIGURE_DIALOG_.vcxproj | 144 + .../user/build/UtilityProjects/configure._ | 4 + .../build/UtilityProjects/configure_dialog._ | 4 + c++/compilers/vs2015/user/build/ncbi_user.sln | 35 + c++/compilers/xcode30_prj/configure | 34 +- c++/compilers/xcode30_prj/ptb.sh | 12 +- c++/configure | 2 +- c++/include/algo/blast/api/blast_aux.hpp | 26 +- c++/include/algo/blast/api/blast_options.hpp | 22 +- .../algo/blast/api/blast_options_handle.hpp | 3 +- .../algo/blast/api/blast_seqinfosrc.hpp | 2 +- .../algo/blast/api/blast_seqinfosrc_aux.hpp | 21 +- c++/include/algo/blast/api/blast_types.hpp | 3 +- c++/include/algo/blast/api/magicblast.hpp | 115 + .../algo/blast/api/magicblast_options.hpp | 211 + .../algo/blast/api/objmgrfree_query_data.hpp | 5 +- c++/include/algo/blast/api/remote_blast.hpp | 2 +- .../algo/blast/api/seqinfosrc_seqdb.hpp | 2 +- .../algo/blast/api/seqinfosrc_seqvec.hpp | 2 +- c++/include/algo/blast/api/setup_factory.hpp | 4 +- .../algo/blast/blastinput/blast_args.hpp | 162 +- .../blast/blastinput/blast_asn1_input.hpp | 119 + .../blast/blastinput/blast_fasta_input.hpp | 82 +- .../algo/blast/blastinput/blast_input.hpp | 51 +- .../algo/blast/blastinput/blast_input_aux.hpp | 15 +- .../algo/blast/blastinput/blast_scope_src.hpp | 6 +- .../algo/blast/blastinput/cmdline_flags.hpp | 51 +- .../algo/blast/blastinput/kblastp_args.hpp | 75 + .../algo/blast/blastinput/magicblast_args.hpp | 63 + .../composition_adjustment.h | 2 +- .../composition_adjustment/redo_alignment.h | 15 +- c++/include/algo/blast/core/blast_engine.h | 23 +- c++/include/algo/blast/core/blast_gapalign.h | 9 +- c++/include/algo/blast/core/blast_hits.h | 102 +- c++/include/algo/blast/core/blast_hspfilter.h | 12 +- c++/include/algo/blast/core/blast_hspstream.h | 19 +- c++/include/algo/blast/core/blast_kappa.h | 2 +- c++/include/algo/blast/core/blast_lookup.h | 53 +- c++/include/algo/blast/core/blast_nalookup.h | 112 +- c++/include/algo/blast/core/blast_options.h | 30 +- c++/include/algo/blast/core/blast_program.h | 15 +- .../algo/blast/core/blast_query_info.h | 19 +- c++/include/algo/blast/core/blast_stat.h | 2 +- .../algo/blast/core/hspfilter_mapper.h | 101 + c++/include/algo/blast/core/lookup_util.h | 4 +- c++/include/algo/blast/core/lookup_wrap.h | 8 +- c++/include/algo/blast/core/na_ungapped.h | 65 +- .../algo/blast/format/blast_format.hpp | 38 +- c++/include/algo/blast/igblast/igblast.hpp | 7 +- c++/include/cgi/cgi_session.hpp | 2 +- c++/include/cgi/cgiapp.hpp | 2 +- c++/include/cgi/cgictx.hpp | 4 +- c++/include/cgi/error_codes.hpp | 2 +- c++/include/cgi/ncbicgi.hpp | 2 +- c++/include/cgi/ncbicgir.hpp | 6 +- c++/include/cgi/user_agent.hpp | 6 +- .../common/config/ncbiconf_msvc_site.h | 35 - .../common/config/ncbiconf_universal.h | 5 +- c++/include/common/config/ncbiconf_xcode.h | 28 +- .../common/config/ncbiconf_xcode_site.h | 123 - c++/include/common/ncbi_build_ver.h.in | 37 + c++/include/common/ncbi_export.h | 19 +- c++/include/common/ncbi_package_ver.h | 2 +- c++/include/common/ncbi_source_ver.h | 12 +- c++/include/common/ncbiconf_impl.h | 2 +- .../connect/impl/server_connection.hpp | 3 +- .../connect/impl/thread_pool_for_server.hpp | 22 +- c++/include/connect/ncbi_base64.h | 8 +- c++/include/connect/ncbi_buffer.h | 5 +- c++/include/connect/ncbi_connector.h | 16 +- c++/include/connect/ncbi_connutil.h | 35 +- c++/include/connect/ncbi_core.h | 3 +- c++/include/connect/ncbi_core_cxx.hpp | 7 +- c++/include/connect/ncbi_gnutls.h | 8 +- c++/include/connect/ncbi_http_connector.h | 9 +- c++/include/connect/ncbi_http_session.hpp | 24 +- c++/include/connect/ncbi_lbos.hpp | 283 +- c++/include/connect/ncbi_monkey.hpp | 405 + c++/include/connect/ncbi_server_info.h | 5 +- c++/include/connect/ncbi_service.h | 47 +- c++/include/connect/ncbi_socket.h | 26 +- c++/include/connect/ncbi_types.h | 6 +- c++/include/connect/server.hpp | 25 +- c++/include/connect/services/grid_client.hpp | 2 +- c++/include/connect/services/grid_worker.hpp | 2 +- .../connect/services/grid_worker_app.hpp | 2 +- .../services/impl/neticache_client_int.hpp | 2 +- .../services/impl/netschedule_api_int.hpp | 2 +- .../connect/services/impl/netstorage_impl.hpp | 15 +- .../connect/services/impl/netstorage_int.hpp | 2 +- .../connect/services/json_over_uttp.hpp | 6 +- .../connect/services/netcache_api_expt.hpp | 2 +- .../connect/services/netcache_search.hpp | 169 + c++/include/connect/services/netcomponent.hpp | 9 +- .../connect/services/neticache_client.hpp | 22 +- .../connect/services/netschedule_api.hpp | 68 +- c++/include/connect/services/netstorage.hpp | 28 +- .../connect/services/netstorage_ft.hpp | 2 +- .../connect/services/ns_output_parser.hpp | 38 +- c++/include/corelib/ddumpable.hpp | 2 +- c++/include/corelib/hash_impl/_hash_map.h | 102 +- c++/include/corelib/hash_impl/_hash_set.h | 105 +- c++/include/corelib/impl/ncbi_atomic_defs.h | 6 +- c++/include/corelib/impl/ncbi_dbsvcmapper.hpp | 54 +- c++/include/corelib/ncbi_base64.h | 8 +- c++/include/corelib/ncbi_config.hpp | 2 +- c++/include/corelib/ncbi_cookies.hpp | 13 +- c++/include/corelib/ncbi_param.hpp | 14 +- c++/include/corelib/ncbi_stack.hpp | 11 +- c++/include/corelib/ncbi_xstr.hpp | 22 +- c++/include/corelib/ncbiapp.hpp | 11 +- c++/include/corelib/ncbiargs.hpp | 99 +- c++/include/corelib/ncbiatomic.h | 4 +- c++/include/corelib/ncbictype.hpp | 15 +- c++/include/corelib/ncbidbg.hpp | 2 +- c++/include/corelib/ncbidiag.hpp | 51 +- c++/include/corelib/ncbidiag.inl | 5 +- c++/include/corelib/ncbierror.hpp | 79 +- c++/include/corelib/ncbifile.hpp | 122 +- c++/include/corelib/ncbimisc.hpp | 119 +- c++/include/corelib/ncbiobj.hpp | 68 +- c++/include/corelib/ncbireg.hpp | 10 +- c++/include/corelib/ncbistl.hpp | 3 +- c++/include/corelib/ncbistr.hpp | 653 +- c++/include/corelib/request_ctx.hpp | 81 +- c++/include/corelib/rwstream.hpp | 40 +- c++/include/corelib/version.hpp | 3 +- c++/include/dbapi/dbapi.hpp | 4 +- .../dbapi/driver/dbapi_driver_conn_mgr.hpp | 2 +- .../dbapi/driver/dbapi_driver_convert.hpp | 2 +- .../dbapi/driver/dbapi_object_convert.hpp | 2 +- c++/include/dbapi/driver/dbapi_svc_mapper.hpp | 4 +- c++/include/dbapi/driver/exception.hpp | 12 +- .../dbapi/driver/impl/dbapi_driver_utils.hpp | 15 +- .../dbapi/driver/impl/dbapi_impl_cmd.hpp | 2 +- .../driver/impl/dbapi_impl_connection.hpp | 14 +- .../dbapi/driver/impl/dbapi_impl_context.hpp | 11 +- .../dbapi/driver/impl/dbapi_impl_result.hpp | 2 +- c++/include/dbapi/driver/interfaces.hpp | 33 +- c++/include/dbapi/driver/odbc/interfaces.hpp | 2 +- c++/include/dbapi/driver/public.hpp | 2 +- c++/include/dbapi/driver/types.hpp | 2 +- c++/include/dbapi/driver/util/blobstore.hpp | 2 +- c++/include/dbapi/error_codes.hpp | 2 +- c++/include/dbapi/variant.hpp | 2 +- c++/include/html/htmlhelper.hpp | 12 +- c++/include/html/nodemap.hpp | 4 +- c++/include/misc/error_codes.hpp | 52 + c++/include/ncbi_pch.hpp | 2 +- c++/include/ncbi_source_ver.h | 2 +- c++/include/ncbiconf.h | 2 +- c++/include/objects/biblio/MedlineUID.hpp | 76 + c++/include/objects/biblio/PmcID.hpp | 76 + c++/include/objects/biblio/PubMedId.hpp | 76 + c++/include/objects/general/Dbtag.hpp | 6 +- c++/include/objects/general/Name_std.hpp | 5 +- c++/include/objects/general/User_object.hpp | 9 +- .../genomecoll/GCClient_GetAssemblyBySequ.hpp | 89 + .../objects/genomecoll/GC_Assembly.hpp | 8 +- .../objects/genomecoll/cached_assembly.hpp | 4 + .../genomecoll/genomic_collections_cli.hpp | 106 +- c++/include/objects/id2/id2processor.hpp | 6 +- .../objects/macro/String_constraint.hpp | 2 +- c++/include/objects/macro/Suspect_rule.hpp | 30 +- c++/include/objects/seq/Seq_gap.hpp | 2 +- c++/include/objects/seq/Seq_inst.hpp | 4 +- c++/include/objects/seq/Seq_literal.hpp | 7 +- .../objects/seq/seq_loc_mapper_base.hpp | 249 +- c++/include/objects/seq/sofa_map.hpp | 2 +- c++/include/objects/seqfeat/BioSource.hpp | 38 +- c++/include/objects/seqfeat/Delta_item.hpp | 94 + c++/include/objects/seqfeat/Gb_qual.hpp | 6 +- c++/include/objects/seqfeat/OrgMod.hpp | 13 +- c++/include/objects/seqfeat/SeqFeatData.hpp | 12 +- c++/include/objects/seqfeat/Seq_feat.hpp | 6 +- c++/include/objects/seqfeat/SubSource.hpp | 3 +- c++/include/objects/seqfeat/Trna_ext.hpp | 2 +- c++/include/objects/seqfeat/Variation_ref.hpp | 22 +- c++/include/objects/seqloc/Seq_loc.hpp | 18 +- c++/include/objects/seqset/Bioseq_set.hpp | 5 +- c++/include/objects/taxon1/Taxon2_data.hpp | 2 +- c++/include/objects/taxon1/taxon1.hpp | 7 +- .../objects/trackmgr/TMgr_ClientInfo.hpp | 2 +- .../objects/trackmgr/TMgr_DTrackId.hpp | 13 +- .../objects/trackmgr/displaytrack_client.hpp | 47 +- .../objects/trackmgr/gridrpcclient.hpp | 149 +- c++/include/objects/valerr/ValidErrItem.hpp | 20 +- c++/include/objects/valerr/ValidError.hpp | 6 +- c++/include/objects/valid/Comment_rule.hpp | 2 +- c++/include/objects/varrep/AaInterval.hpp | 90 + c++/include/objects/varrep/AaLocation.hpp | 90 + c++/include/objmgr/annot_selector.hpp | 49 +- c++/include/objmgr/annot_types_ci.hpp | 5 +- c++/include/objmgr/bioseq_handle.hpp | 2 +- c++/include/objmgr/data_loader.hpp | 2 +- c++/include/objmgr/impl/annot_collector.hpp | 97 +- .../objmgr/impl/annot_object_index.hpp | 8 +- c++/include/objmgr/impl/bioseq_base_info.hpp | 6 +- c++/include/objmgr/impl/bioseq_info.hpp | 2 +- c++/include/objmgr/impl/data_source.hpp | 2 +- c++/include/objmgr/impl/scope_impl.hpp | 2 +- c++/include/objmgr/impl/seq_annot_info.hpp | 56 +- c++/include/objmgr/impl/seq_entry_info.hpp | 43 +- c++/include/objmgr/impl/seq_id_sort.hpp | 2 +- c++/include/objmgr/impl/seq_table_info.hpp | 46 +- c++/include/objmgr/impl/seq_table_setters.hpp | 10 +- .../objmgr/impl/seq_vector_cvt_gen.hpp | 26 +- c++/include/objmgr/impl/snp_annot_info.hpp | 19 +- c++/include/objmgr/impl/snp_info.hpp | 20 +- c++/include/objmgr/impl/tse_info.hpp | 3 +- c++/include/objmgr/impl/tse_info_object.hpp | 5 +- c++/include/objmgr/impl/tse_split_info.hpp | 3 +- c++/include/objmgr/object_manager.hpp | 2 +- c++/include/objmgr/objmgr_exception.hpp | 2 +- c++/include/objmgr/scope.hpp | 2 +- c++/include/objmgr/seq_feat_handle.hpp | 39 +- c++/include/objmgr/seq_loc_mapper.hpp | 86 +- c++/include/objmgr/seq_map.hpp | 2 +- c++/include/objmgr/seq_map_ci.hpp | 2 +- c++/include/objmgr/seq_vector_ci.hpp | 17 +- c++/include/objmgr/split/size.hpp | 4 +- c++/include/objmgr/util/create_defline.hpp | 3 + c++/include/objmgr/util/feature.hpp | 11 +- c++/include/objmgr/util/obj_sniff.hpp | 23 +- c++/include/objmgr/util/seq_loc_util.hpp | 6 +- c++/include/objmgr/util/sequence.hpp | 46 +- .../align_format/align_format_util.hpp | 55 +- .../objtools/align_format/format_flags.hpp | 5 +- .../objtools/align_format/showalign.hpp | 12 +- .../objtools/align_format/showdefline.hpp | 32 +- c++/include/objtools/align_format/tabular.hpp | 33 +- .../objtools/align_format/taxFormat.hpp | 74 +- c++/include/objtools/alnmgr/sparse_aln.hpp | 29 +- .../blastdb_format/blastdb_dataextract.hpp | 84 +- .../blast/blastdb_format/blastdb_seqid.hpp | 2 +- .../blast/blastdb_format/seq_formatter.hpp | 197 + .../blast/blastdb_format/seq_writer.hpp | 6 +- .../blast/seqdb_reader/impl/seqdbatlas.hpp | 16 +- .../blast/seqdb_reader/impl/seqdbgeneral.hpp | 13 +- .../objtools/blast/seqdb_reader/seqdb.hpp | 5 +- .../objtools/blast/seqdb_writer/build_db.hpp | 15 +- .../blast/seqdb_writer/impl/criteria.hpp | 9 +- .../objtools/blast/seqdb_writer/writedb.hpp | 10 +- .../blast/services/blast_services.hpp | 7 +- c++/include/objtools/cleanup/cleanup.hpp | 94 +- .../objtools/cleanup/cleanup_change.hpp | 3 +- .../genbank/cache/writer_cache.hpp | 2 +- .../data_loaders/genbank/gbloader.hpp | 2 +- .../data_loaders/genbank/impl/dispatcher.hpp | 2 +- .../data_loaders/genbank/impl/info_cache.hpp | 8 +- .../genbank/impl/reader_id1_base.hpp | 2 +- .../genbank/impl/reader_id2_base.hpp | 25 +- .../genbank/impl/request_result.hpp | 2 +- .../objtools/data_loaders/genbank/reader.hpp | 2 +- .../data_loaders/genbank/reader_interface.hpp | 2 +- .../objtools/data_loaders/genbank/writer.hpp | 2 +- .../data_loaders/genbank/writer_interface.hpp | 2 +- c++/include/objtools/data_loaders/loaders.hpp | 2 +- c++/include/objtools/edit/apply_object.hpp | 2 +- c++/include/objtools/edit/autodef.hpp | 23 +- .../objtools/edit/autodef_feature_clause.hpp | 9 +- .../edit/autodef_feature_clause_base.hpp | 41 +- .../objtools/edit/autodef_mod_combo.hpp | 2 +- c++/include/objtools/edit/autodef_options.hpp | 12 +- c++/include/objtools/edit/cds_fix.hpp | 2 +- c++/include/objtools/edit/feattable_edit.hpp | 13 +- c++/include/objtools/edit/gaps_edit.hpp | 39 +- c++/include/objtools/edit/mail_report.hpp | 4 +- .../objtools/edit/publication_edit.hpp | 2 +- c++/include/objtools/edit/rna_edit.hpp | 11 +- c++/include/objtools/edit/seq_entry_edit.hpp | 2 +- c++/include/objtools/edit/seqid_guesser.hpp | 6 +- .../objtools/edit/string_constraint.hpp | 4 +- .../objtools/edit/struc_comm_field.hpp | 2 +- c++/include/objtools/error_codes.hpp | 2 +- c++/include/objtools/format/context.hpp | 17 +- .../objtools/format/flat_file_config.hpp | 61 +- c++/include/objtools/format/gather_items.hpp | 2 +- .../objtools/format/genbank_gather.hpp | 2 +- .../objtools/format/item_formatter.hpp | 5 +- .../objtools/format/items/comment_item.hpp | 9 +- .../objtools/format/items/feature_item.hpp | 21 +- .../objtools/format/items/flat_qual_slots.hpp | 3 +- .../objtools/format/items/gene_finder.hpp | 2 +- .../objtools/format/items/locus_item.hpp | 11 +- .../objtools/format/items/tsa_item.hpp | 2 +- c++/include/objtools/readers/aln_reader.hpp | 72 +- c++/include/objtools/readers/bed_reader.hpp | 92 +- c++/include/objtools/readers/fasta.hpp | 75 +- c++/include/objtools/readers/gff2_data.hpp | 14 +- c++/include/objtools/readers/gff2_reader.hpp | 98 +- c++/include/objtools/readers/gff3_reader.hpp | 7 +- c++/include/objtools/readers/gff3_sofa.hpp | 40 +- c++/include/objtools/readers/gtf_reader.hpp | 14 +- c++/include/objtools/readers/gvf_reader.hpp | 73 +- .../objtools/readers/microarray_reader.hpp | 8 +- c++/include/objtools/readers/reader_base.hpp | 14 +- c++/include/objtools/readers/readfeat.hpp | 15 - .../objtools/readers/source_mod_parser.hpp | 2 +- .../objtools/readers/struct_cmt_reader.hpp | 96 + c++/include/objtools/readers/track_data.hpp | 77 + c++/include/objtools/readers/vcf_reader.hpp | 6 +- .../objtools/readers/wiggle_reader.hpp | 4 +- c++/include/serial/impl/enumerated.hpp | 17 +- c++/include/serial/impl/objectiter.inl | 7 +- c++/include/serial/impl/objistrasnb.inl | 23 +- c++/include/serial/impl/objstack.hpp | 13 +- c++/include/serial/impl/objstack.inl | 21 +- c++/include/serial/impl/objstrasnb.inl | 4 +- c++/include/serial/impl/stdtypes.hpp | 12 +- c++/include/serial/objectiter.hpp | 3 +- c++/include/serial/objhook.hpp | 23 +- c++/include/serial/objistr.hpp | 5 +- c++/include/serial/objistrasnb.hpp | 3 +- c++/include/serial/objostr.hpp | 11 +- c++/include/serial/objostrxml.hpp | 4 +- c++/include/serial/rpcbase.hpp | 15 +- c++/include/serial/rpcbase_impl.hpp | 2 +- c++/include/serial/serialbase.hpp | 25 +- c++/include/serial/serialdef.hpp | 4 +- c++/include/serial/serialimpl.hpp | 6 +- c++/include/serial/typeinfo.hpp | 9 +- c++/include/util/align_range_coll.hpp | 14 +- c++/include/util/bitset/bm.h | 194 +- c++/include/util/bitset/bmalgo_impl.h | 37 + c++/include/util/bitset/bmalloc.h | 4 +- c++/include/util/bitset/bmblocks.h | 230 +- c++/include/util/bitset/bmconst.h | 10 +- c++/include/util/bitset/bmdbg.h | 10 +- c++/include/util/bitset/bmdef.h | 3 +- c++/include/util/bitset/bmfunc.h | 225 +- c++/include/util/bitset/bmrandom.h | 1 - c++/include/util/bitset/bmserial.h | 206 +- c++/include/util/bitset/bmsse2.h | 3 + c++/include/util/bitset/bmsse4.h | 18 +- c++/include/util/bitset/bmtrans.h | 40 +- c++/include/util/bitset/bmutil.h | 4 +- c++/include/util/bitset/bmvmin.h | 6 +- c++/include/util/bitset/encoding.h | 13 +- c++/include/util/bitset/ncbi_bitset_util.hpp | 2 +- c++/include/util/cache/icache_cf.hpp | 2 +- c++/include/util/compress/bzip2/bzlib.h | 71 +- c++/include/util/file_manifest.hpp | 2 +- c++/include/util/format_guess.hpp | 47 +- c++/include/util/id_mux.hpp | 6 +- c++/include/util/rangemap.hpp | 10 +- c++/include/util/resize_iter.hpp | 21 +- c++/include/util/resource_pool.hpp | 4 +- c++/include/util/simple_buffer.hpp | 17 +- c++/include/util/static_set.hpp | 16 +- c++/include/util/stream_source.hpp | 4 +- c++/include/util/strsearch.hpp | 4 +- c++/include/util/table_printer.hpp | 4 +- c++/include/util/tables/raw_scoremat.h | 4 +- c++/include/util/timsort.hpp | 666 + c++/include/util/value_convert.hpp | 2 +- c++/include/util/value_convert_policy.hpp | 2 +- c++/scripts/common/add_vdb.sh | 10 +- c++/scripts/common/check/check_add.sh | 11 +- c++/scripts/common/check/check_make_cfg.sh | 2 +- c++/scripts/common/check/check_make_unix.sh | 9 +- .../common/check/inspxe-suppressions/_vs.sup | 54 +- .../check/inspxe-suppressions/connect.sup | 14 + .../check/inspxe-suppressions/corelib.sup | 24 + .../common/check/inspxe-suppressions/misc.sup | 41 + c++/scripts/common/check/inspxe.sh | 2 +- c++/scripts/common/check/valgrind.supp | 25 +- c++/scripts/common/impl/compress_tests.sh | 2 +- c++/scripts/common/impl/install.sh | 2 +- c++/scripts/common/impl/python-config.py | 25 + c++/scripts/common/new_project.sh | 5 +- c++/scripts/common/new_project.wsf | 3 + c++/scripts/common/new_project_msvc7.bat | 45 - c++/scripts/common/project_utilits.js | 91 +- c++/scripts/projects/blast/LICENSE | 505 + c++/scripts/projects/blast/Manifest | 24 +- c++/scripts/projects/blast/components.link | 16 +- .../projects/blast/post_build/blast_utils.py | 8 +- .../blast/post_build/macosx/ncbi-blast.sh | 5 +- .../blast/post_build/make_installers.py | 26 +- .../projects/blast/post_build/win/make_win.py | 11 +- .../blast/post_build/win/ncbi-blast.nsi | 12 + c++/scripts/projects/blast/project.lst | 3 + c++/scripts/projects/cobalt/Manifest | 2 +- c++/scripts/projects/datatool/ChangeLog | 4 +- c++/scripts/projects/datatool/Manifest | 4 +- c++/scripts/projects/dispatcher/Manifest | 4 +- c++/scripts/projects/gumbel_params/Manifest | 2 +- c++/scripts/projects/igblast/ChangeLog | 10 + c++/scripts/projects/igblast/LICENSE | 505 + c++/scripts/projects/igblast/Manifest | 17 +- c++/scripts/projects/igblast/README | 17 +- c++/scripts/projects/igblast/components.link | 16 +- .../igblast/post_build/blast_utils.py | 15 +- .../igblast/post_build/make_installers.py | 37 +- .../igblast/post_build/win/make_win.py | 11 +- .../igblast/post_build/win/ncbi-blast.nsi | 6 + c++/scripts/projects/igblast/project.lst | 3 + c++/scripts/projects/magicblast/ChangeLog | 11 + c++/scripts/projects/magicblast/LICENSE | 524 + c++/scripts/projects/magicblast/Manifest | 50 + c++/scripts/projects/magicblast/README | 170 + .../projects/magicblast/components.link | 9 + .../magicblast/post_build/blast_utils.py | 128 + .../macosx/large-Blue_ncbi_logo.tiff | Bin 0 -> 5536538 bytes .../post_build/macosx/ncbi-magicblast.sh | 86 + .../macosx/uninstall_ncbi_magicblast.zip | Bin 0 -> 58778 bytes .../magicblast/post_build/macosx/welcome.txt | 2 + .../magicblast/post_build/make_installers.py | 112 + .../magicblast/post_build/rpm/make_rpm.py | 173 + .../post_build/rpm/ncbi-magicblast.spec | 41 + .../post_build/win/EnvVarUpdate.nsh | 568 + .../magicblast/post_build/win/make_win.py | 91 + .../magicblast/post_build/win/ncbi-blast.nsi | 102 + .../magicblast/post_build/win/ncbilogo.ico | Bin 0 -> 25214 bytes .../magicblast/post_build/win/unix2dos.nsh | 56 + c++/scripts/projects/magicblast/project.lst | 85 + c++/scripts/projects/ncbi_applog/ChangeLog | 20 +- c++/scripts/projects/ncbi_applog/Manifest | 6 +- c++/scripts/projects/ncbi_applog/project.lst | 2 + c++/scripts/projects/ncbi_gui_base.lst | 1 + c++/scripts/projects/netcache/ChangeLog | 35 + c++/scripts/projects/netschedule/ChangeLog | 39 + c++/scripts/projects/netschedule/Manifest | 9 +- c++/scripts/projects/netstorage/Manifest | 4 +- .../projects/netstorage/components.link | 9 +- c++/scripts/projects/netstorage/project.lst | 1 - .../projects/netstorage_gc/project.lst | 9 + .../projects/project_tree_builder/ChangeLog | 8 + .../projects/project_tree_builder/Manifest | 5 +- c++/scripts/projects/public/Manifest | 31 +- c++/scripts/projects/public/components.link | 23 +- .../projects/python_ncbi_dbapi/ChangeLog | 8 + .../python_ncbi_dbapi/components.link | 6 +- .../projects/python_ncbi_dbapi/project.lst | 10 + c++/scripts/projects/rmblastn/Manifest | 4 +- c++/scripts/projects/testres-kernel/ChangeLog | 7 +- c++/scripts/projects/testres-kernel/Manifest | 7 +- .../projects/testres-kernel/components.link | 6 +- .../projects/testres-scheduler/ChangeLog | 3 + .../projects/testres-scheduler/Manifest | 6 +- .../testres-scheduler/components.link | 6 +- c++/scripts/projects/xmlwrapp/Manifest | 18 +- c++/src/Makefile.in | 2 +- c++/src/algo/blast/Makefile.blast_macros.mk | 8 +- c++/src/algo/blast/Makefile.in | 6 +- c++/src/algo/blast/api/Makefile.xblast.lib | 6 +- .../blast/api/bioseq_extract_data_priv.cpp | 51 +- .../blast/api/bioseq_extract_data_priv.hpp | 9 +- c++/src/algo/blast/api/blast_aux.cpp | 68 +- c++/src/algo/blast/api/blast_aux_priv.cpp | 8 +- c++/src/algo/blast/api/blast_mtlock.cpp | 7 +- c++/src/algo/blast/api/blast_nucl_options.cpp | 4 +- c++/src/algo/blast/api/blast_objmgr_priv.hpp | 13 +- c++/src/algo/blast/api/blast_objmgr_tools.cpp | 4 - .../algo/blast/api/blast_options_builder.cpp | 29 +- c++/src/algo/blast/api/blast_options_cxx.cpp | 119 +- .../algo/blast/api/blast_options_handle.cpp | 43 +- .../blast/api/blast_options_local_priv.cpp | 7 +- .../blast/api/blast_options_local_priv.hpp | 99 +- c++/src/algo/blast/api/blast_results.cpp | 7 +- c++/src/algo/blast/api/blast_seqalign.cpp | 232 +- c++/src/algo/blast/api/blast_seqalign.hpp | 23 +- .../algo/blast/api/blast_seqinfosrc_aux.cpp | 45 +- c++/src/algo/blast/api/blast_setup.hpp | 8 +- c++/src/algo/blast/api/blast_setup_cxx.cpp | 65 +- c++/src/algo/blast/api/cdd_pssm_input.cpp | 8 +- c++/src/algo/blast/api/deltablast.cpp | 10 +- c++/src/algo/blast/api/dust_filter.cpp | 7 +- c++/src/algo/blast/api/local_blast.cpp | 5 +- c++/src/algo/blast/api/local_db_adapter.cpp | 4 - c++/src/algo/blast/api/local_search.cpp | 4 - c++/src/algo/blast/api/magicblast.cpp | 346 + c++/src/algo/blast/api/magicblast_options.cpp | 224 + c++/src/algo/blast/api/msa_pssm_input.cpp | 4 - c++/src/algo/blast/api/objmgr_query_data.cpp | 4 - .../algo/blast/api/objmgrfree_query_data.cpp | 4 - .../algo/blast/api/prelim_search_runner.hpp | 19 +- c++/src/algo/blast/api/prelim_stage.cpp | 4 - c++/src/algo/blast/api/psi_pssm_input.cpp | 4 - c++/src/algo/blast/api/psibl2seq.cpp | 4 - c++/src/algo/blast/api/psiblast.cpp | 4 - c++/src/algo/blast/api/psiblast_aux_priv.cpp | 4 - c++/src/algo/blast/api/psiblast_impl.cpp | 4 - c++/src/algo/blast/api/psiblast_iteration.cpp | 4 - c++/src/algo/blast/api/pssm_engine.cpp | 4 - c++/src/algo/blast/api/query_data.cpp | 4 - c++/src/algo/blast/api/remote_blast.cpp | 21 +- c++/src/algo/blast/api/remote_search.cpp | 4 - c++/src/algo/blast/api/repeats_filter_cxx.cpp | 7 +- c++/src/algo/blast/api/rps_aux.cpp | 4 - c++/src/algo/blast/api/rpstblastn_options.cpp | 4 +- c++/src/algo/blast/api/seedtop.cpp | 4 +- c++/src/algo/blast/api/seqinfosrc_bioseq.cpp | 4 - c++/src/algo/blast/api/seqinfosrc_bioseq.hpp | 2 +- c++/src/algo/blast/api/seqinfosrc_seqdb.cpp | 4 - c++/src/algo/blast/api/seqinfosrc_seqvec.cpp | 4 - c++/src/algo/blast/api/seqsrc_seqdb.cpp | 231 +- c++/src/algo/blast/api/setup_factory.cpp | 31 +- .../algo/blast/api/split_query_aux_priv.cpp | 8 +- c++/src/algo/blast/api/split_query_blk.cpp | 4 - c++/src/algo/blast/api/split_query_cxx.cpp | 4 - c++/src/algo/blast/api/traceback_stage.cpp | 4 - c++/src/algo/blast/api/uniform_search.cpp | 4 - c++/src/algo/blast/api/winmask_filter.cpp | 7 +- .../blast/blastinput/Makefile.blastinput.lib | 9 +- c++/src/algo/blast/blastinput/Makefile.in | 2 +- c++/src/algo/blast/blastinput/blast_args.cpp | 417 +- .../blast/blastinput/blast_asn1_input.cpp | 365 + .../blast/blastinput/blast_fasta_input.cpp | 734 +- c++/src/algo/blast/blastinput/blast_input.cpp | 33 +- .../algo/blast/blastinput/blast_input_aux.cpp | 45 +- .../algo/blast/blastinput/blast_scope_src.cpp | 29 +- c++/src/algo/blast/blastinput/blastn_args.cpp | 7 +- c++/src/algo/blast/blastinput/blastp_args.cpp | 7 +- c++/src/algo/blast/blastinput/blastx_args.cpp | 7 +- .../algo/blast/blastinput/cmdline_flags.cpp | 31 +- .../algo/blast/blastinput/deltablast_args.cpp | 7 +- .../algo/blast/blastinput/igblastn_args.cpp | 9 +- .../algo/blast/blastinput/igblastp_args.cpp | 7 +- .../algo/blast/blastinput/kblastp_args.cpp | 105 + .../algo/blast/blastinput/magicblast_args.cpp | 278 + .../algo/blast/blastinput/psiblast_args.cpp | 9 +- .../algo/blast/blastinput/rmblastn_args.cpp | 7 +- .../algo/blast/blastinput/rpsblast_args.cpp | 7 +- .../algo/blast/blastinput/rpstblastn_args.cpp | 15 +- .../algo/blast/blastinput/tblastn_args.cpp | 7 +- .../algo/blast/blastinput/tblastx_args.cpp | 7 +- .../Makefile.blastinput_unit_test.app | 4 +- .../unit_test/blast_input_unit_test_aux.hpp | 37 +- .../unit_test/blast_scope_src_unit_test.cpp | 14 +- .../unit_test/blastinput_unit_test.cpp | 326 +- .../unit_test/data/paired_reads.asn | 84 + .../blastinput/unit_test/data/paired_reads.fa | 12 + .../unit_test/data/paired_reads.fastq | 24 + .../unit_test/data/paired_reads_1.asn | 42 + .../unit_test/data/paired_reads_1.fa | 6 + .../unit_test/data/paired_reads_1.fastq | 12 + .../unit_test/data/paired_reads_2.asn | 42 + .../unit_test/data/paired_reads_2.fa | 6 + .../unit_test/data/paired_reads_2.fastq | 12 + .../blast/composition_adjustment/compo_heap.c | 5 - .../compo_mode_condition.c | 5 - .../composition_adjustment.c | 18 +- .../matrix_frequency_data.c | 4 - .../nlm_linear_algebra.c | 4 - .../optimize_target_freq.c | 4 - .../composition_adjustment/redo_alignment.c | 52 +- .../composition_adjustment/smith_waterman.c | 4 - .../composition_adjustment/unified_pvalues.c | 4 - c++/src/algo/blast/core/Makefile.blast.lib | 8 +- c++/src/algo/blast/core/aa_ungapped.c | 7 +- c++/src/algo/blast/core/blast_aalookup.c | 7 +- c++/src/algo/blast/core/blast_aascan.c | 7 +- c++/src/algo/blast/core/blast_diagnostics.c | 7 +- c++/src/algo/blast/core/blast_dynarray.c | 7 +- c++/src/algo/blast/core/blast_encoding.c | 7 +- c++/src/algo/blast/core/blast_engine.c | 812 +- c++/src/algo/blast/core/blast_extend.c | 7 +- c++/src/algo/blast/core/blast_filter.c | 20 +- c++/src/algo/blast/core/blast_gapalign.c | 1133 +- c++/src/algo/blast/core/blast_hits.c | 195 +- c++/src/algo/blast/core/blast_hspstream.c | 39 +- .../blast/core/blast_hspstream_mt_utils.c | 7 +- .../blast/core/blast_hspstream_mt_utils.h | 2 +- c++/src/algo/blast/core/blast_itree.c | 7 +- c++/src/algo/blast/core/blast_kappa.c | 714 +- c++/src/algo/blast/core/blast_lookup.c | 198 +- c++/src/algo/blast/core/blast_message.c | 7 +- c++/src/algo/blast/core/blast_nalookup.c | 937 +- c++/src/algo/blast/core/blast_nascan.c | 368 +- c++/src/algo/blast/core/blast_options.c | 144 +- c++/src/algo/blast/core/blast_parameters.c | 26 +- c++/src/algo/blast/core/blast_posit.c | 4 - c++/src/algo/blast/core/blast_program.c | 16 +- c++/src/algo/blast/core/blast_psi.c | 4 - c++/src/algo/blast/core/blast_psi_priv.c | 4 - c++/src/algo/blast/core/blast_query_info.c | 27 +- c++/src/algo/blast/core/blast_seg.c | 2730 +-- c++/src/algo/blast/core/blast_seqsrc.c | 9 +- c++/src/algo/blast/core/blast_setup.c | 93 +- c++/src/algo/blast/core/blast_stat.c | 8 +- c++/src/algo/blast/core/blast_sw.c | 10 +- c++/src/algo/blast/core/blast_traceback.c | 29 +- .../algo/blast/core/blast_traceback_mt_priv.c | 7 +- c++/src/algo/blast/core/blast_tune.c | 7 +- c++/src/algo/blast/core/blast_util.c | 27 +- c++/src/algo/blast/core/boost_erf.c | 2 +- c++/src/algo/blast/core/boost_erf.h | 2 +- c++/src/algo/blast/core/gapinfo.c | 7 +- c++/src/algo/blast/core/gencode_singleton.c | 7 +- c++/src/algo/blast/core/greedy_align.c | 8 +- c++/src/algo/blast/core/hspfilter_besthit.c | 18 +- c++/src/algo/blast/core/hspfilter_collector.c | 15 +- c++/src/algo/blast/core/hspfilter_culling.c | 15 +- c++/src/algo/blast/core/hspfilter_mapper.c | 4353 ++++ c++/src/algo/blast/core/jumper.c | 4025 ++++ c++/src/algo/blast/core/jumper.h | 279 + c++/src/algo/blast/core/link_hsps.c | 7 +- c++/src/algo/blast/core/lookup_util.c | 9 +- c++/src/algo/blast/core/lookup_wrap.c | 29 +- c++/src/algo/blast/core/matrix_freq_ratios.c | 4 - c++/src/algo/blast/core/na_ungapped.c | 545 +- c++/src/algo/blast/core/ncbi_math.c | 7 +- c++/src/algo/blast/core/ncbi_std.c | 7 +- c++/src/algo/blast/core/pattern.c | 7 +- c++/src/algo/blast/core/phi_extend.c | 7 +- c++/src/algo/blast/core/phi_gapalign.c | 8 +- c++/src/algo/blast/core/phi_lookup.c | 8 +- c++/src/algo/blast/core/split_query.c | 7 +- .../algo/blast/dbindex/dbindex_factory.cpp | 40 +- c++/src/algo/blast/dbindex/makeindex/main.cpp | 4 +- c++/src/algo/blast/format/blast_format.cpp | 153 +- c++/src/algo/blast/format/blastfmtutil.cpp | 16 +- c++/src/algo/blast/format/blastxml_format.cpp | 8 +- c++/src/algo/blast/format/data4xmlformat.cpp | 4 - c++/src/algo/blast/format/sam.cpp | 5 +- c++/src/algo/blast/format/vecscreen_run.cpp | 4 - c++/src/algo/blast/igblast/igblast.cpp | 74 +- .../api/Makefile.aalookup_unit_test.app | 2 +- .../api/Makefile.aascan_unit_test.app | 2 +- .../api/Makefile.bl2seq_unit_test.app | 4 +- .../api/Makefile.blast_unit_test.app | 4 +- .../api/Makefile.blast_unit_test_util.lib | 2 +- .../api/Makefile.blastdiag_unit_test.app | 2 +- .../api/Makefile.blastengine_unit_test.app | 2 +- .../api/Makefile.blastextend_unit_test.app | 2 +- .../api/Makefile.blastfilter_unit_test.app | 2 +- .../api/Makefile.blasthits_unit_test.app | 2 +- .../api/Makefile.blastoptions_unit_test.app | 2 +- .../api/Makefile.blastsetup_unit_test.app | 2 +- .../api/Makefile.delta_unit_test.app | 2 +- .../api/Makefile.gapinfo_unit_test.app | 2 +- .../Makefile.gencode_singleton_unit_test.app | 2 +- .../Makefile.hspfilter_besthit_unit_test.app | 4 +- .../Makefile.hspfilter_culling_unit_test.app | 4 +- .../api/Makefile.hspstream_unit_test.app | 4 +- c++/src/algo/blast/unit_tests/api/Makefile.in | 7 +- .../api/Makefile.linkhsp_unit_test.app | 4 +- .../api/Makefile.magicblast_unit_test.app | 16 + .../api/Makefile.msa2pssm_unit_test.app | 4 +- .../api/Makefile.ntlookup_unit_test.app | 6 +- .../api/Makefile.ntscan_unit_test.app | 2 +- .../api/Makefile.optionshandle_unit_test.app | 4 +- .../api/Makefile.phiblast_unit_test.app | 4 +- .../api/Makefile.prelimsearch_unit_test.app | 2 +- .../api/Makefile.psibl2seq_unit_test.app | 4 +- .../Makefile.psiblast_iteration_unit_test.app | 4 +- .../api/Makefile.psiblast_unit_test.app | 4 +- .../api/Makefile.pssmcreate_unit_test.app | 2 +- ...akefile.pssmenginefreqratios_unit_test.app | 2 +- .../api/Makefile.querydata_unit_test.app | 4 +- .../api/Makefile.queryinfo_unit_test.app | 4 +- .../api/Makefile.redoalignment_unit_test.app | 8 +- .../api/Makefile.remote_blast_unit_test.app | 2 +- .../unit_tests/api/Makefile.rps_unit_test.app | 2 +- .../api/Makefile.scoreblk_unit_test.app | 2 +- .../Makefile.search_strategy_unit_test.app | 2 +- .../unit_tests/api/Makefile.seqalign_util.lib | 2 +- .../api/Makefile.seqinfosrc_unit_test.app | 2 +- .../api/Makefile.seqsrc_unit_test.app | 2 +- .../api/Makefile.setupfactory_unit_test.app | 2 +- .../api/Makefile.split_query_unit_test.app | 2 +- .../api/Makefile.stat_unit_test.app | 2 +- .../api/Makefile.subj_ranges_unit_test.app | 4 +- .../api/Makefile.traceback_unit_test.app | 2 +- .../Makefile.tracebacksearch_unit_test.app | 2 +- .../api/Makefile.uniform_search_unit_test.app | 2 +- .../Makefile.version_reference_unit_test.app | 6 +- .../unit_tests/api/aalookup_unit_test.cpp | 3 +- .../blast/unit_tests/api/aascan_unit_test.cpp | 3 +- .../blast/unit_tests/api/bl2seq_unit_test.cpp | 12 +- .../unit_tests/api/blastdiag_unit_test.cpp | 4 +- .../unit_tests/api/blastengine_unit_test.cpp | 24 +- .../unit_tests/api/blastfilter_unit_test.cpp | 15 +- .../unit_tests/api/blasthits_unit_test.cpp | 474 +- .../unit_tests/api/blastoptions_unit_test.cpp | 5 +- .../unit_tests/api/blastsetup_unit_test.cpp | 14 +- .../unit_tests/api/data/magicblast_paired.asn | 50 + .../api/data/magicblast_queries.asn | 74 + .../algo/blast/unit_tests/api/data/pombe.nhr | Bin 0 -> 124 bytes .../algo/blast/unit_tests/api/data/pombe.nin | Bin 0 -> 128 bytes .../algo/blast/unit_tests/api/data/pombe.nog | Bin 0 -> 36 bytes .../algo/blast/unit_tests/api/data/pombe.nsd | 2 + .../algo/blast/unit_tests/api/data/pombe.nsi | Bin 0 -> 64 bytes .../algo/blast/unit_tests/api/data/pombe.nsq | Bin 0 -> 613250 bytes .../blast/unit_tests/api/delta_unit_test.cpp | 14 +- .../api/hspfilter_besthit_unit_test.cpp | 4 +- .../api/hspfilter_culling_unit_test.cpp | 4 +- .../unit_tests/api/hspstream_unit_test.cpp | 6 +- .../unit_tests/api/linkhsp_unit_test.cpp | 4 +- .../unit_tests/api/magicblast_unit_test.cpp | 447 + .../unit_tests/api/magicblast_unit_test.ini | 3 + .../unit_tests/api/ntlookup_unit_test.cpp | 199 +- .../unit_tests/api/ntlookup_unit_test.ini | 4 +- .../blast/unit_tests/api/ntscan_unit_test.cpp | 3 +- .../unit_tests/api/phiblast_unit_test.cpp | 4 +- .../api/psiblast_iteration_unit_test.cpp | 18 +- .../unit_tests/api/psiblast_unit_test.cpp | 2 +- .../unit_tests/api/querydata_unit_test.cpp | 48 +- .../unit_tests/api/queryinfo_unit_test.cpp | 74 +- .../api/redoalignment_unit_test.cpp | 4 +- .../unit_tests/api/remote_blast_unit_test.cpp | 4 +- .../blast/unit_tests/api/rps_unit_test.cpp | 10 +- .../unit_tests/api/split_query_unit_test.cpp | 4 +- .../blast/unit_tests/api/stat_unit_test.cpp | 2 +- .../blast/unit_tests/api/stat_unit_test.ini | 3 + .../unit_tests/api/traceback_unit_test.cpp | 10 +- .../api/tracebacksearch_unit_test.cpp | 95 +- .../api/version_reference_unit_test.cpp | 4 +- .../Makefile.blast_format_unit_test.app | 4 +- .../blast_format/blastfmtutil_unit_test.cpp | 4 +- .../blast_format/vecscreen_run_unit_test.cpp | 8 +- .../blastdb/Makefile.bdbloader_unit_test.app | 5 +- .../seqdb_reader/Makefile.seqdb_unit_test.app | 2 +- .../seqdb_reader/seqdb_unit_test.cpp | 15 +- .../seqdb_reader/seqdb_unit_test.ini | 10 +- c++/src/app/Makefile.in | 8 +- c++/src/app/blast/Makefile.blastn.app | 5 +- c++/src/app/blast/Makefile.in | 2 +- c++/src/app/blast/blast_app_util.cpp | 143 +- c++/src/app/blast/blast_app_util.hpp | 10 +- c++/src/app/blast/blast_formatter.cpp | 12 +- c++/src/app/blast/blastn_app.cpp | 10 +- c++/src/app/blast/blastp_app.cpp | 10 +- c++/src/app/blast/blastx_app.cpp | 10 +- c++/src/app/blast/deltablast_app.cpp | 21 +- c++/src/app/blast/psiblast_app.cpp | 18 +- c++/src/app/blast/rpsblast_app.cpp | 12 +- c++/src/app/blast/rpstblastn_app.cpp | 12 +- c++/src/app/blast/seedtop_app.cpp | 9 +- c++/src/app/blast/tblastn_app.cpp | 13 +- c++/src/app/blast/tblastx_app.cpp | 10 +- c++/src/app/blast/update_blastdb.pl | 4 +- .../blastdb/Makefile.convert2blastmask.app | 2 +- c++/src/app/blastdb/Makefile.makeblastdb.app | 2 +- .../app/blastdb/Makefile.makeprofiledb.app | 2 +- c++/src/app/blastdb/blastdb_aliastool.cpp | 64 +- c++/src/app/blastdb/blastdbcheck.cpp | 4 +- c++/src/app/blastdb/blastdbcmd.cpp | 589 +- c++/src/app/blastdb/blastdbcp.cpp | 4 +- c++/src/app/blastdb/convert2blastmask.cpp | 4 +- c++/src/app/blastdb/makeblastdb.cpp | 25 +- c++/src/app/blastdb/makeprofiledb.cpp | 4 +- .../app/dustmasker/Makefile.dustmasker.app | 4 +- c++/src/app/dustmasker/main.cpp | 4 +- c++/src/app/segmasker/Makefile.segmasker.app | 4 +- c++/src/app/segmasker/segmasker.cpp | 4 +- c++/src/app/winmasker/Makefile.winmasker.app | 6 +- c++/src/app/winmasker/main.cpp | 4 +- c++/src/build-system/Makefile.app.in | 2 +- c++/src/build-system/Makefile.meta_l | 4 +- c++/src/build-system/Makefile.mk.in | 41 +- c++/src/build-system/Makefile.rules.in | 4 +- c++/src/build-system/NEWS | 2 + c++/src/build-system/aclocal.m4 | 14 +- c++/src/build-system/config.h.in | 33 +- c++/src/build-system/configure | 1433 +- c++/src/build-system/configure.ac | 493 +- c++/src/build-system/datatool_version.txt | 2 +- .../helpers/Makefile.run_with_lock.app | 2 +- c++/src/build-system/helpers/run_with_lock.c | 22 +- c++/src/build-system/install.sh.in | 2 +- c++/src/build-system/library_relations.txt | 439 +- c++/src/build-system/ncbi_package_version | 2 +- c++/src/build-system/project_tree_builder.ini | 147 +- .../msvc_prj_generator.cpp | 2 +- .../project_tree_builder/msvc_prj_utils.cpp | 14 +- .../project_tree_builder/msvc_prj_utils.hpp | 3 +- .../project_tree_builder/proj_builder_app.cpp | 19 +- .../proj_tree_builder.cpp | 292 +- c++/src/build-system/ptb_version.txt | 2 +- c++/src/build-system/relocate.sh.in | 2 +- c++/src/cgi/cgiapp.cpp | 18 +- c++/src/cgi/cgictx.cpp | 23 +- c++/src/cgi/fcgi_run.cpp | 8 +- c++/src/cgi/ncbicgi.cpp | 2 +- c++/src/cgi/ncbicgir.cpp | 10 +- c++/src/cgi/user_agent.cpp | 11 +- c++/src/connect/Makefile.connect.lib | 6 +- c++/src/connect/Makefile.connect.lib.unix | 3 +- c++/src/connect/Makefile.connssl.lib | 10 +- c++/src/connect/Makefile.xconnect.lib | 6 +- c++/src/connect/Makefile.xthrserv.lib | 6 +- c++/src/connect/Makefile.xxconnect.lib | 11 +- c++/src/connect/connection_pool.cpp | 176 +- c++/src/connect/connection_pool.hpp | 37 +- c++/src/connect/ncbi_buffer.c | 44 +- c++/src/connect/ncbi_comm.h | 40 +- c++/src/connect/ncbi_conn_stream.cpp | 16 +- c++/src/connect/ncbi_conn_test.cpp | 67 +- c++/src/connect/ncbi_connection.c | 21 +- c++/src/connect/ncbi_connector.c | 41 +- c++/src/connect/ncbi_connutil.c | 173 +- c++/src/connect/ncbi_core.c | 10 +- c++/src/connect/ncbi_core_cxx.cpp | 237 +- c++/src/connect/ncbi_dispd.c | 8 +- c++/src/connect/ncbi_ftp_connector.c | 196 +- c++/src/connect/ncbi_gnutls.c | 43 +- c++/src/connect/ncbi_http_connector.c | 31 +- c++/src/connect/ncbi_http_session.cpp | 184 +- c++/src/connect/ncbi_lbos.c | 1067 +- c++/src/connect/ncbi_lbos.h | 11 +- c++/src/connect/ncbi_lbos_cxx.cpp | 583 +- c++/src/connect/ncbi_lbosp.h | 95 +- c++/src/connect/ncbi_lbosp.hpp | 71 +- c++/src/connect/ncbi_monkey.cpp | 1681 ++ c++/src/connect/ncbi_monkeyp.hpp | 81 + c++/src/connect/ncbi_priv.c | 30 +- c++/src/connect/ncbi_priv.h | 94 +- c++/src/connect/ncbi_server_info.c | 57 +- c++/src/connect/ncbi_service.c | 22 +- c++/src/connect/ncbi_service_connector.c | 27 +- c++/src/connect/ncbi_socket.c | 249 +- c++/src/connect/ncbi_util.c | 6 +- c++/src/connect/parson.c | 1767 ++ c++/src/connect/parson.h | 223 + c++/src/connect/server.cpp | 139 +- .../connect/services/Makefile.xconnserv.lib | 4 +- c++/src/connect/services/grid_client.cpp | 2 +- .../connect/services/grid_control_thread.cpp | 2 +- c++/src/connect/services/grid_worker.cpp | 44 +- c++/src/connect/services/grid_worker_app.cpp | 2 +- c++/src/connect/services/grid_worker_impl.hpp | 8 +- c++/src/connect/services/json_over_uttp.cpp | 300 +- c++/src/connect/services/netcache_api.cpp | 6 +- .../connect/services/netcache_api_impl.hpp | 16 +- c++/src/connect/services/netcache_rw.cpp | 2 +- c++/src/connect/services/netcache_search.cpp | 556 + c++/src/connect/services/neticache_client.cpp | 35 +- c++/src/connect/services/netschedule_api.cpp | 134 +- .../services/netschedule_api_admin.cpp | 2 +- .../services/netschedule_api_executor.cpp | 97 +- .../services/netschedule_api_getjob.cpp | 55 +- .../services/netschedule_api_getjob.hpp | 6 +- .../connect/services/netschedule_api_impl.hpp | 37 +- .../services/netschedule_api_reader.cpp | 14 +- .../services/netschedule_api_submitter.cpp | 8 +- c++/src/connect/services/netservice_api.cpp | 5 +- .../connect/services/netservice_api_impl.hpp | 2 +- c++/src/connect/services/netstorage.cpp | 11 +- .../connect/services/netstorage_direct_nc.cpp | 7 +- .../connect/services/netstorage_direct_nc.hpp | 2 +- c++/src/connect/services/netstorage_rpc.cpp | 77 +- c++/src/connect/services/netstorage_rpc.hpp | 15 +- .../connect/services/netstorageobjectinfo.cpp | 19 +- .../connect/services/netstorageobjectloc.cpp | 2 +- c++/src/connect/services/ns_output_parser.cpp | 242 +- c++/src/connect/services/srv_connections.cpp | 2 +- c++/src/connect/services/tmp_wn_info.cpp | 22 +- c++/src/connect/services/wn_main_loop.cpp | 5 +- c++/src/corelib/ddumpable.cpp | 2 +- c++/src/corelib/env_reg.cpp | 13 +- c++/src/corelib/expr.cpp | 4 +- c++/src/corelib/ncbi_cookies.cpp | 16 +- c++/src/corelib/ncbi_param.cpp | 54 +- c++/src/corelib/ncbi_stack.cpp | 13 +- c++/src/corelib/ncbi_stack_linux.cpp | 11 +- c++/src/corelib/ncbi_stack_solaris.cpp | 4 +- c++/src/corelib/ncbi_stack_win32.cpp | 4 +- c++/src/corelib/ncbi_stack_win64.cpp | 4 +- c++/src/corelib/ncbi_system.cpp | 9 +- c++/src/corelib/ncbi_url.cpp | 4 +- c++/src/corelib/ncbiapp.cpp | 142 +- c++/src/corelib/ncbiargs.cpp | 280 +- c++/src/corelib/ncbidiag.cpp | 270 +- c++/src/corelib/ncbidiag_p.hpp | 4 +- c++/src/corelib/ncbienv.cpp | 4 +- c++/src/corelib/ncbierror.cpp | 185 +- c++/src/corelib/ncbifile.cpp | 141 +- c++/src/corelib/ncbimtx.cpp | 16 +- c++/src/corelib/ncbireg.cpp | 66 +- c++/src/corelib/ncbistr.cpp | 137 +- c++/src/corelib/ncbitime.cpp | 16 +- c++/src/corelib/request_ctx.cpp | 71 +- c++/src/corelib/stream_utils.cpp | 9 +- c++/src/corelib/teamcity_boost.cpp | 150 +- c++/src/corelib/teamcity_messages.cpp | 101 +- c++/src/corelib/teamcity_messages.h | 32 +- c++/src/corelib/test_boost.cpp | 51 +- c++/src/corelib/version.cpp | 10 +- c++/src/dbapi/blobstream.cpp | 4 +- c++/src/dbapi/blobstream.hpp | 4 +- c++/src/dbapi/conn_impl.cpp | 6 +- c++/src/dbapi/dbapi.cpp | 4 +- c++/src/dbapi/driver/dbapi_conn_factory.cpp | 40 +- .../dbapi/driver/dbapi_driver_conn_mgr.cpp | 2 +- .../dbapi/driver/dbapi_driver_conn_params.cpp | 3 +- c++/src/dbapi/driver/dbapi_driver_utils.cpp | 33 +- c++/src/dbapi/driver/dbapi_impl_cmd.cpp | 2 +- .../dbapi/driver/dbapi_impl_connection.cpp | 13 +- c++/src/dbapi/driver/dbapi_impl_context.cpp | 75 +- c++/src/dbapi/driver/dbapi_object_convert.cpp | 2 +- c++/src/dbapi/driver/dbapi_svc_mapper.cpp | 26 +- c++/src/dbapi/driver/interfaces.cpp | 6 +- c++/src/dbapi/driver/memory_store.cpp | 2 +- c++/src/dbapi/driver/memory_store.hpp | 2 +- c++/src/dbapi/driver/odbc/bcp.cpp | 2 +- c++/src/dbapi/driver/odbc/connection.cpp | 23 +- c++/src/dbapi/driver/odbc/cursor.cpp | 2 +- c++/src/dbapi/driver/odbc/result.cpp | 2 +- c++/src/dbapi/driver/public.cpp | 2 +- c++/src/dbapi/driver/types.cpp | 2 +- c++/src/dbapi/driver_mgr.cpp | 4 +- c++/src/dbapi/rs_impl.cpp | 4 +- c++/src/dbapi/rw_impl.cpp | 2 +- c++/src/dbapi/rw_impl.hpp | 2 +- c++/src/dbapi/stmt_impl.cpp | 4 +- c++/src/dbapi/stmt_impl.hpp | 4 +- c++/src/dbapi/variant.cpp | 4 +- c++/src/html/indentstream.cpp | 4 +- c++/src/html/selection.cpp | 4 +- c++/src/misc/CMakeLists.txt | 22 + c++/src/misc/Makefile.in | 10 + c++/src/misc/third_party/CMakeLists.txt | 6 + c++/src/misc/third_party/Makefile.in | 10 + .../Makefile.third_party_dll_install.msvcproj | 11 + ...file.third_party_dll_install.msvcproj.msvc | 4 + ...efile.third_party_msvcdll_install.msvcproj | 11 + .../misc/third_party_static/CMakeLists.txt | 6 + c++/src/misc/third_party_static/Makefile.in | 10 + ...le.third_party_msvcstatic_install.msvcproj | 11 + ...kefile.third_party_static_install.msvcproj | 11 + ...e.third_party_static_install.msvcproj.msvc | 4 + c++/src/objects/Makefile.in | 4 +- c++/src/objects/biblio/Auth_list.cpp | 6 +- c++/src/objects/biblio/Cit_gen.cpp | 4 +- c++/src/objects/biblio/biblio.def | 13 + c++/src/objects/biotree/DistanceMatrix.cpp | 4 +- c++/src/objects/blast/doc/blast.htm | 18 +- c++/src/objects/entrez2/entrez2.def | 18 +- c++/src/objects/general/Dbtag.cpp | 285 +- c++/src/objects/general/Name_std.cpp | 63 +- c++/src/objects/general/User_field.cpp | 8 +- c++/src/objects/general/User_object.cpp | 27 +- .../genomecoll/GCClient_GetAssemblyBySequ.cpp | 81 + c++/src/objects/genomecoll/GC_Assembly.cpp | 108 +- .../objects/genomecoll/cached_assembly.cpp | 56 +- c++/src/objects/genomecoll/gencoll_client.asn | 38 +- c++/src/objects/genomecoll/gencoll_client.def | 2 +- .../objects/genomecoll/genome_collection.asn | 3 +- .../genomecoll/genomic_collections_cli.cpp | 59 +- c++/src/objects/macro/String_constraint.cpp | 8 +- c++/src/objects/macro/Suspect_rule.cpp | 377 +- c++/src/objects/macro/product_rules.inc | 17000 ++++++++++------ c++/src/objects/macro/product_rules.prt | 16797 +++++++++------ c++/src/objects/medline/Medline_entry.cpp | 6 +- c++/src/objects/medline/medline.def | 8 + c++/src/objects/pub/Pub.cpp | 6 +- c++/src/objects/pub/Pub_equiv.cpp | 10 +- c++/src/objects/pub/pub.def | 4 + c++/src/objects/seq/Bioseq.cpp | 20 +- c++/src/objects/seq/Delta_ext.cpp | 6 +- c++/src/objects/seq/Linkage_evidence.cpp | 4 +- c++/src/objects/seq/Seq_gap.cpp | 4 +- c++/src/objects/seq/Seq_inst.cpp | 86 +- c++/src/objects/seq/Seq_literal.cpp | 4 +- c++/src/objects/seq/seq.def | 4 + c++/src/objects/seq/seq_align_mapper_base.cpp | 63 +- c++/src/objects/seq/seq_id_handle.cpp | 4 +- c++/src/objects/seq/seq_id_tree.cpp | 137 +- c++/src/objects/seq/seq_id_tree.hpp | 14 +- c++/src/objects/seq/seq_loc_from_string.cpp | 5 +- c++/src/objects/seq/seq_loc_mapper_base.cpp | 279 +- c++/src/objects/seq/sofa_map.cpp | 97 +- c++/src/objects/seqalign/Sparse_align.cpp | 7 +- c++/src/objects/seqalign/Sparse_seg.cpp | 5 +- c++/src/objects/seqalign/Spliced_seg.cpp | 12 +- c++/src/objects/seqalign/Std_seg.cpp | 5 +- c++/src/objects/seqcode/seqcode.def | 8 + c++/src/objects/seqfeat/BioSource.cpp | 327 +- c++/src/objects/seqfeat/Delta_item.cpp | 81 + c++/src/objects/seqfeat/Gb_qual.cpp | 31 +- .../objects/seqfeat/Genetic_code_table.cpp | 67 +- c++/src/objects/seqfeat/OrgMod.cpp | 92 +- c++/src/objects/seqfeat/OrgName.cpp | 34 +- c++/src/objects/seqfeat/RNA_ref.cpp | 2 +- c++/src/objects/seqfeat/SeqFeatData.cpp | 759 +- c++/src/objects/seqfeat/Seq_feat.cpp | 33 +- c++/src/objects/seqfeat/SubSource.cpp | 162 +- c++/src/objects/seqfeat/Trna_ext.cpp | 6 +- c++/src/objects/seqfeat/Variation_ref.cpp | 103 +- c++/src/objects/seqfeat/ecnum_deleted.inc | 2 +- c++/src/objects/seqfeat/ecnum_replaced.inc | 20 +- c++/src/objects/seqfeat/ecnum_replaced.txt | 18 +- c++/src/objects/seqfeat/ecnum_specific.inc | 86 +- c++/src/objects/seqfeat/ecnum_specific.txt | 84 +- c++/src/objects/seqfeat/institution_codes.inc | 502 +- c++/src/objects/seqfeat/institution_codes.txt | 500 +- c++/src/objects/seqfeat/lat_lon_country.inc | 12 +- c++/src/objects/seqfeat/lat_lon_country.txt | 282 +- c++/src/objects/seqfeat/seqfeat.asn | 5 +- c++/src/objects/seqloc/Seq_id.cpp | 2 +- c++/src/objects/seqloc/Seq_loc.cpp | 135 +- c++/src/objects/seqloc/accguide.inc | 59 +- c++/src/objects/seqloc/accguide.txt | 57 +- c++/src/objects/seqset/Bioseq_set.cpp | 33 +- c++/src/objects/taxon1/Taxon2_data.cpp | 2 +- c++/src/objects/taxon1/taxon1.cpp | 24 +- c++/src/objects/taxon1/taxon1.def | 12 + c++/src/objects/trackmgr/TMgr_ClientInfo.cpp | 4 +- .../objects/trackmgr/displaytrack_client.cpp | 83 +- c++/src/objects/trackmgr/trackmgr.asn | 13 +- c++/src/objects/valerr/ValidErrItem.cpp | 1436 +- c++/src/objects/valerr/ValidError.cpp | 19 +- c++/src/objects/valid/Comment_rule.cpp | 2 +- c++/src/objects/valid/Comment_set.cpp | 4 +- c++/src/objects/valid/validrules.inc | 9 +- c++/src/objects/valid/validrules.prt | 7 +- c++/src/objects/varrep/AaInterval.cpp | 82 + c++/src/objects/varrep/AaLocation.cpp | 77 + c++/src/objects/varrep/Makefile.in | 3 + c++/src/objects/varrep/Makefile.varrep.lib | 3 + c++/src/objects/varrep/varrep.asn | 296 + c++/src/objects/varrep/varrep.def | 17 + c++/src/objects/varrep/varrep.module | 1 + c++/src/objmgr/Makefile.objmgr.lib | 4 +- c++/src/objmgr/annot_collector.cpp | 300 +- c++/src/objmgr/annot_object_index.cpp | 4 +- c++/src/objmgr/annot_selector.cpp | 20 +- c++/src/objmgr/annot_types_ci.cpp | 8 +- c++/src/objmgr/bioseq_base_info.cpp | 31 +- c++/src/objmgr/bioseq_handle.cpp | 2 +- c++/src/objmgr/bioseq_info.cpp | 17 +- c++/src/objmgr/bioseq_set_info.cpp | 8 +- c++/src/objmgr/data_loader.cpp | 2 +- c++/src/objmgr/data_source.cpp | 2 +- c++/src/objmgr/edits_db_saver.cpp | 282 +- c++/src/objmgr/gc_assembly_parser.cpp | 6 +- c++/src/objmgr/mapped_feat.cpp | 20 +- c++/src/objmgr/objmgr_exception.cpp | 2 +- c++/src/objmgr/prefetch_actions.cpp | 4 +- c++/src/objmgr/scope.cpp | 2 +- c++/src/objmgr/scope_impl.cpp | 34 +- c++/src/objmgr/scope_info.cpp | 15 +- c++/src/objmgr/seq_annot_info.cpp | 156 +- c++/src/objmgr/seq_entry_info.cpp | 61 +- c++/src/objmgr/seq_feat_handle.cpp | 134 +- c++/src/objmgr/seq_id_sort.cpp | 2 +- c++/src/objmgr/seq_loc_cvt.cpp | 16 +- c++/src/objmgr/seq_loc_mapper.cpp | 93 +- c++/src/objmgr/seq_map.cpp | 19 +- c++/src/objmgr/seq_map_ci.cpp | 4 +- c++/src/objmgr/seq_map_switch.cpp | 14 +- c++/src/objmgr/seq_table_info.cpp | 186 +- c++/src/objmgr/seq_table_setters.cpp | 30 +- c++/src/objmgr/seq_vector.cpp | 22 +- c++/src/objmgr/snp_annot_info.cpp | 32 +- c++/src/objmgr/split/annot_piece.cpp | 4 +- c++/src/objmgr/split/blob_splitter_impl.cpp | 5 +- c++/src/objmgr/split/blob_splitter_maker.cpp | 20 +- c++/src/objmgr/split/id_range.cpp | 12 +- c++/src/objmgr/split/object_splitinfo.cpp | 4 +- c++/src/objmgr/split/size.cpp | 8 +- c++/src/objmgr/split_parser.cpp | 8 +- c++/src/objmgr/tse_assigner.cpp | 7 +- c++/src/objmgr/tse_handle.cpp | 4 +- c++/src/objmgr/tse_info.cpp | 23 +- c++/src/objmgr/tse_split_info.cpp | 11 +- c++/src/objmgr/unsupp_editsaver.cpp | 6 +- c++/src/objmgr/util/Makefile.util.lib | 4 +- c++/src/objmgr/util/create_defline.cpp | 65 +- c++/src/objmgr/util/feature.cpp | 201 +- c++/src/objmgr/util/obj_sniff.cpp | 75 +- c++/src/objmgr/util/objutil.cpp | 13 +- c++/src/objmgr/util/seq_loc_util.cpp | 32 +- c++/src/objmgr/util/seqtitle.cpp | 6 +- c++/src/objmgr/util/sequence.cpp | 376 +- c++/src/objmgr/util/weight.cpp | 6 +- .../align_format/align_format_util.cpp | 164 +- c++/src/objtools/align_format/aln_printer.cpp | 5 +- .../objtools/align_format/format_flags.cpp | 11 +- .../objtools/align_format/seqalignfilter.cpp | 7 +- c++/src/objtools/align_format/showalign.cpp | 90 +- c++/src/objtools/align_format/showdefline.cpp | 37 +- c++/src/objtools/align_format/tabular.cpp | 46 +- c++/src/objtools/align_format/taxFormat.cpp | 114 +- .../Makefile.align_format_unit_test.app | 6 +- .../data/in_showalign_use_this_gi_ext.asn | 1073 + .../unit_test/showalign_unit_test.cpp | 57 +- .../unit_test/showdefline_unit_test.cpp | 8 +- .../unit_test/tabularinof_unit_test.cpp | 20 +- .../objtools/align_format/vectorscreen.cpp | 9 +- c++/src/objtools/alnmgr/Makefile.alnmgr.lib | 5 +- c++/src/objtools/alnmgr/Makefile.in | 4 +- c++/src/objtools/alnmgr/aln_builders.cpp | 2 +- c++/src/objtools/alnmgr/alnvec.cpp | 5 +- .../objtools/alnmgr/score_builder_base.cpp | 5 +- c++/src/objtools/alnmgr/sparse_aln.cpp | 23 +- .../Makefile.blastdb_format.lib | 4 +- .../blastdb_format/blastdb_dataextract.cpp | 379 +- .../blastdb_format/blastdb_formatter.cpp | 7 +- .../blast/blastdb_format/seq_formatter.cpp | 543 + .../blast/blastdb_format/seq_writer.cpp | 88 +- .../Makefile.blastdb_format_unit_test.app | 6 +- .../unit_test/seq_formatter_unit_test.cpp | 386 + .../unit_test/seq_writer_unit_test.cpp | 67 +- .../demo/gene_info_reader_app.cpp | 4 +- .../blast/gene_info_reader/file_utils.cpp | 7 +- .../blast/gene_info_reader/gene_info.cpp | 7 +- .../gene_info_reader/gene_info_reader.cpp | 7 +- c++/src/objtools/blast/seqdb_reader/seqdb.cpp | 16 +- .../blast/seqdb_reader/seqdbalias.cpp | 7 +- .../blast/seqdb_reader/seqdbatlas.cpp | 7 +- .../blast/seqdb_reader/seqdbbitset.cpp | 7 +- .../objtools/blast/seqdb_reader/seqdbblob.cpp | 7 +- .../objtools/blast/seqdb_reader/seqdbcol.cpp | 7 +- .../blast/seqdb_reader/seqdbcommon.cpp | 29 +- .../blast/seqdb_reader/seqdbexpert.cpp | 7 +- .../objtools/blast/seqdb_reader/seqdbfile.cpp | 7 +- .../blast/seqdb_reader/seqdbfilter.cpp | 7 +- .../blast/seqdb_reader/seqdbgilistset.cpp | 7 +- .../blast/seqdb_reader/seqdbgimask.cpp | 7 +- .../objtools/blast/seqdb_reader/seqdbimpl.cpp | 58 +- .../objtools/blast/seqdb_reader/seqdbimpl.hpp | 20 +- .../objtools/blast/seqdb_reader/seqdbisam.cpp | 11 +- .../objtools/blast/seqdb_reader/seqdbobj.cpp | 7 +- .../blast/seqdb_reader/seqdboidlist.cpp | 7 +- .../objtools/blast/seqdb_reader/seqdbtax.cpp | 7 +- .../objtools/blast/seqdb_reader/seqdbvol.cpp | 21 +- .../blast/seqdb_reader/seqdbvolset.cpp | 7 +- .../blast/seqdb_reader/test/seqdb_perf.cpp | 9 +- .../blast/seqdb_writer/build-alias-index | 2 +- .../objtools/blast/seqdb_writer/build_db.cpp | 56 +- .../blast/seqdb_writer/mask_info_registry.cpp | 5 - .../blast/seqdb_writer/multisource_util.cpp | 7 +- .../objtools/blast/seqdb_writer/taxid_set.cpp | 7 +- .../unit_test/Makefile.writedb_unit_test.app | 4 +- .../unit_test/data/some_prots.fsa | 142 + .../unit_test/writedb_unit_test.cpp | 454 +- .../objtools/blast/seqdb_writer/writedb.cpp | 14 +- .../blast/seqdb_writer/writedb_column.cpp | 7 +- .../blast/seqdb_writer/writedb_convert.cpp | 7 +- .../blast/seqdb_writer/writedb_files.cpp | 7 +- .../blast/seqdb_writer/writedb_general.cpp | 7 +- .../blast/seqdb_writer/writedb_gimask.cpp | 7 +- .../blast/seqdb_writer/writedb_impl.cpp | 66 +- .../blast/seqdb_writer/writedb_impl.hpp | 20 +- .../blast/seqdb_writer/writedb_isam.cpp | 7 +- .../blast/seqdb_writer/writedb_volume.cpp | 10 +- .../services/Makefile.blast_services.lib | 5 +- .../blast/services/blast_services.cpp | 10 +- c++/src/objtools/cleanup/Makefile.cleanup.lib | 6 +- .../cleanup/autogenerated_cleanup.cpp | 309 +- .../cleanup/autogenerated_cleanup.hpp | 43 +- .../cleanup/autogenerated_cleanup.txt | 2 +- .../autogenerated_extended_cleanup.cpp | 3 +- .../autogenerated_extended_cleanup.hpp | 2 +- .../autogenerated_extended_cleanup.txt | 2 - c++/src/objtools/cleanup/cleanup.cpp | 983 +- c++/src/objtools/cleanup/cleanup_utils.cpp | 3 +- c++/src/objtools/cleanup/newcleanupp.cpp | 534 +- c++/src/objtools/cleanup/newcleanupp.hpp | 3 +- c++/src/objtools/data_loaders/Makefile.in | 4 +- .../data_loaders/blastdb/bdbloader.cpp | 6 +- .../data_loaders/blastdb/bdbloader_rmt.cpp | 6 +- .../data_loaders/blastdb/cached_sequence.cpp | 6 +- .../blastdb/local_blastdb_adapter.cpp | 6 +- .../blastdb/remote_blastdb_adapter.cpp | 6 +- .../genbank/Makefile.ncbi_xreader.lib | 4 +- .../genbank/cache/reader_cache.cpp | 2 +- .../genbank/cache/writer_cache.cpp | 2 +- .../data_loaders/genbank/dispatcher.cpp | 2 +- .../data_loaders/genbank/gbloader.cpp | 17 +- .../data_loaders/genbank/gicache/Makefile.in | 4 +- .../gicache/Makefile.ncbi_xreader_gicache.lib | 7 +- .../data_loaders/genbank/gicache/gicache.c | 2570 +-- .../data_loaders/genbank/gicache/gicache.h | 60 +- .../genbank/gicache/gicache_cxx.cpp | 38 - .../genbank/gicache/reader_gicache.cpp | 15 +- .../data_loaders/genbank/id1/reader_id1.cpp | 4 +- .../data_loaders/genbank/id2/reader_id2.cpp | 4 +- .../data_loaders/genbank/info_cache.cpp | 2 +- .../data_loaders/genbank/processors.cpp | 57 +- .../objtools/data_loaders/genbank/reader.cpp | 2 +- .../data_loaders/genbank/reader_id1_base.cpp | 2 +- .../data_loaders/genbank/reader_id2_base.cpp | 585 +- .../data_loaders/genbank/reader_service.cpp | 5 +- .../data_loaders/genbank/reader_snp.cpp | 2 +- .../data_loaders/genbank/request_result.cpp | 2 +- c++/src/objtools/edit/Makefile.edit.lib | 4 +- c++/src/objtools/edit/apply_object.cpp | 2 +- c++/src/objtools/edit/autodef.cpp | 46 +- .../edit/autodef_available_modifier.cpp | 87 +- .../objtools/edit/autodef_feature_clause.cpp | 164 +- .../edit/autodef_feature_clause_base.cpp | 109 +- c++/src/objtools/edit/autodef_mod_combo.cpp | 4 +- c++/src/objtools/edit/autodef_options.cpp | 22 +- c++/src/objtools/edit/cds_fix.cpp | 3 +- c++/src/objtools/edit/feattable_edit.cpp | 296 +- c++/src/objtools/edit/gaps_edit.cpp | 135 +- c++/src/objtools/edit/loc_edit.cpp | 2 +- c++/src/objtools/edit/mail_report.cpp | 24 +- c++/src/objtools/edit/publication_edit.cpp | 2 +- c++/src/objtools/edit/remote_updater.cpp | 2 +- c++/src/objtools/edit/rna_edit.cpp | 195 +- c++/src/objtools/edit/seq_entry_edit.cpp | 13 +- c++/src/objtools/edit/string_constraint.cpp | 66 +- c++/src/objtools/edit/struc_comm_field.cpp | 2 +- c++/src/objtools/format/Makefile.xformat.lib | 4 +- c++/src/objtools/format/comment_item.cpp | 102 +- c++/src/objtools/format/context.cpp | 10 +- c++/src/objtools/format/dbsource_item.cpp | 9 +- c++/src/objtools/format/feature_item.cpp | 102 +- c++/src/objtools/format/flat_file_config.cpp | 57 +- .../objtools/format/flat_file_generator.cpp | 16 +- c++/src/objtools/format/flat_qual_slots.cpp | 3 +- c++/src/objtools/format/flat_seqloc.cpp | 2 +- c++/src/objtools/format/gather_items.cpp | 129 +- c++/src/objtools/format/genbank_formatter.cpp | 70 +- c++/src/objtools/format/genbank_gather.cpp | 2 +- c++/src/objtools/format/gene_finder.cpp | 3 +- c++/src/objtools/format/inst_info_map.cpp | 18 +- c++/src/objtools/format/inst_info_map.hpp | 2 +- c++/src/objtools/format/item_formatter.cpp | 12 +- c++/src/objtools/format/keywords_item.cpp | 2 +- c++/src/objtools/format/locus_item.cpp | 7 +- c++/src/objtools/format/qualifiers.cpp | 14 +- c++/src/objtools/readers/Makefile.in | 4 +- .../objtools/readers/Makefile.xobjread.lib | 10 +- .../objtools/readers/Makefile.xobjreadex.lib | 4 +- c++/src/objtools/readers/agp_util.cpp | 31 +- c++/src/objtools/readers/aln_reader.cpp | 24 +- c++/src/objtools/readers/bed_reader.cpp | 729 +- c++/src/objtools/readers/fasta.cpp | 319 +- c++/src/objtools/readers/gff2_data.cpp | 223 +- c++/src/objtools/readers/gff2_reader.cpp | 806 +- c++/src/objtools/readers/gff3_reader.cpp | 248 +- c++/src/objtools/readers/gff3_sofa.cpp | 34 +- c++/src/objtools/readers/gff_reader.cpp | 2 +- c++/src/objtools/readers/gtf_reader.cpp | 162 +- c++/src/objtools/readers/gvf_reader.cpp | 623 +- c++/src/objtools/readers/idmapper_config.cpp | 6 +- .../objtools/readers/microarray_reader.cpp | 50 +- c++/src/objtools/readers/read_util.cpp | 2 +- c++/src/objtools/readers/reader_base.cpp | 57 +- c++/src/objtools/readers/reader_data.cpp | 52 +- c++/src/objtools/readers/reader_data.hpp | 29 +- c++/src/objtools/readers/readfeat.cpp | 483 +- .../objtools/readers/source_mod_parser.cpp | 10 +- .../objtools/readers/struct_cmt_reader.cpp | 130 + c++/src/objtools/readers/track_data.cpp | 144 + c++/src/objtools/readers/vcf_reader.cpp | 33 +- c++/src/objtools/readers/wiggle_reader.cpp | 3 +- .../objtools/seqmasks_io/mask_bdb_reader.cpp | 7 +- .../seqmasks_io/mask_cmdline_args.cpp | 7 +- .../seqmasks_io/mask_fasta_reader.cpp | 7 +- c++/src/objtools/seqmasks_io/mask_writer.cpp | 7 +- .../mask_writer_blastdb_maskinfo.cpp | 7 +- .../seqmasks_io/mask_writer_fasta.cpp | 7 +- .../objtools/seqmasks_io/mask_writer_int.cpp | 7 +- .../seqmasks_io/mask_writer_seqloc.cpp | 7 +- .../objtools/seqmasks_io/mask_writer_tab.cpp | 7 +- c++/src/serial/aliasinfo.cpp | 12 +- c++/src/serial/choice.cpp | 2 +- c++/src/serial/classinfo.cpp | 2 +- c++/src/serial/datatool/aliasstr.cpp | 4 +- c++/src/serial/datatool/choiceptrstr.cpp | 4 +- c++/src/serial/datatool/choicestr.cpp | 4 +- c++/src/serial/datatool/classstr.cpp | 4 +- c++/src/serial/datatool/datatool.cpp | 4 +- c++/src/serial/datatool/datatool.hpp | 7 +- c++/src/serial/datatool/dtdaux.cpp | 4 +- c++/src/serial/datatool/dtdparser.cpp | 14 +- c++/src/serial/datatool/enumtype.cpp | 7 +- c++/src/serial/datatool/exceptions.hpp | 8 +- c++/src/serial/datatool/filecode.cpp | 4 +- c++/src/serial/datatool/fileutil.cpp | 9 +- c++/src/serial/datatool/module.cpp | 6 +- c++/src/serial/datatool/parser.cpp | 4 +- c++/src/serial/datatool/srcutil.cpp | 4 +- c++/src/serial/datatool/statictype.cpp | 18 +- c++/src/serial/datatool/statictype.hpp | 7 +- c++/src/serial/datatool/stdstr.cpp | 9 +- c++/src/serial/datatool/stdstr.hpp | 3 +- .../datatool/traversal_code_generator.cpp | 18 +- c++/src/serial/datatool/traversal_node.cpp | 14 +- .../traversal_pattern_match_callback.cpp | 4 +- .../datatool/traversal_spec_file_parser.cpp | 7 +- c++/src/serial/datatool/type.cpp | 12 +- c++/src/serial/datatool/typestr.cpp | 9 +- c++/src/serial/datatool/typestr.hpp | 8 +- c++/src/serial/datatool/wsdlparser.cpp | 22 +- c++/src/serial/datatool/wsdlstr.cpp | 8 +- c++/src/serial/datatool/xsdlexer.cpp | 6 +- c++/src/serial/datatool/xsdparser.cpp | 8 +- c++/src/serial/enumerated.cpp | 4 +- c++/src/serial/exception.cpp | 4 +- c++/src/serial/member.cpp | 6 +- c++/src/serial/memberid.cpp | 8 +- c++/src/serial/objectio.cpp | 15 +- c++/src/serial/objhook.cpp | 41 +- c++/src/serial/objistr.cpp | 12 +- c++/src/serial/objistrasn.cpp | 22 +- c++/src/serial/objistrasnb.cpp | 38 +- c++/src/serial/objistrjson.cpp | 44 +- c++/src/serial/objistrxml.cpp | 22 +- c++/src/serial/objostr.cpp | 24 +- c++/src/serial/objostrasn.cpp | 21 +- c++/src/serial/objostrasnb.cpp | 25 +- c++/src/serial/objostrjson.cpp | 16 +- c++/src/serial/objostrxml.cpp | 43 +- c++/src/serial/objstack.cpp | 4 +- c++/src/serial/rpcbase.cpp | 5 +- c++/src/serial/serialobject.cpp | 4 +- c++/src/serial/stdtypes.cpp | 57 +- c++/src/serial/typeinfo.cpp | 5 +- c++/src/util/Makefile.util.lib | 4 +- c++/src/util/bytesrc.cpp | 10 +- c++/src/util/compress/api/archive_zip.cpp | 4 +- c++/src/util/compress/api/stream.cpp | 10 +- c++/src/util/compress/api/stream_util.cpp | 18 +- c++/src/util/compress/api/streambuf.cpp | 56 +- c++/src/util/compress/api/zlib.cpp | 4 +- c++/src/util/compress/bzip2/CHANGES | 74 + c++/src/util/compress/bzip2/LICENSE | 13 +- c++/src/util/compress/bzip2/README | 126 +- .../bzip2/README.COMPILATION.PROBLEMS | 130 +- c++/src/util/compress/bzip2/README.XML.STUFF | 45 + c++/src/util/compress/bzip2/Y2K_INFO | 34 - c++/src/util/compress/bzip2/blocksort.c | 77 +- c++/src/util/compress/bzip2/bzdiff | 4 +- c++/src/util/compress/bzip2/bzgrep | 6 +- c++/src/util/compress/bzip2/bzip.css | 74 + c++/src/util/compress/bzip2/bzip2.1 | 17 +- .../util/compress/bzip2/bzip2.1.preformatted | 398 - c++/src/util/compress/bzip2/bzip2.c | 219 +- c++/src/util/compress/bzip2/bzip2.txt | 119 +- c++/src/util/compress/bzip2/bzip2recover.c | 90 +- c++/src/util/compress/bzip2/bzlib.c | 151 +- c++/src/util/compress/bzip2/bzlib_private.h | 98 +- c++/src/util/compress/bzip2/compress.c | 98 +- c++/src/util/compress/bzip2/crctable.c | 60 +- c++/src/util/compress/bzip2/decompress.c | 102 +- c++/src/util/compress/bzip2/dlltest.c | 5 +- c++/src/util/compress/bzip2/huffman.c | 85 +- c++/src/util/compress/bzip2/manual.html | 2657 ++- c++/src/util/compress/bzip2/manual.pdf | Bin 298267 -> 256905 bytes c++/src/util/compress/bzip2/manual.texi | 2243 -- c++/src/util/compress/bzip2/manual.xml | 2964 +++ c++/src/util/compress/bzip2/manual_1.html | 81 - c++/src/util/compress/bzip2/manual_2.html | 579 - c++/src/util/compress/bzip2/manual_3.html | 1855 -- c++/src/util/compress/bzip2/manual_4.html | 530 - c++/src/util/compress/bzip2/manual_abt.html | 201 - c++/src/util/compress/bzip2/manual_ovr.html | 54 - c++/src/util/compress/bzip2/manual_toc.html | 163 - c++/src/util/compress/bzip2/mk251.c | 15 + .../util/compress/bzip2/ncbi_bz2_compress.c | 706 +- c++/src/util/compress/bzip2/randtable.c | 60 +- c++/src/util/compress/bzip2/spewG.c | 15 + c++/src/util/compress/bzip2/unzcrash.c | 17 +- c++/src/util/file_manifest.cpp | 2 +- c++/src/util/format_guess.cpp | 532 +- c++/src/util/retry_ctx.cpp | 2 +- c++/src/util/scheduler.cpp | 10 +- c++/src/util/sequtil/sequtil_convert_imp.cpp | 10 +- c++/src/util/sequtil/sequtil_convert_imp.hpp | 2 +- c++/src/util/strbuffer.cpp | 11 +- c++/src/util/stream_source.cpp | 2 +- c++/src/util/table_printer.cpp | 6 +- c++/src/util/tables/raw_scoremat.c | 9 +- c++/src/util/thread_pool.cpp | 2 +- 1444 files changed, 102689 insertions(+), 37619 deletions(-) create mode 100644 c++/compilers/vs2015/Makefile.WinMain.app.msvc create mode 100644 c++/compilers/vs2015/Makefile.wxWidgets.app.msvc create mode 100644 c++/compilers/vs2015/build.sh create mode 100644 c++/compilers/vs2015/build_exec.bat create mode 100644 c++/compilers/vs2015/build_util.sh create mode 100644 c++/compilers/vs2015/check.sh create mode 100644 c++/compilers/vs2015/configure.bat create mode 100644 c++/compilers/vs2015/datatool.bat create mode 100644 c++/compilers/vs2015/dll/build/UtilityProjects/_CONFIGURE_.vcxproj create mode 100644 c++/compilers/vs2015/dll/build/UtilityProjects/_CONFIGURE_DIALOG_.vcxproj create mode 100644 c++/compilers/vs2015/dll/build/UtilityProjects/configure._ create mode 100644 c++/compilers/vs2015/dll/build/UtilityProjects/configure_dialog._ create mode 100644 c++/compilers/vs2015/dll/build/all.bat create mode 100644 c++/compilers/vs2015/dll/build/all_gbench.bat create mode 100644 c++/compilers/vs2015/dll/build/all_gui.bat create mode 100644 c++/compilers/vs2015/dll/build/all_ncbi.bat create mode 100644 c++/compilers/vs2015/dll/build/gbench/UtilityProjects/_CONFIGURE_.vcxproj create mode 100644 c++/compilers/vs2015/dll/build/gbench/UtilityProjects/_CONFIGURE_DIALOG_.vcxproj create mode 100644 c++/compilers/vs2015/dll/build/gbench/UtilityProjects/configure._ create mode 100644 c++/compilers/vs2015/dll/build/gbench/UtilityProjects/configure_dialog._ create mode 100644 c++/compilers/vs2015/dll/build/gbench/configure_prebuild.bat create mode 100644 c++/compilers/vs2015/dll/build/gbench/gbench_install/gbench-install.vcxproj create mode 100644 c++/compilers/vs2015/dll/build/gbench/ncbi_gbench.sln create mode 100644 c++/compilers/vs2015/dll/build/gui/UtilityProjects/_CONFIGURE_.vcxproj create mode 100644 c++/compilers/vs2015/dll/build/gui/UtilityProjects/_CONFIGURE_DIALOG_.vcxproj create mode 100644 c++/compilers/vs2015/dll/build/gui/UtilityProjects/configure._ create mode 100644 c++/compilers/vs2015/dll/build/gui/UtilityProjects/configure_dialog._ create mode 100644 c++/compilers/vs2015/dll/build/gui/ncbi_gui_dll.sln create mode 100644 c++/compilers/vs2015/dll/build/internal/gbench/gbench_install_internal/gbench-install-internal.vcxproj create mode 100644 c++/compilers/vs2015/dll/build/ncbi_cpp_dll.sln create mode 100644 c++/compilers/vs2015/dll/dll_main.cpp create mode 100644 c++/compilers/vs2015/dll/third_party_dll_install.mak create mode 100644 c++/compilers/vs2015/dll/third_party_dll_install.vcxproj create mode 100644 c++/compilers/vs2015/dll/third_party_msvcdll_install.vcxproj create mode 100644 c++/compilers/vs2015/install.sh create mode 100644 c++/compilers/vs2015/lock_ptb_config.bat create mode 100644 c++/compilers/vs2015/make.bat create mode 100644 c++/compilers/vs2015/make_ncbi.bat create mode 100644 c++/compilers/vs2015/msvcvars.bat create mode 100644 c++/compilers/vs2015/ncbi.rc create mode 100644 c++/compilers/vs2015/ncbilogo.ico create mode 100644 c++/compilers/vs2015/ptb.bat create mode 100644 c++/compilers/vs2015/static/build/UtilityProjects/PTB.sln create mode 100644 c++/compilers/vs2015/static/build/UtilityProjects/_CONFIGURE_.vcxproj create mode 100644 c++/compilers/vs2015/static/build/UtilityProjects/_CONFIGURE_DIALOG_.vcxproj create mode 100644 c++/compilers/vs2015/static/build/UtilityProjects/configure._ create mode 100644 c++/compilers/vs2015/static/build/UtilityProjects/configure_dialog._ create mode 100644 c++/compilers/vs2015/static/build/all.bat create mode 100644 c++/compilers/vs2015/static/build/all_gui.bat create mode 100644 c++/compilers/vs2015/static/build/all_ncbi.bat create mode 100644 c++/compilers/vs2015/static/build/build-system/project_tree_builder/msbuild/msbuild_dataobj.lib.vcxproj create mode 100644 c++/compilers/vs2015/static/build/build-system/project_tree_builder/project_tree_builder.exe.vcxproj create mode 100644 c++/compilers/vs2015/static/build/corelib/xncbi.lib.vcxproj create mode 100644 c++/compilers/vs2015/static/build/gui/UtilityProjects/_CONFIGURE_.vcxproj create mode 100644 c++/compilers/vs2015/static/build/gui/UtilityProjects/_CONFIGURE_DIALOG_.vcxproj create mode 100644 c++/compilers/vs2015/static/build/gui/UtilityProjects/configure._ create mode 100644 c++/compilers/vs2015/static/build/gui/UtilityProjects/configure_dialog._ create mode 100644 c++/compilers/vs2015/static/build/gui/ncbi_gui.sln create mode 100644 c++/compilers/vs2015/static/build/ncbi_cpp.sln create mode 100644 c++/compilers/vs2015/static/build/serial/datatool/datatool.exe.vcxproj create mode 100644 c++/compilers/vs2015/static/build/serial/xser.lib.vcxproj create mode 100644 c++/compilers/vs2015/static/build/util/regexp/regexp.lib.vcxproj create mode 100644 c++/compilers/vs2015/static/build/util/xregexp/xregexp.lib.vcxproj create mode 100644 c++/compilers/vs2015/static/build/util/xutil.lib.vcxproj create mode 100644 c++/compilers/vs2015/static/third_party_msvcstatic_install.vcxproj create mode 100644 c++/compilers/vs2015/static/third_party_static_install.mak create mode 100644 c++/compilers/vs2015/static/third_party_static_install.vcxproj create mode 100644 c++/compilers/vs2015/third_party_install.meta.mk create mode 100644 c++/compilers/vs2015/user/build/UtilityProjects/_CONFIGURE_.vcxproj create mode 100644 c++/compilers/vs2015/user/build/UtilityProjects/_CONFIGURE_DIALOG_.vcxproj create mode 100644 c++/compilers/vs2015/user/build/UtilityProjects/configure._ create mode 100644 c++/compilers/vs2015/user/build/UtilityProjects/configure_dialog._ create mode 100644 c++/compilers/vs2015/user/build/ncbi_user.sln create mode 100644 c++/include/algo/blast/api/magicblast.hpp create mode 100644 c++/include/algo/blast/api/magicblast_options.hpp create mode 100644 c++/include/algo/blast/blastinput/blast_asn1_input.hpp create mode 100644 c++/include/algo/blast/blastinput/kblastp_args.hpp create mode 100644 c++/include/algo/blast/blastinput/magicblast_args.hpp create mode 100644 c++/include/algo/blast/core/hspfilter_mapper.h delete mode 100644 c++/include/common/config/ncbiconf_msvc_site.h delete mode 100644 c++/include/common/config/ncbiconf_xcode_site.h create mode 100644 c++/include/common/ncbi_build_ver.h.in mode change 100755 => 100644 c++/include/connect/ncbi_lbos.hpp create mode 100644 c++/include/connect/ncbi_monkey.hpp create mode 100644 c++/include/connect/services/netcache_search.hpp create mode 100644 c++/include/misc/error_codes.hpp create mode 100644 c++/include/objects/biblio/MedlineUID.hpp create mode 100644 c++/include/objects/biblio/PmcID.hpp create mode 100644 c++/include/objects/biblio/PubMedId.hpp create mode 100644 c++/include/objects/genomecoll/GCClient_GetAssemblyBySequ.hpp create mode 100644 c++/include/objects/seqfeat/Delta_item.hpp create mode 100644 c++/include/objects/varrep/AaInterval.hpp create mode 100644 c++/include/objects/varrep/AaLocation.hpp create mode 100644 c++/include/objtools/blast/blastdb_format/seq_formatter.hpp create mode 100644 c++/include/objtools/readers/struct_cmt_reader.hpp create mode 100644 c++/include/objtools/readers/track_data.hpp mode change 100755 => 100644 c++/include/util/bitset/bmblocks.h mode change 100755 => 100644 c++/include/util/bitset/ncbi_bitset_util.hpp create mode 100644 c++/include/util/timsort.hpp create mode 100755 c++/scripts/common/impl/python-config.py delete mode 100755 c++/scripts/common/new_project_msvc7.bat create mode 100644 c++/scripts/projects/magicblast/ChangeLog create mode 100644 c++/scripts/projects/magicblast/LICENSE create mode 100644 c++/scripts/projects/magicblast/Manifest create mode 100644 c++/scripts/projects/magicblast/README create mode 100644 c++/scripts/projects/magicblast/components.link create mode 100644 c++/scripts/projects/magicblast/post_build/blast_utils.py create mode 100644 c++/scripts/projects/magicblast/post_build/macosx/large-Blue_ncbi_logo.tiff create mode 100755 c++/scripts/projects/magicblast/post_build/macosx/ncbi-magicblast.sh create mode 100644 c++/scripts/projects/magicblast/post_build/macosx/uninstall_ncbi_magicblast.zip create mode 100644 c++/scripts/projects/magicblast/post_build/macosx/welcome.txt create mode 100755 c++/scripts/projects/magicblast/post_build/make_installers.py create mode 100755 c++/scripts/projects/magicblast/post_build/rpm/make_rpm.py create mode 100644 c++/scripts/projects/magicblast/post_build/rpm/ncbi-magicblast.spec create mode 100644 c++/scripts/projects/magicblast/post_build/win/EnvVarUpdate.nsh create mode 100644 c++/scripts/projects/magicblast/post_build/win/make_win.py create mode 100755 c++/scripts/projects/magicblast/post_build/win/ncbi-blast.nsi create mode 100644 c++/scripts/projects/magicblast/post_build/win/ncbilogo.ico create mode 100644 c++/scripts/projects/magicblast/post_build/win/unix2dos.nsh create mode 100644 c++/scripts/projects/magicblast/project.lst create mode 100644 c++/src/algo/blast/api/magicblast.cpp create mode 100644 c++/src/algo/blast/api/magicblast_options.cpp create mode 100644 c++/src/algo/blast/blastinput/blast_asn1_input.cpp create mode 100644 c++/src/algo/blast/blastinput/kblastp_args.cpp create mode 100644 c++/src/algo/blast/blastinput/magicblast_args.cpp create mode 100644 c++/src/algo/blast/blastinput/unit_test/data/paired_reads.asn create mode 100644 c++/src/algo/blast/blastinput/unit_test/data/paired_reads.fa create mode 100644 c++/src/algo/blast/blastinput/unit_test/data/paired_reads.fastq create mode 100644 c++/src/algo/blast/blastinput/unit_test/data/paired_reads_1.asn create mode 100644 c++/src/algo/blast/blastinput/unit_test/data/paired_reads_1.fa create mode 100644 c++/src/algo/blast/blastinput/unit_test/data/paired_reads_1.fastq create mode 100644 c++/src/algo/blast/blastinput/unit_test/data/paired_reads_2.asn create mode 100644 c++/src/algo/blast/blastinput/unit_test/data/paired_reads_2.fa create mode 100644 c++/src/algo/blast/blastinput/unit_test/data/paired_reads_2.fastq create mode 100644 c++/src/algo/blast/core/hspfilter_mapper.c create mode 100644 c++/src/algo/blast/core/jumper.c create mode 100644 c++/src/algo/blast/core/jumper.h create mode 100644 c++/src/algo/blast/unit_tests/api/Makefile.magicblast_unit_test.app create mode 100644 c++/src/algo/blast/unit_tests/api/data/magicblast_paired.asn create mode 100644 c++/src/algo/blast/unit_tests/api/data/magicblast_queries.asn create mode 100644 c++/src/algo/blast/unit_tests/api/data/pombe.nhr create mode 100644 c++/src/algo/blast/unit_tests/api/data/pombe.nin create mode 100644 c++/src/algo/blast/unit_tests/api/data/pombe.nog create mode 100644 c++/src/algo/blast/unit_tests/api/data/pombe.nsd create mode 100644 c++/src/algo/blast/unit_tests/api/data/pombe.nsi create mode 100644 c++/src/algo/blast/unit_tests/api/data/pombe.nsq create mode 100644 c++/src/algo/blast/unit_tests/api/magicblast_unit_test.cpp create mode 100644 c++/src/algo/blast/unit_tests/api/magicblast_unit_test.ini create mode 100644 c++/src/algo/blast/unit_tests/api/stat_unit_test.ini mode change 100755 => 100644 c++/src/connect/ncbi_lbos.h mode change 100755 => 100644 c++/src/connect/ncbi_lbos_cxx.cpp create mode 100644 c++/src/connect/ncbi_monkey.cpp create mode 100644 c++/src/connect/ncbi_monkeyp.hpp create mode 100644 c++/src/connect/parson.c create mode 100644 c++/src/connect/parson.h create mode 100644 c++/src/connect/services/netcache_search.cpp create mode 100644 c++/src/misc/CMakeLists.txt create mode 100644 c++/src/misc/Makefile.in create mode 100644 c++/src/misc/third_party/CMakeLists.txt create mode 100644 c++/src/misc/third_party/Makefile.in create mode 100644 c++/src/misc/third_party/Makefile.third_party_dll_install.msvcproj create mode 100644 c++/src/misc/third_party/Makefile.third_party_dll_install.msvcproj.msvc create mode 100644 c++/src/misc/third_party/Makefile.third_party_msvcdll_install.msvcproj create mode 100644 c++/src/misc/third_party_static/CMakeLists.txt create mode 100644 c++/src/misc/third_party_static/Makefile.in create mode 100644 c++/src/misc/third_party_static/Makefile.third_party_msvcstatic_install.msvcproj create mode 100644 c++/src/misc/third_party_static/Makefile.third_party_static_install.msvcproj create mode 100644 c++/src/misc/third_party_static/Makefile.third_party_static_install.msvcproj.msvc create mode 100644 c++/src/objects/genomecoll/GCClient_GetAssemblyBySequ.cpp create mode 100644 c++/src/objects/seqfeat/Delta_item.cpp create mode 100644 c++/src/objects/varrep/AaInterval.cpp create mode 100644 c++/src/objects/varrep/AaLocation.cpp create mode 100644 c++/src/objects/varrep/Makefile.in create mode 100644 c++/src/objects/varrep/Makefile.varrep.lib create mode 100644 c++/src/objects/varrep/varrep.asn create mode 100644 c++/src/objects/varrep/varrep.def create mode 100644 c++/src/objects/varrep/varrep.module create mode 100755 c++/src/objtools/align_format/unit_test/data/in_showalign_use_this_gi_ext.asn create mode 100644 c++/src/objtools/blast/blastdb_format/seq_formatter.cpp create mode 100644 c++/src/objtools/blast/blastdb_format/unit_test/seq_formatter_unit_test.cpp create mode 100644 c++/src/objtools/blast/seqdb_writer/unit_test/data/some_prots.fsa delete mode 100644 c++/src/objtools/data_loaders/genbank/gicache/gicache_cxx.cpp create mode 100644 c++/src/objtools/readers/struct_cmt_reader.cpp create mode 100644 c++/src/objtools/readers/track_data.cpp create mode 100644 c++/src/util/compress/bzip2/README.XML.STUFF delete mode 100644 c++/src/util/compress/bzip2/Y2K_INFO create mode 100644 c++/src/util/compress/bzip2/bzip.css delete mode 100644 c++/src/util/compress/bzip2/bzip2.1.preformatted delete mode 100644 c++/src/util/compress/bzip2/manual.texi create mode 100644 c++/src/util/compress/bzip2/manual.xml delete mode 100644 c++/src/util/compress/bzip2/manual_1.html delete mode 100644 c++/src/util/compress/bzip2/manual_2.html delete mode 100644 c++/src/util/compress/bzip2/manual_3.html delete mode 100644 c++/src/util/compress/bzip2/manual_4.html delete mode 100644 c++/src/util/compress/bzip2/manual_abt.html delete mode 100644 c++/src/util/compress/bzip2/manual_ovr.html delete mode 100644 c++/src/util/compress/bzip2/manual_toc.html diff --git a/c++/compilers/unix/GCC.sh b/c++/compilers/unix/GCC.sh index 7d0a5e61..c1af4dc2 100755 --- a/c++/compilers/unix/GCC.sh +++ b/c++/compilers/unix/GCC.sh @@ -3,7 +3,7 @@ # Setup the local working environment for the "configure" script # Compiler: GCC # -# $Revision: 491045 $ // by Denis Vakatov, NCBI (vakatov@ncbi.nlm.nih.gov) +# $Revision: 491630 $ // by Denis Vakatov, NCBI (vakatov@ncbi.nlm.nih.gov) ############################################################################# diff --git a/c++/compilers/unix/ICC.sh b/c++/compilers/unix/ICC.sh index 385338ea..8175035c 100755 --- a/c++/compilers/unix/ICC.sh +++ b/c++/compilers/unix/ICC.sh @@ -5,7 +5,7 @@ # OS: Linux # Processor: Intel X86(-64) # -# $Revision: 492739 $ // Dmitriy Beloslyudtsev, NCBI (beloslyu@ncbi.nlm.nih.gov) +# $Revision: 492694 $ // Dmitriy Beloslyudtsev, NCBI (beloslyu@ncbi.nlm.nih.gov) ############################################################################# diff --git a/c++/compilers/vs2013/build_exec.bat b/c++/compilers/vs2013/build_exec.bat index ba9a4ae9..2ce01647 100644 --- a/c++/compilers/vs2013/build_exec.bat +++ b/c++/compilers/vs2013/build_exec.bat @@ -1,5 +1,5 @@ @ECHO OFF -REM $Id: build_exec.bat 430635 2014-03-27 17:34:42Z gouriano $ +REM $Id: build_exec.bat 505228 2016-06-23 12:54:48Z ivanov $ REM =========================================================================== REM REM PUBLIC DOMAIN NOTICE @@ -43,6 +43,7 @@ exit 1 :be_build set arch=Win32 +if _%5_ == __CONFIGURE__ set arch=x86 if _%3_ == _64_ set arch=x64 rem Next command should be executed last! No other code after it, please. diff --git a/c++/compilers/vs2013/configure.bat b/c++/compilers/vs2013/configure.bat index 9354ee8e..14339f6f 100644 --- a/c++/compilers/vs2013/configure.bat +++ b/c++/compilers/vs2013/configure.bat @@ -1,5 +1,5 @@ @echo off -REM $Id: configure.bat 449189 2014-10-14 14:54:57Z gouriano $ +REM $Id: configure.bat 505229 2016-06-23 13:04:20Z gouriano $ REM =========================================================================== REM REM PUBLIC DOMAIN NOTICE diff --git a/c++/compilers/vs2013/dll/build/gbench/ncbi_gbench.sln b/c++/compilers/vs2013/dll/build/gbench/ncbi_gbench.sln index a54e8468..dda40e3f 100644 --- a/c++/compilers/vs2013/dll/build/gbench/ncbi_gbench.sln +++ b/c++/compilers/vs2013/dll/build/gbench/ncbi_gbench.sln @@ -1,33 +1,33 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_CONFIGURE_", "UtilityProjects\_CONFIGURE_.vcxproj", "{8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA58}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_CONFIGURE_DIALOG_", "UtilityProjects\_CONFIGURE_DIALOG_.vcxproj", "{6DEFDB58-C014-4026-A166-299146BD9947}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_CONFIGURE_", "UtilityProjects\_CONFIGURE_.vcxproj", "{8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA58}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - DebugDLL|Win32 = DebugDLL|Win32 DebugDLL|x64 = DebugDLL|x64 - ReleaseDLL|Win32 = ReleaseDLL|Win32 + DebugDLL|x86 = DebugDLL|x86 ReleaseDLL|x64 = ReleaseDLL|x64 + ReleaseDLL|x86 = ReleaseDLL|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA58}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA58}.DebugDLL|Win32.Build.0 = DebugDLL|Win32 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA58}.DebugDLL|x64.ActiveCfg = DebugDLL|x64 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA58}.DebugDLL|x64.Build.0 = DebugDLL|x64 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA58}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA58}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA58}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA58}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 - {6DEFDB58-C014-4026-A166-299146BD9947}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32 - {6DEFDB58-C014-4026-A166-299146BD9947}.DebugDLL|Win32.Build.0 = DebugDLL|Win32 {6DEFDB58-C014-4026-A166-299146BD9947}.DebugDLL|x64.ActiveCfg = DebugDLL|x64 {6DEFDB58-C014-4026-A166-299146BD9947}.DebugDLL|x64.Build.0 = DebugDLL|x64 - {6DEFDB58-C014-4026-A166-299146BD9947}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32 - {6DEFDB58-C014-4026-A166-299146BD9947}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32 + {6DEFDB58-C014-4026-A166-299146BD9947}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32 + {6DEFDB58-C014-4026-A166-299146BD9947}.DebugDLL|x86.Build.0 = DebugDLL|Win32 {6DEFDB58-C014-4026-A166-299146BD9947}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 {6DEFDB58-C014-4026-A166-299146BD9947}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + {6DEFDB58-C014-4026-A166-299146BD9947}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32 + {6DEFDB58-C014-4026-A166-299146BD9947}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA58}.DebugDLL|x64.ActiveCfg = DebugDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA58}.DebugDLL|x64.Build.0 = DebugDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA58}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA58}.DebugDLL|x86.Build.0 = DebugDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA58}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA58}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA58}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA58}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/c++/compilers/vs2013/dll/build/gui/ncbi_gui_dll.sln b/c++/compilers/vs2013/dll/build/gui/ncbi_gui_dll.sln index 80e21b23..f76dc114 100644 --- a/c++/compilers/vs2013/dll/build/gui/ncbi_gui_dll.sln +++ b/c++/compilers/vs2013/dll/build/gui/ncbi_gui_dll.sln @@ -1,33 +1,33 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_CONFIGURE_", "UtilityProjects\_CONFIGURE_.vcxproj", "{8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA56}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_CONFIGURE_DIALOG_", "UtilityProjects\_CONFIGURE_DIALOG_.vcxproj", "{9BAE6EEC-8C80-44F0-84A9-3379631A8654}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_CONFIGURE_", "UtilityProjects\_CONFIGURE_.vcxproj", "{8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA56}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - DebugDLL|Win32 = DebugDLL|Win32 DebugDLL|x64 = DebugDLL|x64 - ReleaseDLL|Win32 = ReleaseDLL|Win32 + DebugDLL|x86 = DebugDLL|x86 ReleaseDLL|x64 = ReleaseDLL|x64 + ReleaseDLL|x86 = ReleaseDLL|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA56}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA56}.DebugDLL|Win32.Build.0 = DebugDLL|Win32 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA56}.DebugDLL|x64.ActiveCfg = DebugDLL|x64 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA56}.DebugDLL|x64.Build.0 = DebugDLL|x64 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA56}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA56}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA56}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA56}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 - {9BAE6EEC-8C80-44F0-84A9-3379631A8654}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32 - {9BAE6EEC-8C80-44F0-84A9-3379631A8654}.DebugDLL|Win32.Build.0 = DebugDLL|Win32 {9BAE6EEC-8C80-44F0-84A9-3379631A8654}.DebugDLL|x64.ActiveCfg = DebugDLL|x64 {9BAE6EEC-8C80-44F0-84A9-3379631A8654}.DebugDLL|x64.Build.0 = DebugDLL|x64 - {9BAE6EEC-8C80-44F0-84A9-3379631A8654}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32 - {9BAE6EEC-8C80-44F0-84A9-3379631A8654}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32 + {9BAE6EEC-8C80-44F0-84A9-3379631A8654}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32 + {9BAE6EEC-8C80-44F0-84A9-3379631A8654}.DebugDLL|x86.Build.0 = DebugDLL|Win32 {9BAE6EEC-8C80-44F0-84A9-3379631A8654}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 {9BAE6EEC-8C80-44F0-84A9-3379631A8654}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + {9BAE6EEC-8C80-44F0-84A9-3379631A8654}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32 + {9BAE6EEC-8C80-44F0-84A9-3379631A8654}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA56}.DebugDLL|x64.ActiveCfg = DebugDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA56}.DebugDLL|x64.Build.0 = DebugDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA56}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA56}.DebugDLL|x86.Build.0 = DebugDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA56}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA56}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA56}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA56}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/c++/compilers/vs2013/dll/build/ncbi_cpp_dll.sln b/c++/compilers/vs2013/dll/build/ncbi_cpp_dll.sln index 55e5b0e2..ec1ea742 100644 --- a/c++/compilers/vs2013/dll/build/ncbi_cpp_dll.sln +++ b/c++/compilers/vs2013/dll/build/ncbi_cpp_dll.sln @@ -1,33 +1,33 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_CONFIGURE_", "UtilityProjects\_CONFIGURE_.vcxproj", "{8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAAC9}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_CONFIGURE_DIALOG_", "UtilityProjects\_CONFIGURE_DIALOG_.vcxproj", "{67EC51FA-3A0D-46B8-8F89-49EE209C8CB8}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_CONFIGURE_", "UtilityProjects\_CONFIGURE_.vcxproj", "{8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAAC9}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - DebugDLL|Win32 = DebugDLL|Win32 DebugDLL|x64 = DebugDLL|x64 - ReleaseDLL|Win32 = ReleaseDLL|Win32 + DebugDLL|x86 = DebugDLL|x86 ReleaseDLL|x64 = ReleaseDLL|x64 + ReleaseDLL|x86 = ReleaseDLL|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAAC9}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAAC9}.DebugDLL|Win32.Build.0 = DebugDLL|Win32 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAAC9}.DebugDLL|x64.ActiveCfg = DebugDLL|x64 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAAC9}.DebugDLL|x64.Build.0 = DebugDLL|x64 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAAC9}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAAC9}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAAC9}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAAC9}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 - {67EC51FA-3A0D-46B8-8F89-49EE209C8CB8}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32 - {67EC51FA-3A0D-46B8-8F89-49EE209C8CB8}.DebugDLL|Win32.Build.0 = DebugDLL|Win32 {67EC51FA-3A0D-46B8-8F89-49EE209C8CB8}.DebugDLL|x64.ActiveCfg = DebugDLL|x64 {67EC51FA-3A0D-46B8-8F89-49EE209C8CB8}.DebugDLL|x64.Build.0 = DebugDLL|x64 - {67EC51FA-3A0D-46B8-8F89-49EE209C8CB8}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32 - {67EC51FA-3A0D-46B8-8F89-49EE209C8CB8}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32 + {67EC51FA-3A0D-46B8-8F89-49EE209C8CB8}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32 + {67EC51FA-3A0D-46B8-8F89-49EE209C8CB8}.DebugDLL|x86.Build.0 = DebugDLL|Win32 {67EC51FA-3A0D-46B8-8F89-49EE209C8CB8}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 {67EC51FA-3A0D-46B8-8F89-49EE209C8CB8}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + {67EC51FA-3A0D-46B8-8F89-49EE209C8CB8}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32 + {67EC51FA-3A0D-46B8-8F89-49EE209C8CB8}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAAC9}.DebugDLL|x64.ActiveCfg = DebugDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAAC9}.DebugDLL|x64.Build.0 = DebugDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAAC9}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAAC9}.DebugDLL|x86.Build.0 = DebugDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAAC9}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAAC9}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAAC9}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAAC9}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/c++/compilers/vs2013/make.bat b/c++/compilers/vs2013/make.bat index 8ebc67ef..88d4e1ff 100644 --- a/c++/compilers/vs2013/make.bat +++ b/c++/compilers/vs2013/make.bat @@ -1,5 +1,5 @@ @ECHO OFF -REM $Id: make.bat 485599 2015-11-24 13:11:05Z ivanov $ +REM $Id: make.bat 509501 2016-08-05 19:08:31Z fukanchi $ REM =========================================================================== REM REM PUBLIC DOMAIN NOTICE @@ -62,7 +62,9 @@ set libdll=%~3 set arch=%~4 set archw=Win32 -if _%arch%_ == _64_ set archw=x64 +set archwc=x86 +if _%arch%_ == _64_ set archw=x64 +if _%arch%_ == _64_ set archwc=x64 shift shift @@ -81,9 +83,9 @@ rem ---------------------------------------------------------------------------- :NOARGS if exist configure_make.bat ( - configure_make.bat + configure_make.bat ) else ( - goto USAGE + goto USAGE ) :USAGE @@ -152,7 +154,7 @@ if not "%with_openmp%" == "" ( time /t echo INFO: Configure "%libdll%\%solution% [ReleaseDLL|%arch%]" -%DEVENV% %libdll%\build\%solution%.sln /build "ReleaseDLL|%archw%" /project "_CONFIGURE_" +%DEVENV% %libdll%\build\%solution%.sln /build "ReleaseDLL|%archwc%" /project "_CONFIGURE_" if errorlevel 1 goto ABORT if not _%cmd% == _make goto COMPLETE diff --git a/c++/compilers/vs2013/ptb.bat b/c++/compilers/vs2013/ptb.bat index 0f39f160..c7560219 100644 --- a/c++/compilers/vs2013/ptb.bat +++ b/c++/compilers/vs2013/ptb.bat @@ -1,5 +1,5 @@ @echo off -REM $Id: ptb.bat 434581 2014-05-08 16:47:33Z gouriano $ +REM $Id: ptb.bat 507295 2016-07-18 15:40:58Z gouriano $ REM =========================================================================== REM REM PUBLIC DOMAIN NOTICE @@ -51,6 +51,10 @@ set PTBGUI="%TREE_ROOT%\src\build-system\project_tree_builder_gui\bin\ptbgui.jar set DEFPTB_VERSION_FILE=%TREE_ROOT%\src\build-system\ptb_version.txt set PTB_INI=%TREE_ROOT%\src\build-system\project_tree_builder.ini set PTB_SLN=%BUILD_TREE_ROOT%\static\build\UtilityProjects\PTB.sln +set NCBICONF_MSVC=%TREE_ROOT%\include\common\config\ncbiconf_msvc_site.h +if exist "%NCBICONF_MSVC%" ( + set NCBICONF_MSVC= +) REM --- get solution dir --- call :XSLNPATH %SLN_PATH% @@ -199,6 +203,9 @@ if not exist "%PTB_EXE%" ( echo ****************************************************************************** rem --- @echo msbuild "%BUILD_TREE_ROOT%\static\build\ncbi_cpp.sln" /t:"project_tree_builder_exe:Rebuild" /p:Configuration=ReleaseDLL;Platform=%PTB_PLATFORM% /maxcpucount:1 rem --- msbuild "%BUILD_TREE_ROOT%\static\build\ncbi_cpp.sln" /t:"project_tree_builder_exe:Rebuild" /p:Configuration=ReleaseDLL;Platform=%PTB_PLATFORM% /maxcpucount:1 + if not "%NCBICONF_MSVC%"=="" ( + echo // > "%NCBICONF_MSVC%" + ) if exist "%PTB_SLN%" ( @echo %DEVENV% "%PTB_SLN%" /rebuild "ReleaseDLL|%PTB_PLATFORM%" /project "project_tree_builder.exe" %DEVENV% "%PTB_SLN%" /rebuild "ReleaseDLL|%PTB_PLATFORM%" /project "project_tree_builder.exe" @@ -206,6 +213,9 @@ if not exist "%PTB_EXE%" ( @echo %DEVENV% "%BUILD_TREE_ROOT%\static\build\ncbi_cpp.sln" /rebuild "ReleaseDLL|%PTB_PLATFORM%" /project "project_tree_builder.exe" %DEVENV% "%BUILD_TREE_ROOT%\static\build\ncbi_cpp.sln" /rebuild "ReleaseDLL|%PTB_PLATFORM%" /project "project_tree_builder.exe" ) + if not "%NCBICONF_MSVC%"=="" ( + del "%NCBICONF_MSVC%" + ) ) else ( echo ****************************************************************************** echo Using PREBUILT project tree builder at %PTB_EXE% diff --git a/c++/compilers/vs2013/static/build/gui/ncbi_gui.sln b/c++/compilers/vs2013/static/build/gui/ncbi_gui.sln index a2bae451..da8a9e59 100644 --- a/c++/compilers/vs2013/static/build/gui/ncbi_gui.sln +++ b/c++/compilers/vs2013/static/build/gui/ncbi_gui.sln @@ -1,33 +1,33 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_CONFIGURE_", "UtilityProjects\_CONFIGURE_.vcxproj", "{8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA7E}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_CONFIGURE_DIALOG_", "UtilityProjects\_CONFIGURE_DIALOG_.vcxproj", "{FDC9447A-C7F1-492D-B84F-D54A1E610F16}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_CONFIGURE_", "UtilityProjects\_CONFIGURE_.vcxproj", "{8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA7E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - DebugDLL|Win32 = DebugDLL|Win32 DebugDLL|x64 = DebugDLL|x64 - ReleaseDLL|Win32 = ReleaseDLL|Win32 + DebugDLL|x86 = DebugDLL|x86 ReleaseDLL|x64 = ReleaseDLL|x64 + ReleaseDLL|x86 = ReleaseDLL|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA7E}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA7E}.DebugDLL|Win32.Build.0 = DebugDLL|Win32 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA7E}.DebugDLL|x64.ActiveCfg = DebugDLL|x64 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA7E}.DebugDLL|x64.Build.0 = DebugDLL|x64 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA7E}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA7E}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA7E}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA7E}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 - {FDC9447A-C7F1-492D-B84F-D54A1E610F16}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32 - {FDC9447A-C7F1-492D-B84F-D54A1E610F16}.DebugDLL|Win32.Build.0 = DebugDLL|Win32 {FDC9447A-C7F1-492D-B84F-D54A1E610F16}.DebugDLL|x64.ActiveCfg = DebugDLL|x64 {FDC9447A-C7F1-492D-B84F-D54A1E610F16}.DebugDLL|x64.Build.0 = DebugDLL|x64 - {FDC9447A-C7F1-492D-B84F-D54A1E610F16}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32 - {FDC9447A-C7F1-492D-B84F-D54A1E610F16}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32 + {FDC9447A-C7F1-492D-B84F-D54A1E610F16}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32 + {FDC9447A-C7F1-492D-B84F-D54A1E610F16}.DebugDLL|x86.Build.0 = DebugDLL|Win32 {FDC9447A-C7F1-492D-B84F-D54A1E610F16}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 {FDC9447A-C7F1-492D-B84F-D54A1E610F16}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + {FDC9447A-C7F1-492D-B84F-D54A1E610F16}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32 + {FDC9447A-C7F1-492D-B84F-D54A1E610F16}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA7E}.DebugDLL|x64.ActiveCfg = DebugDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA7E}.DebugDLL|x64.Build.0 = DebugDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA7E}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA7E}.DebugDLL|x86.Build.0 = DebugDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA7E}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA7E}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA7E}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA7E}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/c++/compilers/vs2013/static/build/ncbi_cpp.sln b/c++/compilers/vs2013/static/build/ncbi_cpp.sln index 38ca7de8..c972e4c8 100644 --- a/c++/compilers/vs2013/static/build/ncbi_cpp.sln +++ b/c++/compilers/vs2013/static/build/ncbi_cpp.sln @@ -6,28 +6,28 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_CONFIGURE_", "UtilityProje EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - DebugDLL|Win32 = DebugDLL|Win32 DebugDLL|x64 = DebugDLL|x64 - ReleaseDLL|Win32 = ReleaseDLL|Win32 + DebugDLL|x86 = DebugDLL|x86 ReleaseDLL|x64 = ReleaseDLL|x64 + ReleaseDLL|x86 = ReleaseDLL|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {E7DBEF6D-5DA9-4B0D-9375-C3F26659827B}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32 - {E7DBEF6D-5DA9-4B0D-9375-C3F26659827B}.DebugDLL|Win32.Build.0 = DebugDLL|Win32 {E7DBEF6D-5DA9-4B0D-9375-C3F26659827B}.DebugDLL|x64.ActiveCfg = DebugDLL|x64 {E7DBEF6D-5DA9-4B0D-9375-C3F26659827B}.DebugDLL|x64.Build.0 = DebugDLL|x64 - {E7DBEF6D-5DA9-4B0D-9375-C3F26659827B}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32 - {E7DBEF6D-5DA9-4B0D-9375-C3F26659827B}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32 + {E7DBEF6D-5DA9-4B0D-9375-C3F26659827B}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32 + {E7DBEF6D-5DA9-4B0D-9375-C3F26659827B}.DebugDLL|x86.Build.0 = DebugDLL|Win32 {E7DBEF6D-5DA9-4B0D-9375-C3F26659827B}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 {E7DBEF6D-5DA9-4B0D-9375-C3F26659827B}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA105}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA105}.DebugDLL|Win32.Build.0 = DebugDLL|Win32 + {E7DBEF6D-5DA9-4B0D-9375-C3F26659827B}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32 + {E7DBEF6D-5DA9-4B0D-9375-C3F26659827B}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32 {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA105}.DebugDLL|x64.ActiveCfg = DebugDLL|x64 {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA105}.DebugDLL|x64.Build.0 = DebugDLL|x64 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA105}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA105}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA105}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA105}.DebugDLL|x86.Build.0 = DebugDLL|Win32 {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA105}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA105}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA105}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA105}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/c++/compilers/vs2013/user/build/ncbi_user.sln b/c++/compilers/vs2013/user/build/ncbi_user.sln index 7cf10adb..04aa8233 100644 --- a/c++/compilers/vs2013/user/build/ncbi_user.sln +++ b/c++/compilers/vs2013/user/build/ncbi_user.sln @@ -1,33 +1,33 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_CONFIGURE_", "UtilityProjects\_CONFIGURE_.vcxproj", "{8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA108}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_CONFIGURE_DIALOG_", "UtilityProjects\_CONFIGURE_DIALOG_.vcxproj", "{EB043EAF-58D4-4179-AC32-538D9059BB8B}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_CONFIGURE_", "UtilityProjects\_CONFIGURE_.vcxproj", "{8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA108}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - DebugDLL|Win32 = DebugDLL|Win32 DebugDLL|x64 = DebugDLL|x64 - ReleaseDLL|Win32 = ReleaseDLL|Win32 + DebugDLL|x86 = DebugDLL|x86 ReleaseDLL|x64 = ReleaseDLL|x64 + ReleaseDLL|x86 = ReleaseDLL|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA108}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA108}.DebugDLL|Win32.Build.0 = DebugDLL|Win32 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA108}.DebugDLL|x64.ActiveCfg = DebugDLL|x64 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA108}.DebugDLL|x64.Build.0 = DebugDLL|x64 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA108}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA108}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA108}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 - {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA108}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 - {EB043EAF-58D4-4179-AC32-538D9059BB8B}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32 - {EB043EAF-58D4-4179-AC32-538D9059BB8B}.DebugDLL|Win32.Build.0 = DebugDLL|Win32 {EB043EAF-58D4-4179-AC32-538D9059BB8B}.DebugDLL|x64.ActiveCfg = DebugDLL|x64 {EB043EAF-58D4-4179-AC32-538D9059BB8B}.DebugDLL|x64.Build.0 = DebugDLL|x64 - {EB043EAF-58D4-4179-AC32-538D9059BB8B}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32 - {EB043EAF-58D4-4179-AC32-538D9059BB8B}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32 + {EB043EAF-58D4-4179-AC32-538D9059BB8B}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32 + {EB043EAF-58D4-4179-AC32-538D9059BB8B}.DebugDLL|x86.Build.0 = DebugDLL|Win32 {EB043EAF-58D4-4179-AC32-538D9059BB8B}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 {EB043EAF-58D4-4179-AC32-538D9059BB8B}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + {EB043EAF-58D4-4179-AC32-538D9059BB8B}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32 + {EB043EAF-58D4-4179-AC32-538D9059BB8B}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA108}.DebugDLL|x64.ActiveCfg = DebugDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA108}.DebugDLL|x64.Build.0 = DebugDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA108}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA108}.DebugDLL|x86.Build.0 = DebugDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA108}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA108}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA108}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA108}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/c++/compilers/vs2015/Makefile.WinMain.app.msvc b/c++/compilers/vs2015/Makefile.WinMain.app.msvc new file mode 100644 index 00000000..3ccfcd0c --- /dev/null +++ b/c++/compilers/vs2015/Makefile.WinMain.app.msvc @@ -0,0 +1,11 @@ +[Rule] +Priority = 127 + + +[Linker] +subSystem = 2 + + +[AddToProject] +SourceFiles = ../../src/gui/winmain + diff --git a/c++/compilers/vs2015/Makefile.wxWidgets.app.msvc b/c++/compilers/vs2015/Makefile.wxWidgets.app.msvc new file mode 100644 index 00000000..1f2ace29 --- /dev/null +++ b/c++/compilers/vs2015/Makefile.wxWidgets.app.msvc @@ -0,0 +1,11 @@ +[Rule] +Priority = 127 + + +[Linker] +subSystem = 2 + + +[AddToProject] +; SourceFiles = ../../src/gui/winmain + diff --git a/c++/compilers/vs2015/build.sh b/c++/compilers/vs2015/build.sh new file mode 100644 index 00000000..81db32d7 --- /dev/null +++ b/c++/compilers/vs2015/build.sh @@ -0,0 +1,264 @@ +#! /bin/sh +# $Id: build.sh 498022 2016-04-12 18:52:45Z ivanov $ +# Author: Vladimir Ivanov (ivanov@ncbi.nlm.nih.gov) +# +# Build C++ Toolkit. + + +#---------------- Arguments ---------------- + +script="$0" +cfgs="${1:-DebugDLL ReleaseDLL}" +arch="$2" + + +#---------------- Configuration ---------------- + +# Configure with Unicode configurations enabled + +NCBI_CONFIG____ENABLEDUSERREQUESTS__NCBI_UNICODE=1 +export NCBI_CONFIG____ENABLEDUSERREQUESTS__NCBI_UNICODE +#NCBI_CONFIG____ENABLEDUSERREQUESTS__TWEAKVTUNE=1 +#export NCBI_CONFIG____ENABLEDUSERREQUESTS__TWEAKVTUNE + +# Bootstrap mode + +#PREBUILT_PTB_EXE=bootstrap +#export PREBUILT_PTB_EXE +#PREBUILT_DATATOOL_EXE=bootstrap +#export PREBUILT_DATATOOL_EXE + + +#---------------- Global variables ---------------- + +build_trees='static dll' +sol_static="ncbi_cpp.sln gui/ncbi_gui.sln" +sol_dll="ncbi_cpp_dll.sln gui/ncbi_gui_dll.sln" +timer="date +'%H:%M'" + +# TRUE if parallell project build system is enabled in Visual Studio +is_ppb=false +need_ppb_check=true + + + +#-------------- Functions -------------- + +error() +{ + echo "[`basename $script`] ERROR: $1" + exit 1 +} + +generate_vs2015_error_check_file() +{ + cat <<-EOF >$1 + /.*--* (Reb|B)uild( All | )started: Project:/ { + expendable = "" + } + + /^--* Project:/ { + expendable = "" + } + + /EXPENDABLE project/ { + expendable = \$0 + } + + /(| : |The source )([fatal ]*error [A-Z]*[0-9]* *: |The .* are both configured to produce|.*: error [0-9]*:|: general error |Error executing |ERROR: This project depends)/ { + if (!expendable) { + print \$0 + exit + } + } + EOF +} + +generate_simple_log() +{ + echo Parallel project build detected! Creating simplified log. + echo + + log=$1 + tree=$2 + sol=$3 + cfg=$4 + + # Get solution directory + sol_dir=`echo $sol | sed 's%/[^/]*$%%'` + if [ $sol_dir = $sol ] ; then + sol_dir='' + fi + + # Get built projects + projects=`grep '.*--* Build started:' $log | awk '{ sub(/^.* started:/, ""); gsub(/ /,"#"); print $0}'` + + for p in $projects ; do + echo "------$p" | awk '{gsub(/[#]/," "); print}' + prj_name=`echo $p | awk '{gsub(/[#,]/," "); print $2}'` +### cfg=`echo $p | awk '{gsub(/[#,]/," "); print $4}'` + + # Get path for specified project name from solution + s=`grep \"$prj_name\" $tree/build/$sol | awk '{gsub(/,/," "); print $4}' | sed -e 's%"%%g' -e 's%\\\%/%g' -e 's%.vcxproj%%'` + + target_dir=`echo $s | sed 's%/[^/]*$%%'` + test $target_dir = $s && target_dir='' + target_name=`echo $s | sed 's%^.*/%%'` + + # Path to regular logfile for current project + prj_log="$tree/build/$sol_dir/$target_dir/$cfg/$prj_name/$target_name.log" + + # Add it to new combined log + if test ! -f "$prj_log" ; then + # Not all projects have a log file in the ${prj_name} sub-directory + prj_log_short="$tree/build/$sol_dir/$target_dir/$cfg/$target_name.log" + if test ! -f "$prj_log_short" ; then + echo "BUILD_SYSTEM_ERROR: Cannot find log file for this project: $prj_log" + echo + continue + fi + prj_log=$prj_log_short + fi + # Remove 3 first bytes from logfile (EF BB BF) and some garbage from a multi-projects build + cat $prj_log | tr -d '\357\273\277' | sed 's/\( *\)1>/\1 /g' + echo + done + grep '.*========== Build:' $log + echo +} + + +#---------------- Main ---------------- + +# Get build dir +build_dir=`dirname $script` +build_dir=`(cd "$build_dir"; pwd)` + +if [ ! -d $build_dir ] ; then + error "Build directory $build_dir not found" + exit 1 +fi +cd $build_dir + +# Configuration to build configure +cfg_configure='ReleaseDLL' +out=".build.$$" + +# Get directory for build logfiles +log_dir="$build_dir/../../logs" +mkdir $log_dir >/dev/null 2>&1 +log_dir=`(cd "$log_dir"; pwd)` +rm $log_dir/* >/dev/null 2>&1 + + +chmod +x $build_dir/build_exec.bat +rm -f $build_dir/cfgs.log + + +# Configure + +for tree in $build_trees ; do + sols=`eval echo "$"sol_${tree}""` + for sol in $sols ; do + if test ! -f "$tree/build/$sol" ; then + echo "INFO: Solution not found, skipped." + continue + fi + alias=`echo $sol | sed -e 's|\\\\.*$||g' -e 's|_.*$||g'` + start=`eval $timer` + echo + echo Start time: $start + echo "INFO: Configure \"$tree\\$alias\"" + echo "Command line: " $build_dir/build_exec.bat "$tree\\build\\$sol" build "$arch" "$cfg_configure" "_CONFIGURE_" $out + $build_dir/build_exec.bat "$tree\\build\\$sol" build "$arch" "$cfg_configure" "_CONFIGURE_" $out >/dev/null + echo + status=$? + # Wait a bit to allow compiler to exit and flush logfile + sleep 20 + if $need_ppb_check; then + need_ppb_check=false + grep '^1>------ Build started:' $out >/dev/null 2>&1 && is_ppb=true + fi + if $is_ppb; then + generate_simple_log $out $tree "$sol" $cfg_configure > $out.simple + mv $out $cfg.configure.log + mv $out.simple $out + fi + cat $out + cat $out >> ${log_dir}/${tree}_${cfg_configure}.log + echo "Build time: $start - `eval $timer`" + echo STATUS = $status + if [ $status -ne 0 ] ; then + echo "FAILED: Configure $tree\\build\\$sol, $cfg_configure" + fi + rm -f $out >/dev/null 2>&1 + if [ $status -ne 0 ] ; then + exit 3 + fi + done +done + + + +# Generate errors check script + +check_awk=$build_dir/build_check.awk +generate_vs2015_error_check_file $check_awk + + +# Build + +for tree in $build_trees ; do + for cfg in $cfgs ; do + if [ $tree = dll ] ; then + echo "$cfg" | grep '.*DLL$' >/dev/null || continue + fi + sols=`eval echo "$"sol_${tree}""` + for sol in $sols ; do + if test ! -f "$tree/build/$sol" ; then + echo "INFO: Solution not found, skipped." + continue + fi + alias=`echo $sol | sed -e 's|\\\\.*$||g' -e 's|_.*$||g'` + start=`eval $timer` + echo + echo Start time: $start + echo "$tree,$sol,$cfg" >> $build_dir/cfgs.log + echo "INFO: Building \"$tree\\$cfg\\$alias\"" + echo "Command line: " $build_dir/build_exec.bat "$tree\\build\\$sol" build "$arch" "$cfg" "_BUILD_ALL_" $out + echo + $build_dir/build_exec.bat "$tree\\build\\$sol" build "$arch" "$cfg" "_BUILD_ALL_" $out >/dev/null + status=$? + # Wait a bit to allow compiler to exit and flush logfile + sleep 20 + if $is_ppb; then + generate_simple_log $out $tree "$sol" $cfg > $out.simple + mv $out $cfg.build.log + mv $out.simple $out + fi + cat $out + cat $out >> ${log_dir}/${tree}_${cfg}.log + echo "Build time: $start - `eval $timer`" + echo STATUS = $status + if [ $status -ne 0 ] ; then + # Check on errors (skip expendable projects) + failed="1" + awk -f $check_awk $out >$out.res 2>/dev/null && test ! -s $out.res && failed="0" + if [ "$failed" = "1" ]; then + echo "FAILED: Build $tree\\build\\$sol, $cfg" + echo "FAILED: Build $tree\\build\\$sol, $cfg" > failed.build.log + echo >> failed.build.log + cat $out >> failed.build.log + cat $tree/build/${sol}_watchers.txt > failed.watchers.log + fi + rm -f $out $out.res >/dev/null 2>&1 + if [ "$failed" = "1" ]; then + exit 4 + fi + fi + rm -f $out >/dev/null 2>&1 + done + done +done + +exit 0 diff --git a/c++/compilers/vs2015/build_exec.bat b/c++/compilers/vs2015/build_exec.bat new file mode 100644 index 00000000..2ce01647 --- /dev/null +++ b/c++/compilers/vs2015/build_exec.bat @@ -0,0 +1,51 @@ +@ECHO OFF +REM $Id: build_exec.bat 505228 2016-06-23 12:54:48Z ivanov $ +REM =========================================================================== +REM +REM PUBLIC DOMAIN NOTICE +REM National Center for Biotechnology Information +REM +REM This software/database is a "United States Government Work" under the +REM terms of the United States Copyright Act. It was written as part of +REM the author's official duties as a United States Government employee and +REM thus cannot be copyrighted. This software/database is freely available +REM to the public for use. The National Library of Medicine and the U.S. +REM Government have not placed any restriction on its use or reproduction. +REM +REM Although all reasonable efforts have been taken to ensure the accuracy +REM and reliability of the software and data, the NLM and the U.S. +REM Government do not and cannot warrant the performance or results that +REM may be obtained by using this software or data. The NLM and the U.S. +REM Government disclaim all warranties, express or implied, including +REM warranties of performance, merchantability or fitness for any particular +REM purpose. +REM +REM Please cite the author in any work or product based on this material. +REM +REM =========================================================================== +REM +REM Author: Vladimir Ivanov +REM +REM Auxiliary script for build.sh to run C++ build for specified project +REM and configuration. Cygwin cannot run devenv directly inside shell-script. +REM +REM =========================================================================== + +call msvcvars.bat + +if _%1% == _ goto be_abort +goto be_build + +:be_abort +rem You should specify logfile or you will not see an output +echo Usage: "%0 " +exit 1 + +:be_build +set arch=Win32 +if _%5_ == __CONFIGURE__ set arch=x86 +if _%3_ == _64_ set arch=x64 + +rem Next command should be executed last! No other code after it, please. + +%DEVENV% %1 /%2 "%4|%arch%" /project "%5" /out "%6" diff --git a/c++/compilers/vs2015/build_util.sh b/c++/compilers/vs2015/build_util.sh new file mode 100644 index 00000000..7d419333 --- /dev/null +++ b/c++/compilers/vs2015/build_util.sh @@ -0,0 +1,67 @@ +#! /bin/sh +# $Id: build_util.sh 492980 2016-02-23 16:24:57Z gouriano $ +# Author: Vladimir Ivanov (ivanov@ncbi.nlm.nih.gov) +# +# Utility functions for building C++ Toolkit. + + +#---------------- Arguments ---------------- + +arg="$1" + +script=`basename $0` +script_dir=`dirname $0` +script_dir=`(cd "$script_dir"; pwd)` + + + +#-------------- Functions -------------- + +error() +{ + echo "[$script] ERROR: $1" + exit 1 +} + + +#---------------- Main ---------------- + +case "$arg" in + + --with-openmp ) + + makefile="$script_dir/../../src/build-system/Makefile.mk.in.msvc" + if [ ! -f $makefile ] ; then + error "$makefile not found" + exit 1 + fi + tmp=/tmp/build_util_$$ + trap "rm -f $tmp $tmp.awk" 0 1 2 15 + + cat <<-EOF >$tmp.awk + /^\[Compiler\]/ { + comp = 1 + } + /^AdditionalOptions=/ { + if (comp == 1) { + gsub("/openmp","") + gsub("AdditionalOptions=","AdditionalOptions=/openmp ") + gsub(" ", " ") + comp = 0 + } + } + /.*/ { + print + } + EOF + awk -f $tmp.awk $makefile >$tmp || exit 1 + touch -r $makefile $tmp + cp -fp $tmp $makefile || exit 2 + ;; + + * ) + error "Unknown command: $arg" + ;; +esac + +exit 0 diff --git a/c++/compilers/vs2015/check.sh b/c++/compilers/vs2015/check.sh new file mode 100644 index 00000000..9b4458ef --- /dev/null +++ b/c++/compilers/vs2015/check.sh @@ -0,0 +1,276 @@ +#! /bin/sh +# $Id: check.sh 492980 2016-02-23 16:24:57Z gouriano $ +# Author: Vladimir Ivanov (ivanov@ncbi.nlm.nih.gov) +# +# Check C++ Toolkit in all previously built configurations +# (see 'cfgs.log', generated with 'build.sh' script). +# +# USAGE: +# check.sh {run | concat | concat_err | concat_cfg | load_to_db} +# +# Use 'run' command first, than use other commands. +# For 'concat_cfg' -- use 'run', 'concat' and 'concat_err' commands first. + + + +########### Arguments + +script="$0" +method="$1" + +# Maximum number of parallel running test configurations +max_tasks=2 +# Sleep timeout between checks on finished 'run' tasks (seconds) +sleeptime=60 + + +########## Functions + +Error() +{ + echo "[`basename $script`] ERROR: $1" + exit 1 +} + +ParseConfig() +{ + if [ -z "$1" ] ; then + Error "Unknown configuration name" + fi + x_tree=`echo $1 | sed -e 's/,.*$//'` + x_sol=`echo $1 | sed -e 's/^[^,]*,//' -e 's/,.*$//' -e 's/\.sln//' -e 's|\\\|/|g'` + x_cfg=`echo $1 | sed -e 's/^.*,//'` +} + +CopyConfigLogs() +{ + cat ${tasks_dir[$1]}/check.sh.log >> $res_log + cat ${tasks_dir[$1]}/check.sh.log >> \ + $build_dir/check.sh.${tasks_tree[$1]}_${tasks_cfg[$1]}.log +} + + + +########## Main + +errcode=0 + +# Get build directory +build_dir=`dirname $script` +build_dir=`(cd "$build_dir"; pwd)` +timer="date +'%H:%M'" + +if [ ! -d $build_dir ] ; then + Error "Build directory $build_dir not found" +fi +cd $build_dir || Error "Cannot change directory" + +res_log="$build_dir/check.sh.log" +res_concat="$build_dir/check.sh.out" +res_concat_err="$build_dir/check.sh.out_err" + +cfgs="`cat cfgs.log`" +if [ -z "$cfgs" ] ; then + Error "Build some configurations first" +fi + + +# --- Initialization + +case "$method" in + run ) + rm -f "$res_log" + rm -f "$build_dir/check.sh.*.log" > /dev/null 2>&1 + # Init checks + $build_dir/../../scripts/common/check/check_make_win_cfg.sh init || \ + Error "Check initialization failed" + # Init task list + i=0 + while [ $i -lt $max_tasks ] ; do + tasks_name[$i]="" + tasks_tree[$i]="" + tasks_cfg[$i]="" + tasks_dir[$i]="" + tasks_start[$i]="" + i=`expr $i + 1` + done + ;; + clean ) + # not implemented, 'clean' method is not used on Windows + exit 0 + ;; + concat ) + cp $res_log $res_concat + ;; + concat_err ) + egrep 'ERR \[|TO -' $res_log > $res_concat_err + ;; + concat_cfg ) + rm -f "$build_dir/check.sh.*.out_err" > /dev/null 2>&1 + ;; + load_to_db ) + rm -f "$build_dir/test_stat_load.log" > /dev/null 2>&1 + ;; + * ) + Error "Invalid method name" + ;; +esac + + + +# --- Run checks for each previously built configuration + + +for cfg in $cfgs ; do + + ParseConfig $cfg + cd $build_dir + + check_name=$x_tree/$x_sol/$x_cfg + check_dir="$x_tree/build/${x_sol}.check/$x_cfg" + if [ ! -d "$check_dir" ] ; then + Error "Check directory \"$check_dir\" not found" + fi + + # Special processing for 'run' to allow parallel test runs + + if [ "$method" = "run" ]; then + + while true; do + i=0 + idx=999 + + while [ $i -lt $max_tasks ]; do + # Find first free slot + if [ -z "${tasks_name[$i]}" ]; then + idx=$i + break + fi + # Check on finished tasks + if [ -f "${tasks_dir[$i]}/check.success" ]; then + idx=$i + fi + if [ -f "${tasks_dir[$i]}/check.failed" ]; then + idx=$i + errcode=1 + fi + if [ $idx -lt $max_tasks ]; then + CopyConfigLogs $idx + echo `eval $timer` + echo CHECK_$method: finished: ${tasks_name[$idx]} \(${tasks_start[idx]} - `eval $timer`\) + tasks_name[$idx]="" + break + fi + i=`expr $i + 1` + done + + if [ $idx -lt $max_tasks ]; then + # Run tests for current configuration $cfg + tasks_name[$idx]="$x_tree/$x_sol/$x_cfg" + tasks_tree[$idx]="$x_tree" + tasks_cfg[$idx]="$x_cfg" + tasks_dir[$idx]="$check_dir" + tasks_start[$idx]=`eval $timer` + + echo ${tasks_start[$idx]} + echo CHECK_$method: started : ${tasks_name[$idx]} + rm ${tasks_dir[$idx]}/check.success ${tasks_dir[$idx]}/check.failed >/dev/null 2>&1 + + ../../scripts/common/check/check_make_win_cfg.sh create "$x_sol" "$x_tree" "$x_cfg" || \ + Error "Creating check script for \"$check_dir\" failed" + test -x "${tasks_dir[$idx]}/check.sh" || \ + Error "Cannot find $check_dir/check.sh" + + ${tasks_dir[$idx]}/check.sh run >/dev/null 2>&1 & + + # Move to next configuration + break + else + # All slots busy -- waiting + sleep $sleeptime + fi + done + + continue + fi + + + # All actions except 'run' + + test -x "$check_dir/check.sh" || \ + Error "Run checks first. $check_dir/check.sh not found." + + echo `eval $timer` + echo CHECK_$method: $check_name + + case "$method" in + concat ) + $check_dir/check.sh concat + cat $check_dir/check.sh.out >> $res_concat + ;; + concat_err ) + $check_dir/check.sh concat_err + cat $check_dir/check.sh.out_err >> $res_concat_err + ;; + concat_cfg ) + # Copy log entries + egrep 'ERR \[|TO -' $check_dir/check.sh.log >> $build_dir/check.sh.${x_tree}_${x_cfg}.out_err + # See below for copying of failed tests outputs, + # it should be printed after log entries for all configurations. + ;; + load_to_db ) + $check_dir/check.sh load_to_db + ;; + esac +done + + +# --- Waiting unfinished tasks for 'run' + +if [ "$method" = "run" ]; then + while true; do + i=0 + idx=999 + active=false + + while [ $i -lt $max_tasks ]; do + if [ -n "${tasks_name[$i]}" ]; then + # Check on finished tasks + if [ -f "${tasks_dir[$i]}/check.success" ]; then + idx=$i + fi + if [ -f "${tasks_dir[$i]}/check.failed" ]; then + idx=$i + errcode=1 + fi + if [ $idx -lt $max_tasks ]; then + CopyConfigLogs $idx + echo `eval $timer` + echo CHECK_$method: finished: ${tasks_name[$idx]} \(${tasks_start[$idx]} - `eval $timer`\) + tasks_name[$idx]="" + idx=999 + else + active=true + fi + fi + i=`expr $i + 1` + done + + if $active; then + sleep $sleeptime + else + break + fi + done +fi + +if [ "$method" = "concat_cfg" ]; then + for cfg in $cfgs ; do + ParseConfig $cfg + cd $build_dir + check_dir="$x_tree/build/${x_sol}.check/$x_cfg" + cat $check_dir/check.sh.out_err >> $build_dir/check.sh.${x_tree}_${x_cfg}.out_err + done +fi + +exit $errcode diff --git a/c++/compilers/vs2015/configure.bat b/c++/compilers/vs2015/configure.bat new file mode 100644 index 00000000..14339f6f --- /dev/null +++ b/c++/compilers/vs2015/configure.bat @@ -0,0 +1,384 @@ +@echo off +REM $Id: configure.bat 505229 2016-06-23 13:04:20Z gouriano $ +REM =========================================================================== +REM +REM PUBLIC DOMAIN NOTICE +REM National Center for Biotechnology Information +REM +REM This software/database is a "United States Government Work" under the +REM terms of the United States Copyright Act. It was written as part of +REM the author's official duties as a United States Government employee and +REM thus cannot be copyrighted. This software/database is freely available +REM to the public for use. The National Library of Medicine and the U.S. +REM Government have not placed any restriction on its use or reproduction. +REM +REM Although all reasonable efforts have been taken to ensure the accuracy +REM and reliability of the software and data, the NLM and the U.S. +REM Government do not and cannot warrant the performance or results that +REM may be obtained by using this software or data. The NLM and the U.S. +REM Government disclaim all warranties, express or implied, including +REM warranties of performance, merchantability or fitness for any particular +REM purpose. +REM +REM Please cite the author in any work or product based on this material. +REM +REM =========================================================================== +REM +REM Author: Andrei Gourianov +REM +REM Configure MSVC solution and projects +REM +REM =========================================================================== + +setlocal + +set sln_name=ncbi_cpp +set use_projectlst=scripts/projects/ncbi_cpp.lst + +set use_savedcfg= +set use_gui=no +set maybe_gui=yes +set use_debug=yes +set use_dll=no +set use_64=no +set use_staticstd=no +set use_arch=Win32 +set use_flags= +set help_req=no +set srcroot=../.. + +REM ----------------------------------------------------------------------------- +REM silently ignored options +set noops= +set noops=%noops% --without-optimization +set noops=%noops% --with-profiling +set noops=%noops% --with-tcheck +set noops=%noops% --with-static +set noops=%noops% --with-plugin-auto-load +set noops=%noops% --with-bin-release +set noops=%noops% --with-mt +set noops=%noops% --without-exe +set noops=%noops% --with-runpath +set noops=%noops% --with-lfs +set noops=%noops% --with-autodep +set noops=%noops% --with-build-root +set noops=%noops% --with-fake-root +set noops=%noops% --without-suffix +set noops=%noops% --with-hostspec +set noops=%noops% --without-version +set noops=%noops% --with-build-root-sfx +set noops=%noops% --without-execopy +set noops=%noops% --with-bincopy +set noops=%noops% --with-lib-rebuilds +set noops=%noops% --with-lib-rebuilds +set noops=%noops% --without-deactivation +set noops=%noops% --without-makefile-auto-update +set noops=%noops% --without-flat-makefile +set noops=%noops% --with-check +set noops=%noops% --with-check-tools +set noops=%noops% --with-ncbi-public +set noops=%noops% --with-strip +set noops=%noops% --with-pch +set noops=%noops% --with-caution +set noops=%noops% --without-caution +set noops=%noops% --without-ccache +set noops=%noops% --with-distcc +set noops=%noops% --without-ncbi-c +set noops=%noops% --without-sss +set noops=%noops% --without-utils +set noops=%noops% --without-sssdb +set noops=%noops% --with-included-sss +set noops=%noops% --with-z +set noops=%noops% --without-z +set noops=%noops% --with-bz2 +set noops=%noops% --without-bz2 +set noops=%noops% --with-lzo +set noops=%noops% --without-lzo +set noops=%noops% --with-pcre +set noops=%noops% --without-pcre +set noops=%noops% --with-gnutls +set noops=%noops% --without-gnutls +set noops=%noops% --with-openssl +set noops=%noops% --without-openssl +set noops=%noops% --without-sybase +set noops=%noops% --with-sybase-local +set noops=%noops% --with-sybase-new +set noops=%noops% --without-ftds +set noops=%noops% --with-ftds +set noops=%noops% --without-ftds-renamed +set noops=%noops% --without-mysql +set noops=%noops% --with-mysql +set noops=%noops% --without-opengl +set noops=%noops% --with-opengl +set noops=%noops% --without-mesa +set noops=%noops% --with-mesa +set noops=%noops% --without-glut +set noops=%noops% --with-glut +set noops=%noops% --without-wxwin +set noops=%noops% --with-wxwin +set noops=%noops% --without-wxwidgets +set noops=%noops% --with-wxwidgets +set noops=%noops% --with-wxwidgets-ucs +set noops=%noops% --without-wxwidgets-ucs +set noops=%noops% --without-freetype +set noops=%noops% --with-freetype +set noops=%noops% --without-fastcgi +set noops=%noops% --with-fastcgi +set noops=%noops% --with-fastcgi +set noops=%noops% --without-bdb +set noops=%noops% --with-bdb +set noops=%noops% --without-sp +set noops=%noops% --without-orbacus +set noops=%noops% --with-orbacus +set noops=%noops% --with-odbc +set noops=%noops% --with-python +set noops=%noops% --without-python +set noops=%noops% --with-boost +set noops=%noops% --without-boost +set noops=%noops% --with-boost-tag +set noops=%noops% --without-boost-tag +set noops=%noops% --with-sqlite +set noops=%noops% --without-sqlite +set noops=%noops% --with-sqlite3 +set noops=%noops% --without-sqlite3 +set noops=%noops% --with-icu +set noops=%noops% --without-icu +set noops=%noops% --with-expat +set noops=%noops% --without-expat +set noops=%noops% --with-sablot +set noops=%noops% --without-sablot +set noops=%noops% --with-libxml +set noops=%noops% --without-libxml +set noops=%noops% --with-libxslt +set noops=%noops% --without-libxslt +set noops=%noops% --with-xerces +set noops=%noops% --without-xerces +set noops=%noops% --with-xalan +set noops=%noops% --without-xalan +set noops=%noops% --with-oechem +set noops=%noops% --without-oechem +set noops=%noops% --with-sge +set noops=%noops% --without-sge +set noops=%noops% --with-muparser +set noops=%noops% --without-muparser +set noops=%noops% --with-hdf5 +set noops=%noops% --without-hdf5 +set noops=%noops% --with-gif +set noops=%noops% --without-gif +set noops=%noops% --with-jpeg +set noops=%noops% --without-jpeg \ +set noops=%noops% --with-png +set noops=%noops% --without-png +set noops=%noops% --with-tiff +set noops=%noops% --without-tiff +set noops=%noops% --with-xpm +set noops=%noops% --without-xpm +set noops=%noops% --without-local-lbsm +set noops=%noops% --without-ncbi-crypt +set noops=%noops% --without-connext +set noops=%noops% --without-serial +set noops=%noops% --without-objects +set noops=%noops% --without-dbapi +set noops=%noops% --without-app +set noops=%noops% --without-ctools +set noops=%noops% --without-gui +set noops=%noops% --without-algo +set noops=%noops% --without-internal +set noops=%noops% --with-gbench +set noops=%noops% --without-gbench +set noops=%noops% --with-x + + +set initial_dir=%CD% +set script_name=%0 +cd %~p0 +for /f "delims=" %%a in ('cd') do (set script_dir=%%a) +cd %srcroot% +for /f "delims=" %%a in ('cd') do (set srcroot=%%a) +cd %initial_dir% + +REM -------------------------------------------------------------------------------- +REM parse arguments + +set unknown= +set ignore_unknown=no +set dest= +:PARSEARGS +if "%1"=="" goto ENDPARSEARGS +if "%dest%"=="lst" (set use_projectlst=%1& set dest=& goto CONTINUEPARSEARGS) +if "%dest%"=="cfg" (set use_savedcfg=%~1& set dest=& goto CONTINUEPARSEARGS) +if "%1"=="--help" (set help_req=yes& goto CONTINUEPARSEARGS) +if "%1"=="--with-configure-dialog" (set use_gui=yes& goto CONTINUEPARSEARGS) +if "%1"=="--without-configure-dialog" (set use_gui=no& goto CONTINUEPARSEARGS) +if "%1"=="--with-saved-settings" (set dest=cfg& goto CONTINUEPARSEARGS) +if "%1"=="--without-debug" (set use_debug=no& goto CONTINUEPARSEARGS) +if "%1"=="--with-debug" (set use_debug=yes& goto CONTINUEPARSEARGS) +if "%1"=="--without-dll" (set use_dll=no& goto CONTINUEPARSEARGS) +if "%1"=="--with-dll" (set use_dll=yes& goto CONTINUEPARSEARGS) +if "%1"=="--with-64" (set use_64=yes& goto CONTINUEPARSEARGS) +if "%1"=="--with-static-exe" (set use_staticstd=yes& goto CONTINUEPARSEARGS) +if "%1"=="--with-projects" (set dest=lst& goto CONTINUEPARSEARGS) +if "%1"=="--ignore-unsupported-options" (set ignore_unknown=yes& goto CONTINUEPARSEARGS) +set unknown=%unknown% %1 +:CONTINUEPARSEARGS +set maybe_gui=no +shift +goto PARSEARGS +:ENDPARSEARGS +if "%maybe_gui%"=="yes" ( + set use_gui=yes +) + +REM -------------------------------------------------------------------------------- +REM check and report unknown options + +set invalid_unknown=no +for %%u in (%unknown%) do ( + call :CHECKUNKNOWN %%u +) +if "%invalid_unknown%"=="yes" exit /b 1 +goto DONEUNKNOWN + +:CHECKUNKNOWN +for %%n in (%noops%) do ( + if "%1"=="%%n" ( + echo Ignored: %1 + goto :eof + ) +) +for /f "eol=-" %%a in ('echo %1') do goto :eof +if "%ignore_unknown%"=="no" ( + echo Unsupported option: %1 + set invalid_unknown=yes +) else ( + echo Ignored unsupported: %1 +) +goto :eof +:DONEUNKNOWN + +REM -------------------------------------------------------------------------------- +REM print usage + +:PRINTUSAGE +if "%help_req%"=="yes" ( + echo USAGE: + echo %script_name% [OPTION]... + echo SYNOPSIS: + echo configure NCBI C++ toolkit for MSVC build system. + echo OPTIONS: + echo --help -- print Usage + echo --with-configure-dialog -- use Configuration GUI application + echo --without-configure-dialog -- do not use Configuration GUI application + echo --with-saved-settings=FILE -- load configuration settings from FILE + echo --without-debug -- build non-debug versions of libs and apps + echo --with-debug -- build debug versions of libs and apps + echo --without-dll -- build all toolkit libraries as static ones + echo --with-dll -- assemble toolkit libraries into DLLs + echo where requested + echo --with-64 -- compile to 64-bit code + echo --with-static-exe -- use static C++ standard libraries + echo --with-projects=FILE -- build projects listed in "%srcroot%\FILE" + echo FILE can also be a name of a subdirectory + echo examples: --with-projects=src/corelib + echo --with-projects=scripts/projects/ncbi_cpp.lst + echo --ignore-unsupported-options -- ignore unsupported options + exit /b 0 +) + +REM -------------------------------------------------------------------------------- +REM target architecture, solution path, configuration and flags + +if "%use_64%"=="yes" ( + set use_arch=x64 +) else ( + set use_arch=Win32 +) +if "%use_dll%"=="yes" ( + if "%use_debug%"=="yes" ( + set CONFIGURATION=DebugDLL + ) else ( + set CONFIGURATION=ReleaseDLL + ) +) else ( + if "%use_debug%"=="yes" ( + if "%use_staticstd%"=="yes" ( + set CONFIGURATION=DebugMT + ) else ( + set CONFIGURATION=DebugDLL + ) + ) else ( + if "%use_staticstd%"=="yes" ( + set CONFIGURATION=ReleaseMT + ) else ( + set CONFIGURATION=ReleaseDLL + ) + ) +) +if "%use_gui%"=="yes" ( + set use_flags=%use_flags% -cfg +) +if "%use_dll%"=="yes" ( + set build_results=dll + set sln_name=%sln_name%_dll + set use_flags=%use_flags% -dll +) else ( + set build_results=static +) +set use_projectlst=%use_projectlst:/=\% + + +REM -------------------------------------------------------------------------------- +REM prepare and run ptb.bat +cd %script_dir% +set PTB_PLATFORM=%use_arch% +set PTB_FLAGS=%use_flags% +set PTB_PATH=./static/bin/ReleaseDLL +set SLN_PATH=%script_dir%\%build_results%\build\%sln_name%.sln +set TREE_ROOT=%srcroot% +set BUILD_TREE_ROOT=. +set PTB_PROJECT_REQ=%use_projectlst% + +if "%use_savedcfg%"=="" ( + set PTB_SAVED_CFG_REQ= +) else ( + if exist "%use_savedcfg%" ( + set PTB_SAVED_CFG_REQ="%use_savedcfg%" + ) else ( + if exist "%initial_dir%\%use_savedcfg%" ( + set PTB_SAVED_CFG_REQ="%initial_dir%\%use_savedcfg%" + ) else ( + echo ERROR: "%use_savedcfg%" not found + exit /b 1 + ) + ) +) + +call ./ptb.bat +if errorlevel 1 ( + cd %initial_dir% + exit /b 1 +) + +REM -------------------------------------------------------------------------------- +REM generate configure_make.bat + +cd %script_dir% +set mk_cmnd=make.bat build %sln_name% %build_results% +if "%use_64%"=="yes" ( + set mk_cmnd=%mk_cmnd% 64 +) else ( + set mk_cmnd=%mk_cmnd% 32 +) +set mk_cmnd=%mk_cmnd% %CONFIGURATION% +echo %mk_cmnd% > configure_make.bat + + +REM ------------------------------------------------------------------------------ +echo To build the solution %SLN_PATH% +echo execute the following commands: +echo cd %script_dir% +echo make + +cd %initial_dir% +endlocal +exit /b 0 diff --git a/c++/compilers/vs2015/datatool.bat b/c++/compilers/vs2015/datatool.bat new file mode 100644 index 00000000..36a4feda --- /dev/null +++ b/c++/compilers/vs2015/datatool.bat @@ -0,0 +1,188 @@ +@echo off +REM $Id: datatool.bat 492980 2016-02-23 16:24:57Z gouriano $ +REM =========================================================================== +REM +REM PUBLIC DOMAIN NOTICE +REM National Center for Biotechnology Information +REM +REM This software/database is a "United States Government Work" under the +REM terms of the United States Copyright Act. It was written as part of +REM the author's official duties as a United States Government employee and +REM thus cannot be copyrighted. This software/database is freely available +REM to the public for use. The National Library of Medicine and the U.S. +REM Government have not placed any restriction on its use or reproduction. +REM +REM Although all reasonable efforts have been taken to ensure the accuracy +REM and reliability of the software and data, the NLM and the U.S. +REM Government do not and cannot warrant the performance or results that +REM may be obtained by using this software or data. The NLM and the U.S. +REM Government disclaim all warranties, express or implied, including +REM warranties of performance, merchantability or fitness for any particular +REM purpose. +REM +REM Please cite the author in any work or product based on this material. +REM +REM =========================================================================== +REM +REM Author: Andrei Gourianov +REM +REM Run datatool.exe to generate sources from ASN/DTD/Schema specifications +REM +REM DO NOT ATTEMPT to run this bat file manually +REM +REM =========================================================================== + +set ORIGINAL_ARGS=%* + +REM ---------------- begin workaround FOR MSVC2010! --------------------------------- +set input_asn_path= +set input_asn_name= +set input_def_path= +set subtree= +set srcroot= +:PARSEARGS +if _%1==_ goto ENDPARSEARGS +if "%dest%"=="inASN" (set input_asn_path=%~1& set input_asn_name=%~n1& set dest=& goto CONTINUEPARSEARGS) +if "%dest%"=="inDEF" (set input_def_path=%~1& set dest=& goto CONTINUEPARSEARGS) +if "%dest%"=="subtree" (set subtree=%1& set dest=& goto CONTINUEPARSEARGS) +if "%dest%"=="srcroot" (set srcroot=%1& set dest=& goto CONTINUEPARSEARGS) +if "%1"=="-m" (set dest=inASN& goto CONTINUEPARSEARGS) +if "%1"=="-od" (set dest=inDEF& goto CONTINUEPARSEARGS) +if "%1"=="-or" (set dest=subtree& goto CONTINUEPARSEARGS) +if "%1"=="-oR" (set dest=srcroot& goto CONTINUEPARSEARGS) +if "%1"=="-M" (goto ENDPARSEARGS) +:CONTINUEPARSEARGS +shift +REM echo parsing %1 +goto PARSEARGS +:ENDPARSEARGS +set src_subtree=%CD%\%srcroot%src\%subtree% +set dest_spec=%BUILD_TREE_ROOT%\static\build\%subtree% +if not exist "%dest_spec%" mkdir "%dest_spec%" +if not exist "%dest_spec%" set dest_spec=. + +set copied_asn=0 +for /f %%a in ('xcopy "%input_asn_path%" "%dest_spec%" /q /d /y') do (set copied_asn=%%a) +set copied_def=0 +if not exist "%input_def_path%" echo [-] > "%input_def_path%" +if exist "%input_def_path%" for /f %%a in ('xcopy "%input_def_path%" "%dest_spec%" /q /d /y') do (set copied_def=%%a) +if not %copied_asn%==0 goto DOGENERATE +if not %copied_def%==0 goto DOGENERATE +if not exist "%src_subtree%%input_asn_name%.files" goto DOGENERATE +if not exist "%src_subtree%%input_asn_name%__.cpp" goto DOGENERATE +if not exist "%src_subtree%%input_asn_name%___.cpp" goto DOGENERATE +echo generation NOT needed +exit /b 0 +:DOGENERATE +REM ---------------- end workaround -------------------------------------- + +set DEFDT_LOCATION=\\snowman\win-coremake\App\Ncbi\cppcore\datatool + +for %%v in ("%DATATOOL_PATH%" "%TREE_ROOT%" "%BUILD_TREE_ROOT%" "%PTB_PLATFORM%") do ( + if %%v=="" ( + echo ERROR: required environment variable is missing + echo DO NOT ATTEMPT to run this bat file manually + exit /b 1 + ) +) +set DEFDT_VERSION_FILE=%TREE_ROOT%\src\build-system\datatool_version.txt +set PTB_SLN=%BUILD_TREE_ROOT%\static\build\UtilityProjects\PTB.sln +set DT=datatool.exe + +call "%BUILD_TREE_ROOT%\msvcvars.bat" + + +REM ------------------------------------------------------------------------- +REM get DT version: from DEFDT_VERSION_FILE or from PREBUILT_DATATOOL_EXE + +set DEFDT_VERSION= +if exist "%DEFDT_VERSION_FILE%" ( + for /f %%a in ('type "%DEFDT_VERSION_FILE%"') do (set DEFDT_VERSION=%%a& goto donedf) + :donedf + set DEFDT_VERSION=%DEFDT_VERSION: =% +) +if exist "%PREBUILT_DATATOOL_EXE%" ( + set ptbver= + for /f "tokens=2" %%a in ('"%PREBUILT_DATATOOL_EXE%" -version') do (set ptbver=%%a& goto donepb) + :donepb + set ptbver=%ptbver: =% + if not "%DEFDT_VERSION%"=="%ptbver%" ( + echo WARNING: requested %DT% version %ptbver% does not match default one: %DEFDT_VERSION% + set DEFDT_VERSION=%ptbver% + ) +) + +if "%DEFDT_VERSION%"=="" ( + echo ERROR: DEFDT_VERSION not specified + exit /b 1 +) +for /f "tokens=1-3 delims=." %%a in ('echo %DEFDT_VERSION%') do (set DT_VER=%%a%%b%%c& set DT_VER_MAJOR=%%a) + + +REM ------------------------------------------------------------------------- +REM Identify DATATOOL_EXE + +set DT_COPY_HERE=NO +if "%PREBUILT_DATATOOL_EXE%"=="bootstrap" ( + set DEF_DT=%DATATOOL_PATH%\%DT% +) else if not "%PREBUILT_DATATOOL_EXE%"=="" ( + if exist "%PREBUILT_DATATOOL_EXE%" ( + set DEF_DT=%PREBUILT_DATATOOL_EXE% + ) else ( + echo ERROR: "%PREBUILT_DATATOOL_EXE%" not found + exit /b 1 + ) +) else ( + set DEF_DT=%DEFDT_LOCATION%\msvc\%DEFDT_VERSION%\%DT% + if not "%COPY_DATATOOL_EXE%"=="NO" ( + set DT_COPY_HERE=YES + ) +) +if exist "%DEF_DT%" ( + set DATATOOL_EXE=%DEF_DT% +) else ( + echo %DT% not found at %DEF_DT% + set DATATOOL_EXE=%DATATOOL_PATH%\%DT% + set DT_COPY_HERE=NO +) + + +REM ------------------------------------------------------------------------- +REM Build DATATOOL_EXE if needed + +if not exist "%DATATOOL_EXE%" ( + if exist "%PTB_SLN%" ( + echo ****************************************************************************** + echo Building %DT% locally, please wait + echo ****************************************************************************** + @echo %DEVENV% "%PTB_SLN%" /rebuild "ReleaseDLL|%PTB_PLATFORM%" /project "datatool.exe" + %DEVENV% "%PTB_SLN%" /rebuild "ReleaseDLL|%PTB_PLATFORM%" /project "datatool.exe" + ) else ( + echo ERROR: do not know how to build %DT% + ) +) else ( + echo ****************************************************************************** + echo Using PREBUILT %DT% at %DATATOOL_EXE% + echo ****************************************************************************** +) +if not exist "%DATATOOL_EXE%" ( + echo ERROR: "%DATATOOL_EXE%" not found + exit /b 1 +) + +REM ------------------------------------------------------------------------- +REM Copy datatool from network to the local tree (to make it work faster) + +set DT_LOCAL=%BUILD_TREE_ROOT%\static\build\UtilityProjects\%DEFDT_VERSION%_%DT% +if "%DT_COPY_HERE%"=="YES" ( + if not exist "%DT_LOCAL%" ( + xcopy "%DATATOOL_EXE%" "%BUILD_TREE_ROOT%\static\build\UtilityProjects\" /q /d /y >NUL + rename "%BUILD_TREE_ROOT%\static\build\UtilityProjects\%DT%" "%DEFDT_VERSION%_%DT%" + ) + set DATATOOL_EXE=%DT_LOCAL% +) + +REM ------------------------------------------------------------------------- +REM Run DATATOOL_EXE + +"%DATATOOL_EXE%" %ORIGINAL_ARGS% diff --git a/c++/compilers/vs2015/dll/build/UtilityProjects/_CONFIGURE_.vcxproj b/c++/compilers/vs2015/dll/build/UtilityProjects/_CONFIGURE_.vcxproj new file mode 100644 index 00000000..56dd94a6 --- /dev/null +++ b/c++/compilers/vs2015/dll/build/UtilityProjects/_CONFIGURE_.vcxproj @@ -0,0 +1,144 @@ + + + + + DebugDLL + Win32 + + + DebugDLL + x64 + + + ReleaseDLL + Win32 + + + ReleaseDLL + x64 + + + + _CONFIGURE_ + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAAC9} + MasterProject + ManagedCProj + + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_ + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_ + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_ + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_ + + + + X64 + + + + + X64 + + + + + Document + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\static\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_cpp_dll.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\static\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\static\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_cpp_dll.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\static\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\static\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_cpp_dll.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\static\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\static\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_cpp_dll.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\static\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + + + + + + \ No newline at end of file diff --git a/c++/compilers/vs2015/dll/build/UtilityProjects/_CONFIGURE_DIALOG_.vcxproj b/c++/compilers/vs2015/dll/build/UtilityProjects/_CONFIGURE_DIALOG_.vcxproj new file mode 100644 index 00000000..02c6d532 --- /dev/null +++ b/c++/compilers/vs2015/dll/build/UtilityProjects/_CONFIGURE_DIALOG_.vcxproj @@ -0,0 +1,144 @@ + + + + + DebugDLL + Win32 + + + DebugDLL + x64 + + + ReleaseDLL + Win32 + + + ReleaseDLL + x64 + + + + _CONFIGURE_DIALOG_ + {67EC51FA-3A0D-46B8-8F89-49EE209C8CB8} + MasterProject + ManagedCProj + + + + Utility + MultiByte + v120 + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_DIALOG_ + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_DIALOG_ + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_DIALOG_ + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_DIALOG_ + + + + X64 + + + + + X64 + + + + + Document + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\static\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_cpp_dll.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\static\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\static\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_cpp_dll.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\static\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\static\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_cpp_dll.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\static\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\static\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_cpp_dll.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\static\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + + + + + + \ No newline at end of file diff --git a/c++/compilers/vs2015/dll/build/UtilityProjects/configure._ b/c++/compilers/vs2015/dll/build/UtilityProjects/configure._ new file mode 100644 index 00000000..7d4011f2 --- /dev/null +++ b/c++/compilers/vs2015/dll/build/UtilityProjects/configure._ @@ -0,0 +1,4 @@ +set PTB_FLAGS= -dll +set PTB_PROJECT_REQ=scripts\projects\ncbi_cpp_dll.lst +call "%BUILD_TREE_ROOT%\ptb.bat" +if errorlevel 1 exit 1 diff --git a/c++/compilers/vs2015/dll/build/UtilityProjects/configure_dialog._ b/c++/compilers/vs2015/dll/build/UtilityProjects/configure_dialog._ new file mode 100644 index 00000000..f4e04b9d --- /dev/null +++ b/c++/compilers/vs2015/dll/build/UtilityProjects/configure_dialog._ @@ -0,0 +1,4 @@ +set PTB_FLAGS= -dll -cfg +set PTB_PROJECT_REQ=scripts\projects\ncbi_cpp_dll.lst +call "%BUILD_TREE_ROOT%\ptb.bat" +if errorlevel 1 exit 1 diff --git a/c++/compilers/vs2015/dll/build/all.bat b/c++/compilers/vs2015/dll/build/all.bat new file mode 100644 index 00000000..d1e7a340 --- /dev/null +++ b/c++/compilers/vs2015/dll/build/all.bat @@ -0,0 +1,42 @@ +@ECHO OFF +REM $Id: all.bat 492988 2016-02-23 17:04:54Z gouriano $ +REM =========================================================================== +REM +REM PUBLIC DOMAIN NOTICE +REM National Center for Biotechnology Information +REM +REM This software/database is a "United States Government Work" under the +REM terms of the United States Copyright Act. It was written as part of +REM the author's official duties as a United States Government employee and +REM thus cannot be copyrighted. This software/database is freely available +REM to the public for use. The National Library of Medicine and the U.S. +REM Government have not placed any restriction on its use or reproduction. +REM +REM Although all reasonable efforts have been taken to ensure the accuracy +REM and reliability of the software and data, the NLM and the U.S. +REM Government do not and cannot warrant the performance or results that +REM may be obtained by using this software or data. The NLM and the U.S. +REM Government disclaim all warranties, express or implied, including +REM warranties of performance, merchantability or fitness for any particular +REM purpose. +REM +REM Please cite the author in any work or product based on this material. +REM +REM =========================================================================== +REM +REM Author: Vladimir Ivanov +REM +REM Build all C++ Toolkit DLL projects +REM +REM =========================================================================== + + +CALL all_ncbi.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +IF ERRORLEVEL 1 GOTO _ABORT_ + +CALL all_gui.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +IF ERRORLEVEL 1 GOTO _ABORT_ + +CALL all_gbench.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 + +:_ABORT_ \ No newline at end of file diff --git a/c++/compilers/vs2015/dll/build/all_gbench.bat b/c++/compilers/vs2015/dll/build/all_gbench.bat new file mode 100644 index 00000000..dff15ed1 --- /dev/null +++ b/c++/compilers/vs2015/dll/build/all_gbench.bat @@ -0,0 +1,75 @@ +@ECHO OFF +REM $Id: all_gbench.bat 492988 2016-02-23 17:04:54Z gouriano $ +REM =========================================================================== +REM +REM PUBLIC DOMAIN NOTICE +REM National Center for Biotechnology Information +REM +REM This software/database is a "United States Government Work" under the +REM terms of the United States Copyright Act. It was written as part of +REM the author's official duties as a United States Government employee and +REM thus cannot be copyrighted. This software/database is freely available +REM to the public for use. The National Library of Medicine and the U.S. +REM Government have not placed any restriction on its use or reproduction. +REM +REM Although all reasonable efforts have been taken to ensure the accuracy +REM and reliability of the software and data, the NLM and the U.S. +REM Government do not and cannot warrant the performance or results that +REM may be obtained by using this software or data. The NLM and the U.S. +REM Government disclaim all warranties, express or implied, including +REM warranties of performance, merchantability or fitness for any particular +REM purpose. +REM +REM Please cite the author in any work or product based on this material. +REM +REM =========================================================================== +REM +REM Author: Anton Lavrentiev +REM +REM Build GBENCH +REM +REM =========================================================================== + +call "..\..\msvcvars.bat" + +IF _%1% == _ GOTO BUILDALL +IF _%1% == _ALL GOTO BUILDALL +GOTO CONFIG + +:BUILDALL +CALL %0 DebugDLL ReleaseDLL +GOTO EXIT + +:CONFIG +TIME /T +ECHO INFO: Configure "dll\gbench" +msbuild gbench\ncbi_gbench.sln /t:"_CONFIGURE_:Rebuild" /p:Configuration=ReleaseDLL +IF ERRORLEVEL 1 GOTO ABORT + +SET CFG=%1% + +:ARGLOOP +IF %CFG% == DebugDLL GOTO CONTINUE +IF %CFG% == ReleaseDLL GOTO CONTINUE +ECHO INFO: The following configuration names are recognized: +ECHO DebugDLL ReleaseDLL +ECHO FATAL: Unknown configuration name %CFG%. Please correct. +GOTO EXIT + +:CONTINUE +TIME /T +ECHO INFO: Building "dll\gbench\%CFG%" +msbuild gbench\ncbi_gbench.sln /t:"_BUILD_ALL_" /p:Configuration=%CFG% +IF ERRORLEVEL 1 GOTO ABORT + +SHIFT +IF _%1% == _ GOTO COMPLETE +SET CFG=%1% +GOTO ARGLOOP + +:ABORT +ECHO INFO: Build failed. +GOTO EXIT +:COMPLETE +ECHO INFO: Build complete. +:EXIT diff --git a/c++/compilers/vs2015/dll/build/all_gui.bat b/c++/compilers/vs2015/dll/build/all_gui.bat new file mode 100644 index 00000000..7cf2cf10 --- /dev/null +++ b/c++/compilers/vs2015/dll/build/all_gui.bat @@ -0,0 +1,75 @@ +@ECHO OFF +REM $Id: all_gui.bat 492988 2016-02-23 17:04:54Z gouriano $ +REM =========================================================================== +REM +REM PUBLIC DOMAIN NOTICE +REM National Center for Biotechnology Information +REM +REM This software/database is a "United States Government Work" under the +REM terms of the United States Copyright Act. It was written as part of +REM the author's official duties as a United States Government employee and +REM thus cannot be copyrighted. This software/database is freely available +REM to the public for use. The National Library of Medicine and the U.S. +REM Government have not placed any restriction on its use or reproduction. +REM +REM Although all reasonable efforts have been taken to ensure the accuracy +REM and reliability of the software and data, the NLM and the U.S. +REM Government do not and cannot warrant the performance or results that +REM may be obtained by using this software or data. The NLM and the U.S. +REM Government disclaim all warranties, express or implied, including +REM warranties of performance, merchantability or fitness for any particular +REM purpose. +REM +REM Please cite the author in any work or product based on this material. +REM +REM =========================================================================== +REM +REM Author: Anton Lavrentiev +REM +REM Build C++ GUI libraries, tests and samples +REM +REM =========================================================================== + +call "..\..\msvcvars.bat" + +IF _%1% == _ GOTO BUILDALL +IF _%1% == _ALL GOTO BUILDALL +GOTO CONFIG + +:BUILDALL +CALL %0 DebugDLL ReleaseDLL +GOTO EXIT + +:CONFIG +TIME /T +ECHO INFO: Configure "dll\gui" +msbuild gui\ncbi_gui_dll.sln /t:"_CONFIGURE_:Rebuild" /p:Configuration=ReleaseDLL +IF ERRORLEVEL 1 GOTO ABORT + +SET CFG=%1% + +:ARGLOOP +IF %CFG% == DebugDLL GOTO CONTINUE +IF %CFG% == ReleaseDLL GOTO CONTINUE +ECHO INFO: The following configuration names are recognized: +ECHO DebugDLL ReleaseDLL +ECHO FATAL: Unknown configuration name %CFG%. Please correct. +GOTO EXIT + +:CONTINUE +TIME /T +ECHO INFO: Building "dll\gui\%CFG%" +msbuild gui\ncbi_gui_dll.sln /t:"_BUILD_ALL_" /p:Configuration=%CFG% +IF ERRORLEVEL 1 GOTO ABORT + +SHIFT +IF _%1% == _ GOTO COMPLETE +SET CFG=%1% +GOTO ARGLOOP + +:ABORT +ECHO INFO: Build failed. +GOTO EXIT +:COMPLETE +ECHO INFO: Build complete. +:EXIT diff --git a/c++/compilers/vs2015/dll/build/all_ncbi.bat b/c++/compilers/vs2015/dll/build/all_ncbi.bat new file mode 100644 index 00000000..830c2210 --- /dev/null +++ b/c++/compilers/vs2015/dll/build/all_ncbi.bat @@ -0,0 +1,75 @@ +@ECHO OFF +REM $Id: all_ncbi.bat 492988 2016-02-23 17:04:54Z gouriano $ +REM =========================================================================== +REM +REM PUBLIC DOMAIN NOTICE +REM National Center for Biotechnology Information +REM +REM This software/database is a "United States Government Work" under the +REM terms of the United States Copyright Act. It was written as part of +REM the author's official duties as a United States Government employee and +REM thus cannot be copyrighted. This software/database is freely available +REM to the public for use. The National Library of Medicine and the U.S. +REM Government have not placed any restriction on its use or reproduction. +REM +REM Although all reasonable efforts have been taken to ensure the accuracy +REM and reliability of the software and data, the NLM and the U.S. +REM Government do not and cannot warrant the performance or results that +REM may be obtained by using this software or data. The NLM and the U.S. +REM Government disclaim all warranties, express or implied, including +REM warranties of performance, merchantability or fitness for any particular +REM purpose. +REM +REM Please cite the author in any work or product based on this material. +REM +REM =========================================================================== +REM +REM Author: Anton Lavrentiev +REM +REM Build NCBI C++ core libraries, tests and samples +REM +REM =========================================================================== + +call "..\..\msvcvars.bat" + +IF _%1% == _ GOTO BUILDALL +IF _%1% == _ALL GOTO BUILDALL +GOTO CONFIG + +:BUILDALL +CALL %0 DebugDLL ReleaseDLL +GOTO EXIT + +:CONFIG +TIME /T +ECHO INFO: Configure "dll\ncbi" +msbuild ncbi_cpp_dll.sln /t:"_CONFIGURE_:Rebuild" /p:Configuration=ReleaseDLL +IF ERRORLEVEL 1 GOTO ABORT + +SET CFG=%1% + +:ARGLOOP +IF %CFG% == DebugDLL GOTO CONTINUE +IF %CFG% == ReleaseDLL GOTO CONTINUE +ECHO INFO: The following configuration names are recognized: +ECHO DebugDLL ReleaseDLL +ECHO FATAL: Unknown configuration name %CFG%. Please correct. +GOTO EXIT + +:CONTINUE +TIME /T +ECHO INFO: Building "dll\ncbi\%CFG%" +msbuild ncbi_cpp_dll.sln /t:"_BUILD_ALL_" /p:Configuration=%CFG% +IF ERRORLEVEL 1 GOTO ABORT + +SHIFT +IF _%1% == _ GOTO COMPLETE +SET CFG=%1% +GOTO ARGLOOP + +:ABORT +ECHO INFO: Build failed. +GOTO EXIT +:COMPLETE +ECHO INFO: Build complete. +:EXIT diff --git a/c++/compilers/vs2015/dll/build/gbench/UtilityProjects/_CONFIGURE_.vcxproj b/c++/compilers/vs2015/dll/build/gbench/UtilityProjects/_CONFIGURE_.vcxproj new file mode 100644 index 00000000..3bfcfd80 --- /dev/null +++ b/c++/compilers/vs2015/dll/build/gbench/UtilityProjects/_CONFIGURE_.vcxproj @@ -0,0 +1,148 @@ + + + + + DebugDLL + Win32 + + + DebugDLL + x64 + + + ReleaseDLL + Win32 + + + ReleaseDLL + x64 + + + + _CONFIGURE_ + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA58} + MasterProject + ManagedCProj + + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_ + + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_ + + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_ + + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_ + + + + + X64 + + + + + X64 + + + + + Document + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_gbench.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_gbench.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_gbench.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_gbench.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + + + + + + \ No newline at end of file diff --git a/c++/compilers/vs2015/dll/build/gbench/UtilityProjects/_CONFIGURE_DIALOG_.vcxproj b/c++/compilers/vs2015/dll/build/gbench/UtilityProjects/_CONFIGURE_DIALOG_.vcxproj new file mode 100644 index 00000000..cc572dd9 --- /dev/null +++ b/c++/compilers/vs2015/dll/build/gbench/UtilityProjects/_CONFIGURE_DIALOG_.vcxproj @@ -0,0 +1,148 @@ + + + + + DebugDLL + Win32 + + + DebugDLL + x64 + + + ReleaseDLL + Win32 + + + ReleaseDLL + x64 + + + + _CONFIGURE_DIALOG_ + {6DEFDB58-C014-4026-A166-299146BD9947} + MasterProject + ManagedCProj + + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_DIALOG_ + + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_DIALOG_ + + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_DIALOG_ + + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_DIALOG_ + + + + + X64 + + + + + X64 + + + + + Document + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_gbench.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_gbench.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_gbench.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_gbench.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + + + + + + \ No newline at end of file diff --git a/c++/compilers/vs2015/dll/build/gbench/UtilityProjects/configure._ b/c++/compilers/vs2015/dll/build/gbench/UtilityProjects/configure._ new file mode 100644 index 00000000..6be17e9b --- /dev/null +++ b/c++/compilers/vs2015/dll/build/gbench/UtilityProjects/configure._ @@ -0,0 +1,5 @@ +set NCBI_CONFIG____ENABLEDUSERREQUESTS__NCBI-UNICODE=1 +set PTB_FLAGS= -dll +set PTB_PROJECT_REQ=scripts\projects\ncbi_gbench.lst +call "%BUILD_TREE_ROOT%\ptb.bat" +if errorlevel 1 exit 1 diff --git a/c++/compilers/vs2015/dll/build/gbench/UtilityProjects/configure_dialog._ b/c++/compilers/vs2015/dll/build/gbench/UtilityProjects/configure_dialog._ new file mode 100644 index 00000000..b6f1b6c9 --- /dev/null +++ b/c++/compilers/vs2015/dll/build/gbench/UtilityProjects/configure_dialog._ @@ -0,0 +1,5 @@ +set NCBI_CONFIG____ENABLEDUSERREQUESTS__NCBI-UNICODE=1 +set PTB_FLAGS= -dll -cfg +set PTB_PROJECT_REQ=scripts\projects\ncbi_gbench.lst +call "%BUILD_TREE_ROOT%\ptb.bat" +if errorlevel 1 exit 1 diff --git a/c++/compilers/vs2015/dll/build/gbench/configure_prebuild.bat b/c++/compilers/vs2015/dll/build/gbench/configure_prebuild.bat new file mode 100644 index 00000000..5b68e068 --- /dev/null +++ b/c++/compilers/vs2015/dll/build/gbench/configure_prebuild.bat @@ -0,0 +1,48 @@ +@echo off +REM $Id: configure_prebuild.bat 492989 2016-02-23 17:05:09Z gouriano $ +REM =========================================================================== +REM +REM PUBLIC DOMAIN NOTICE +REM National Center for Biotechnology Information +REM +REM This software/database is a "United States Government Work" under the +REM terms of the United States Copyright Act. It was written as part of +REM the author's official duties as a United States Government employee and +REM thus cannot be copyrighted. This software/database is freely available +REM to the public for use. The National Library of Medicine and the U.S. +REM Government have not placed any restriction on its use or reproduction. +REM +REM Although all reasonable efforts have been taken to ensure the accuracy +REM and reliability of the software and data, the NLM and the U.S. +REM Government do not and cannot warrant the performance or results that +REM may be obtained by using this software or data. The NLM and the U.S. +REM Government disclaim all warranties, express or implied, including +REM warranties of performance, merchantability or fitness for any particular +REM purpose. +REM +REM Please cite the author in any work or product based on this material. +REM +REM =========================================================================== +REM +REM Author: Andrei Gourianov +REM +REM This script is called by compilers/msvcNNN_prj/ptb.bat +REM when building CONFIGURE project, before performing any meaningful actions. +REM +REM So, this is a good place to put any custom PRE-BUILD operations. +REM For example, set environment variables. +REM +REM =========================================================================== + +set initial_dir=%CD% +set script_name=%~nx0 +cd %~dp0 +for /f "delims=" %%a in ('cd') do (set script_dir=%%a) +cd %initial_dir% + +set cfgs=project_tree_builder.ini.custom + +set NCBI_CONFIG____ENABLEDUSERREQUESTS__NCBI-UNICODE= +if not exist "%script_dir%\%cfgs%" ( + set NCBI_CONFIG____ENABLEDUSERREQUESTS__NCBI-UNICODE=1 +) diff --git a/c++/compilers/vs2015/dll/build/gbench/gbench_install/gbench-install.vcxproj b/c++/compilers/vs2015/dll/build/gbench/gbench_install/gbench-install.vcxproj new file mode 100644 index 00000000..bb816ca1 --- /dev/null +++ b/c++/compilers/vs2015/dll/build/gbench/gbench_install/gbench-install.vcxproj @@ -0,0 +1,218 @@ + + + + + DebugDLL + Win32 + + + DebugDLL + x64 + + + ReleaseDLL + Win32 + + + ReleaseDLL + x64 + + + Unicode_DebugDLL + Win32 + + + Unicode_DebugDLL + x64 + + + Unicode_ReleaseDLL + Win32 + + + Unicode_ReleaseDLL + x64 + + + VTune_DebugDLL + Win32 + + + VTune_DebugDLL + x64 + + + VTune_ReleaseDLL + Win32 + + + VTune_ReleaseDLL + x64 + + + + {6C23686B-1522-4B44-8D48-7E3176C36247} + gbench-install + MakeFileProj + + + + Makefile + + + Makefile + + + Makefile + + + Makefile + + + Makefile + + + Makefile + + + Makefile + + + Makefile + + + Makefile + + + Makefile + + + Makefile + + + Makefile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + DebugDLL\ + DebugDLL\ + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak all IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak all IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak clean IntDir=$(IntDir) MSVC_SRC="vs2015" + gbench-install.exe + DebugDLL\ + DebugDLL\ + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak all IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak all IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak clean IntDir=$(IntDir) MSVC_SRC="vs2015.64" + gbench-install.exe + ReleaseDLL\ + ReleaseDLL\ + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak all IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak all IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak clean IntDir=$(IntDir) MSVC_SRC="vs2015" + gbench-install.exe + ReleaseDLL\ + ReleaseDLL\ + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak all IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak all IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak clean IntDir=$(IntDir) MSVC_SRC="vs2015.64" + gbench-install.exe + Unicode_DebugDLL\ + Unicode_DebugDLL\ + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak all IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak all IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak clean IntDir=$(IntDir) MSVC_SRC="vs2015" + gbench-install.exe + Unicode_DebugDLL\ + Unicode_DebugDLL\ + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak all IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak all IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak clean IntDir=$(IntDir) MSVC_SRC="vs2015.64" + gbench-install.exe + Unicode_ReleaseDLL\ + Unicode_ReleaseDLL\ + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak all IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak all IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak clean IntDir=$(IntDir) MSVC_SRC="vs2015" + gbench-install.exe + Unicode_ReleaseDLL\ + Unicode_ReleaseDLL\ + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak all IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak all IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak clean IntDir=$(IntDir) MSVC_SRC="vs2015.64" + gbench-install.exe + VTune_DebugDLL\ + VTune_DebugDLL\ + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak all IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak all IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak clean IntDir=$(IntDir) MSVC_SRC="vs2015" + gbench-install.exe + VTune_DebugDLL\ + VTune_DebugDLL\ + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak all IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak all IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak clean IntDir=$(IntDir) MSVC_SRC="vs2015.64" + gbench-install.exe + VTune_ReleaseDLL\ + VTune_ReleaseDLL\ + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak all IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak all IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak clean IntDir=$(IntDir) MSVC_SRC="vs2015" + gbench-install.exe + VTune_ReleaseDLL\ + VTune_ReleaseDLL\ + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak all IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak all IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f ..\..\..\..\..\..\src\app\gbench\gbench_install\gbench_install.win32.mak clean IntDir=$(IntDir) MSVC_SRC="vs2015.64" + gbench-install.exe + + + + + + + + + + diff --git a/c++/compilers/vs2015/dll/build/gbench/ncbi_gbench.sln b/c++/compilers/vs2015/dll/build/gbench/ncbi_gbench.sln new file mode 100644 index 00000000..9513fb00 --- /dev/null +++ b/c++/compilers/vs2015/dll/build/gbench/ncbi_gbench.sln @@ -0,0 +1,35 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_CONFIGURE_DIALOG_", "UtilityProjects\_CONFIGURE_DIALOG_.vcxproj", "{6DEFDB58-C014-4026-A166-299146BD9947}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_CONFIGURE_", "UtilityProjects\_CONFIGURE_.vcxproj", "{8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA58}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + DebugDLL|x64 = DebugDLL|x64 + DebugDLL|x86 = DebugDLL|x86 + ReleaseDLL|x64 = ReleaseDLL|x64 + ReleaseDLL|x86 = ReleaseDLL|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6DEFDB58-C014-4026-A166-299146BD9947}.DebugDLL|x64.ActiveCfg = DebugDLL|x64 + {6DEFDB58-C014-4026-A166-299146BD9947}.DebugDLL|x64.Build.0 = DebugDLL|x64 + {6DEFDB58-C014-4026-A166-299146BD9947}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32 + {6DEFDB58-C014-4026-A166-299146BD9947}.DebugDLL|x86.Build.0 = DebugDLL|Win32 + {6DEFDB58-C014-4026-A166-299146BD9947}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 + {6DEFDB58-C014-4026-A166-299146BD9947}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + {6DEFDB58-C014-4026-A166-299146BD9947}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32 + {6DEFDB58-C014-4026-A166-299146BD9947}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA58}.DebugDLL|x64.ActiveCfg = DebugDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA58}.DebugDLL|x64.Build.0 = DebugDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA58}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA58}.DebugDLL|x86.Build.0 = DebugDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA58}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA58}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA58}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA58}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/c++/compilers/vs2015/dll/build/gui/UtilityProjects/_CONFIGURE_.vcxproj b/c++/compilers/vs2015/dll/build/gui/UtilityProjects/_CONFIGURE_.vcxproj new file mode 100644 index 00000000..0804bcba --- /dev/null +++ b/c++/compilers/vs2015/dll/build/gui/UtilityProjects/_CONFIGURE_.vcxproj @@ -0,0 +1,144 @@ + + + + + DebugDLL + Win32 + + + DebugDLL + x64 + + + ReleaseDLL + Win32 + + + ReleaseDLL + x64 + + + + _CONFIGURE_ + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA56} + MasterProject + ManagedCProj + + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_ + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_ + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_ + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_ + + + + X64 + + + + + X64 + + + + + Document + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_gui_dll.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_gui_dll.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_gui_dll.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_gui_dll.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + + + + + + \ No newline at end of file diff --git a/c++/compilers/vs2015/dll/build/gui/UtilityProjects/_CONFIGURE_DIALOG_.vcxproj b/c++/compilers/vs2015/dll/build/gui/UtilityProjects/_CONFIGURE_DIALOG_.vcxproj new file mode 100644 index 00000000..4d2da5b6 --- /dev/null +++ b/c++/compilers/vs2015/dll/build/gui/UtilityProjects/_CONFIGURE_DIALOG_.vcxproj @@ -0,0 +1,144 @@ + + + + + DebugDLL + Win32 + + + DebugDLL + x64 + + + ReleaseDLL + Win32 + + + ReleaseDLL + x64 + + + + _CONFIGURE_DIALOG_ + {9BAE6EEC-8C80-44F0-84A9-3379631A8654} + MasterProject + ManagedCProj + + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_DIALOG_ + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_DIALOG_ + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_DIALOG_ + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_DIALOG_ + + + + X64 + + + + + X64 + + + + + Document + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_gui_dll.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_gui_dll.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_gui_dll.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_gui_dll.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + + + + + + \ No newline at end of file diff --git a/c++/compilers/vs2015/dll/build/gui/UtilityProjects/configure._ b/c++/compilers/vs2015/dll/build/gui/UtilityProjects/configure._ new file mode 100644 index 00000000..b86cc7e0 --- /dev/null +++ b/c++/compilers/vs2015/dll/build/gui/UtilityProjects/configure._ @@ -0,0 +1,4 @@ +set PTB_FLAGS= -dll +set PTB_PROJECT_REQ=scripts\projects\ncbi_gui.lst +call "%BUILD_TREE_ROOT%\ptb.bat" +if errorlevel 1 exit 1 diff --git a/c++/compilers/vs2015/dll/build/gui/UtilityProjects/configure_dialog._ b/c++/compilers/vs2015/dll/build/gui/UtilityProjects/configure_dialog._ new file mode 100644 index 00000000..78a91812 --- /dev/null +++ b/c++/compilers/vs2015/dll/build/gui/UtilityProjects/configure_dialog._ @@ -0,0 +1,4 @@ +set PTB_FLAGS= -dll -cfg +set PTB_PROJECT_REQ=scripts\projects\ncbi_gui.lst +call "%BUILD_TREE_ROOT%\ptb.bat" +if errorlevel 1 exit 1 diff --git a/c++/compilers/vs2015/dll/build/gui/ncbi_gui_dll.sln b/c++/compilers/vs2015/dll/build/gui/ncbi_gui_dll.sln new file mode 100644 index 00000000..3ec883f3 --- /dev/null +++ b/c++/compilers/vs2015/dll/build/gui/ncbi_gui_dll.sln @@ -0,0 +1,35 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_CONFIGURE_DIALOG_", "UtilityProjects\_CONFIGURE_DIALOG_.vcxproj", "{9BAE6EEC-8C80-44F0-84A9-3379631A8654}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_CONFIGURE_", "UtilityProjects\_CONFIGURE_.vcxproj", "{8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA56}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + DebugDLL|x64 = DebugDLL|x64 + DebugDLL|x86 = DebugDLL|x86 + ReleaseDLL|x64 = ReleaseDLL|x64 + ReleaseDLL|x86 = ReleaseDLL|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9BAE6EEC-8C80-44F0-84A9-3379631A8654}.DebugDLL|x64.ActiveCfg = DebugDLL|x64 + {9BAE6EEC-8C80-44F0-84A9-3379631A8654}.DebugDLL|x64.Build.0 = DebugDLL|x64 + {9BAE6EEC-8C80-44F0-84A9-3379631A8654}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32 + {9BAE6EEC-8C80-44F0-84A9-3379631A8654}.DebugDLL|x86.Build.0 = DebugDLL|Win32 + {9BAE6EEC-8C80-44F0-84A9-3379631A8654}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 + {9BAE6EEC-8C80-44F0-84A9-3379631A8654}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + {9BAE6EEC-8C80-44F0-84A9-3379631A8654}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32 + {9BAE6EEC-8C80-44F0-84A9-3379631A8654}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA56}.DebugDLL|x64.ActiveCfg = DebugDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA56}.DebugDLL|x64.Build.0 = DebugDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA56}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA56}.DebugDLL|x86.Build.0 = DebugDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA56}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA56}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA56}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA56}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/c++/compilers/vs2015/dll/build/internal/gbench/gbench_install_internal/gbench-install-internal.vcxproj b/c++/compilers/vs2015/dll/build/internal/gbench/gbench_install_internal/gbench-install-internal.vcxproj new file mode 100644 index 00000000..7d3fdd30 --- /dev/null +++ b/c++/compilers/vs2015/dll/build/internal/gbench/gbench_install_internal/gbench-install-internal.vcxproj @@ -0,0 +1,218 @@ + + + + + DebugDLL + Win32 + + + DebugDLL + x64 + + + ReleaseDLL + Win32 + + + ReleaseDLL + x64 + + + Unicode_DebugDLL + Win32 + + + Unicode_DebugDLL + x64 + + + Unicode_ReleaseDLL + Win32 + + + Unicode_ReleaseDLL + x64 + + + VTune_DebugDLL + Win32 + + + VTune_DebugDLL + x64 + + + VTune_ReleaseDLL + Win32 + + + VTune_ReleaseDLL + x64 + + + + {6C23686B-1522-4B44-8D48-7E3176C36248} + gbench-install + MakeFileProj + + + + Makefile + + + Makefile + + + Makefile + + + Makefile + + + Makefile + + + Makefile + + + Makefile + + + Makefile + + + Makefile + + + Makefile + + + Makefile + + + Makefile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + DebugDLL\ + DebugDLL\ + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak all IntDir=$(IntDir) + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak all IntDir=$(IntDir) + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak clean IntDir=$(IntDir) + gbench-install.exe + DebugDLL\ + DebugDLL\ + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak all IntDir=$(IntDir) + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak all IntDir=$(IntDir) + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak clean IntDir=$(IntDir) + gbench-install.exe + ReleaseDLL\ + ReleaseDLL\ + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak all IntDir=$(IntDir) + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak all IntDir=$(IntDir) + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak clean IntDir=$(IntDir) + gbench-install.exe + ReleaseDLL\ + ReleaseDLL\ + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak all IntDir=$(IntDir) + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak all IntDir=$(IntDir) + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak clean IntDir=$(IntDir) + gbench-install.exe + Unicode_DebugDLL\ + Unicode_DebugDLL\ + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak all IntDir=$(IntDir) + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak all IntDir=$(IntDir) + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak clean IntDir=$(IntDir) + gbench-install.exe + Unicode_DebugDLL\ + Unicode_DebugDLL\ + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak all IntDir=$(IntDir) + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak all IntDir=$(IntDir) + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak clean IntDir=$(IntDir) + gbench-install.exe + Unicode_ReleaseDLL\ + Unicode_ReleaseDLL\ + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak all IntDir=$(IntDir) + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak all IntDir=$(IntDir) + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak clean IntDir=$(IntDir) + gbench-install.exe + Unicode_ReleaseDLL\ + Unicode_ReleaseDLL\ + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak all IntDir=$(IntDir) + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak all IntDir=$(IntDir) + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak clean IntDir=$(IntDir) + gbench-install.exe + VTune_DebugDLL\ + VTune_DebugDLL\ + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak all IntDir=$(IntDir) + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak all IntDir=$(IntDir) + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak clean IntDir=$(IntDir) + gbench-install.exe + VTune_DebugDLL\ + VTune_DebugDLL\ + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak all IntDir=$(IntDir) + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak all IntDir=$(IntDir) + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak clean IntDir=$(IntDir) + gbench-install.exe + VTune_ReleaseDLL\ + VTune_ReleaseDLL\ + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak all IntDir=$(IntDir) + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak all IntDir=$(IntDir) + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak clean IntDir=$(IntDir) + gbench-install.exe + VTune_ReleaseDLL\ + VTune_ReleaseDLL\ + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak all IntDir=$(IntDir) + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak all IntDir=$(IntDir) + nmake -f ..\..\..\..\..\..\..\src\internal\gbench\install\gbench_install_internal.win32.mak clean IntDir=$(IntDir) + gbench-install.exe + + + + + + + + + + diff --git a/c++/compilers/vs2015/dll/build/ncbi_cpp_dll.sln b/c++/compilers/vs2015/dll/build/ncbi_cpp_dll.sln new file mode 100644 index 00000000..234c31cc --- /dev/null +++ b/c++/compilers/vs2015/dll/build/ncbi_cpp_dll.sln @@ -0,0 +1,35 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_CONFIGURE_DIALOG_", "UtilityProjects\_CONFIGURE_DIALOG_.vcxproj", "{67EC51FA-3A0D-46B8-8F89-49EE209C8CB8}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_CONFIGURE_", "UtilityProjects\_CONFIGURE_.vcxproj", "{8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAAC9}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + DebugDLL|x64 = DebugDLL|x64 + DebugDLL|x86 = DebugDLL|x86 + ReleaseDLL|x64 = ReleaseDLL|x64 + ReleaseDLL|x86 = ReleaseDLL|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {67EC51FA-3A0D-46B8-8F89-49EE209C8CB8}.DebugDLL|x64.ActiveCfg = DebugDLL|x64 + {67EC51FA-3A0D-46B8-8F89-49EE209C8CB8}.DebugDLL|x64.Build.0 = DebugDLL|x64 + {67EC51FA-3A0D-46B8-8F89-49EE209C8CB8}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32 + {67EC51FA-3A0D-46B8-8F89-49EE209C8CB8}.DebugDLL|x86.Build.0 = DebugDLL|Win32 + {67EC51FA-3A0D-46B8-8F89-49EE209C8CB8}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 + {67EC51FA-3A0D-46B8-8F89-49EE209C8CB8}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + {67EC51FA-3A0D-46B8-8F89-49EE209C8CB8}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32 + {67EC51FA-3A0D-46B8-8F89-49EE209C8CB8}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAAC9}.DebugDLL|x64.ActiveCfg = DebugDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAAC9}.DebugDLL|x64.Build.0 = DebugDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAAC9}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAAC9}.DebugDLL|x86.Build.0 = DebugDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAAC9}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAAC9}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAAC9}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAAC9}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/c++/compilers/vs2015/dll/dll_main.cpp b/c++/compilers/vs2015/dll/dll_main.cpp new file mode 100644 index 00000000..7bd913fb --- /dev/null +++ b/c++/compilers/vs2015/dll/dll_main.cpp @@ -0,0 +1,18 @@ + +#include + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +// Windows Header Files: +#include + +BOOL APIENTRY DllMain( HANDLE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + return TRUE; +} + + + + diff --git a/c++/compilers/vs2015/dll/third_party_dll_install.mak b/c++/compilers/vs2015/dll/third_party_dll_install.mak new file mode 100644 index 00000000..b008b71e --- /dev/null +++ b/c++/compilers/vs2015/dll/third_party_dll_install.mak @@ -0,0 +1,62 @@ +# $Id: third_party_dll_install.mak 492981 2016-02-23 16:27:34Z gouriano $ +################################################################# + + +INSTALL = .\bin +INSTALL_BINPATH = $(INSTALL)\$(INTDIR) +THIRDPARTY_MAKEFILES_DIR = . + + +META_MAKE = $(THIRDPARTY_MAKEFILES_DIR)\..\third_party_install.meta.mk +!IF EXIST($(META_MAKE)) +!INCLUDE $(META_MAKE) +!ELSE +!ERROR $(META_MAKE) not found +!ENDIF + +THIRD_PARTY_LIBS = \ + install_berkeleydb \ + install_gnutls \ + install_glew \ + install_lzo \ + install_mssql \ + install_mysql \ + install_openssl \ + install_sqlite \ + install_sqlite3 \ + install_sybase \ + install_wxwidgets \ + install_wxwindows \ + install_xalan \ + install_xerces \ + install_libxml \ + install_libxslt \ + install_vdb + +CLEAN_THIRD_PARTY_LIBS = \ + clean_berkeleydb \ + clean_gnutls \ + clean_glew \ + clean_lzo \ + clean_mssql \ + clean_mysql \ + clean_openssl \ + clean_sqlite \ + clean_sqlite3 \ + clean_sybase \ + clean_wxwidgets \ + clean_wxwindows \ + clean_xalan \ + clean_xerces \ + clean_libxml \ + clean_libxslt \ + clean_vdb + +all : dirs $(THIRD_PARTY_LIBS) + +clean : $(CLEAN_THIRD_PARTY_LIBS) + +rebuild : clean all + +dirs : + @if not exist $(INSTALL_BINPATH) (echo Creating directory $(INSTALL_BINPATH)... & mkdir $(INSTALL_BINPATH)) diff --git a/c++/compilers/vs2015/dll/third_party_dll_install.vcxproj b/c++/compilers/vs2015/dll/third_party_dll_install.vcxproj new file mode 100644 index 00000000..fb0b4650 --- /dev/null +++ b/c++/compilers/vs2015/dll/third_party_dll_install.vcxproj @@ -0,0 +1,433 @@ + + + + + DebugDLL + Win32 + + + DebugDLL + x64 + + + DebugMT + Win32 + + + DebugMT + x64 + + + ReleaseDLL + Win32 + + + ReleaseDLL + x64 + + + ReleaseMT + Win32 + + + ReleaseMT + x64 + + + Unicode_DebugDLL + Win32 + + + Unicode_DebugDLL + x64 + + + Unicode_DebugMT + Win32 + + + Unicode_DebugMT + x64 + + + Unicode_ReleaseDLL + Win32 + + + Unicode_ReleaseDLL + x64 + + + Unicode_ReleaseMT + Win32 + + + Unicode_ReleaseMT + x64 + + + VTune_DebugDLL + Win32 + + + VTune_DebugDLL + x64 + + + VTune_DebugMT + Win32 + + + VTune_DebugMT + x64 + + + VTune_ReleaseDLL + Win32 + + + VTune_ReleaseDLL + x64 + + + VTune_ReleaseMT + Win32 + + + VTune_ReleaseMT + x64 + + + + {9E4B5381-9B6C-4867-BF8A-F1AAA1FD580F} + MakeFileProj + + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_dll_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" clean IntDir=$(IntDir) + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_dll_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" clean IntDir=$(IntDir) + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_dll_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" clean IntDir=$(IntDir) + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_dll_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" clean IntDir=$(IntDir) + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_dll_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" clean IntDir=$(IntDir) + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_dll_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" clean IntDir=$(IntDir) + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_dll_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" clean IntDir=$(IntDir) + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_dll_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" clean IntDir=$(IntDir) + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_dll_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" clean IntDir=$(IntDir) + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_dll_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" clean IntDir=$(IntDir) + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_dll_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" clean IntDir=$(IntDir) + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_dll_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" clean IntDir=$(IntDir) + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_dll_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" clean IntDir=$(IntDir) + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_dll_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" clean IntDir=$(IntDir) + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_dll_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" clean IntDir=$(IntDir) + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_dll_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" clean IntDir=$(IntDir) + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_dll_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" clean IntDir=$(IntDir) + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_dll_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" clean IntDir=$(IntDir) + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_dll_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" clean IntDir=$(IntDir) + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_dll_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" clean IntDir=$(IntDir) + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_dll_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" clean IntDir=$(IntDir) + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_dll_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" clean IntDir=$(IntDir) + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_dll_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" clean IntDir=$(IntDir) + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_dll_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" clean IntDir=$(IntDir) + dlls-install.exe + + + + + + + + + + diff --git a/c++/compilers/vs2015/dll/third_party_msvcdll_install.vcxproj b/c++/compilers/vs2015/dll/third_party_msvcdll_install.vcxproj new file mode 100644 index 00000000..c7b2fc74 --- /dev/null +++ b/c++/compilers/vs2015/dll/third_party_msvcdll_install.vcxproj @@ -0,0 +1,433 @@ + + + + + DebugDLL + Win32 + + + DebugDLL + x64 + + + DebugMT + Win32 + + + DebugMT + x64 + + + ReleaseDLL + Win32 + + + ReleaseDLL + x64 + + + ReleaseMT + Win32 + + + ReleaseMT + x64 + + + VTune_DebugDLL + Win32 + + + VTune_DebugDLL + x64 + + + VTune_DebugMT + Win32 + + + VTune_DebugMT + x64 + + + VTune_ReleaseDLL + Win32 + + + VTune_ReleaseDLL + x64 + + + VTune_ReleaseMT + Win32 + + + VTune_ReleaseMT + x64 + + + Unicode_DebugDLL + Win32 + + + Unicode_DebugDLL + x64 + + + Unicode_DebugMT + Win32 + + + Unicode_DebugMT + x64 + + + Unicode_ReleaseDLL + Win32 + + + Unicode_ReleaseDLL + x64 + + + Unicode_ReleaseMT + Win32 + + + Unicode_ReleaseMT + x64 + + + + {9E4B5381-9B6C-4867-BF8A-F1AAA1FD581F} + MakeFileProj + + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015" + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015.64" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015.64" + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015" + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015.64" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015.64" + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015" + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015.64" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015.64" + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015" + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015.64" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015.64" + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015" + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015.64" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015.64" + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015" + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015.64" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015.64" + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015" + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015.64" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015.64" + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015" + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015.64" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015.64" + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015" + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015.64" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015.64" + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015" + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015.64" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015.64" + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015" + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015.64" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015.64" + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015" + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015.64" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_dll_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015.64" + dlls-install.exe + + + + + + + + + + diff --git a/c++/compilers/vs2015/install.sh b/c++/compilers/vs2015/install.sh new file mode 100644 index 00000000..0a891f67 --- /dev/null +++ b/c++/compilers/vs2015/install.sh @@ -0,0 +1,186 @@ +#! /bin/sh +# $Id: install.sh 493164 2016-02-24 19:08:26Z ivanov $ +# Authors: Denis Vakatov (vakatov@ncbi.nlm.nih.gov) +# Anton Lavrentiev (lavr@ncbi.nlm.nih.gov) +# +# Deploy sources, headers, libraries and executables for the further use +# by the "external" users' projects + + +# Cmd.-line args -- source and destination +script="$0" +builddir="$1" +target="$2" +compiler="${3:-vs2015}" + +# Real number of argument is 2. +# The 3th argument do not used here (32|64-bit architecture), +# but is needed for master installation script. +if test -n "$4" ; then + echo "USAGE: `basename $script` [build_dir] [install_dir]" +fi + + +error() +{ + echo "[`basename $script`] ERROR: $1" + exit 1 +} + + +makedir() +{ + test -d "$1" || mkdir $2 "$1" || error "Cannot create \"$1\"" +} + + +echo "[`basename $script`] NCBI C++: \"$builddir\" to \"$target\"..." + + +# Derive the destination dirs +docdir="$target"/doc +scriptdir="$target"/scripts +incdir="$target"/include +srcdir="$target"/src +libdir="$target"/lib +bindir="$target"/bin +cldir="$target"/compilers +logdir="$target"/logs +tmpdir="$target"/tmp + + +install() +{ + test -d "$1" || return; + makedir "$2" -p + tmp_cwd=`pwd` + cd "$1" + find . -type f | + grep -v '/\.svn/' > "$tmpdir"/flist + tar cf - -T "$tmpdir"/flist | (cd "$2" ; tar xf - ) + cd "$tmp_cwd" +} + + + +# Check +test -d "$builddir" || error "Absent build dir \"$builddir\"" + + +# Reset the public directory +test -d "$target" && find "$target" -type f -exec rm -f {} \; >/dev/null 2>&1 +makedir "$target" -p +makedir "$tmpdir" -p + + +# Documentation +echo "[`basename $script`] Installing documentation..." +install "$builddir/doc" "$docdir" + +# Scripts +echo "[`basename $script`] Installing scripts..." +install "$builddir/scripts" "$scriptdir" + +# Include dir +echo "[`basename $script`] Installing include files..." +install "$builddir/include" "$incdir" + +# Source dir +echo "[`basename $script`] Installing source files..." +install "$builddir/src" "$srcdir" + +# Build logs +echo "[`basename $script`] Installing build logs..." +install "$builddir/logs" "$logdir" + +rm -rf "$tmpdir" + + +# Libraries +echo "[`basename $script`] Installing libraries..." +for i in 'Debug' 'Release' ; do + for j in '' 'DLL' ; do + for b in 'static' 'dll' ; do + + if test -d "$builddir"/compilers/$compiler/$b/lib/$i$j ; then + makedir "$libdir/$b/$i$j" -p + cd "$builddir"/compilers/$compiler/$b/lib/$i$j + cp -p *.lib "$libdir/$b/$i$j" + fi + if test "$b"=='dll' ; then + if test -d "$builddir"/compilers/$compiler/$b/bin/$i$j ; then + makedir "$libdir/$b/$i$j" -p + cd "$builddir"/compilers/$compiler/$b/bin/$i$j + cp -p *.lib *.dll *.exp "$libdir/$b/$i$j" + fi + fi + done + done +done + + +# Executables +echo "[`basename $script`] Installing executables..." +makedir "$bindir" -p +for i in 'DLL' '' ; do + if test -d "$builddir"/compilers/$compiler/static/bin/Release$i ; then + cd "$builddir"/compilers/$compiler/static/bin/Release$i + if ls *.exe >/dev/null 2>&1 ; then + cp -p *.exe *.dll *.exp *.manifest "$bindir" + break + fi + fi +done + + +# Install additional files (scripts and etc) into binary directory +cp -p "$builddir"/src/app/blast/legacy_blast.pl "$bindir" + + +# Gbench public installation +echo "[`basename $script`] Installing Gbench..." +for i in ReleaseDLL DebugDLL; do + if test -d "$builddir"/compilers/$compiler/dll/bin/"$i" ; then + cp -pr "$builddir"/compilers/$compiler/dll/bin/$i/gbench "$bindir" + break + fi +done + + +# Compiler dir (copy all .pdb and configurable files files for debug purposes) +echo "[`basename $script`] Installing .pdb files..." +makedir "$cldir" -p +pdb_files=`find "$builddir/compilers/$compiler" -type f -a \( -name '*.pdb' -o -name '*.c' -o -name '*.cpp' \) 2>/dev/null` +cd "$cldir" +for pdb in $pdb_files ; do + # Do not copy .pdb for executable files to save space + exe=`echo $pdb | sed -e 's|\.pdb$|\.exe|'` + if test -x "$exe" ; then + continue + fi + rel_dir=`echo $pdb | sed -e "s|$builddir/compilers/||" -e 's|/[^/]*$||'` + makedir "$rel_dir" -p + cp -pr "$pdb" "$rel_dir" +done + + +# Compiler dir (other common stuff) +makedir "$cldir"/$compiler/static -p +makedir "$cldir"/$compiler/dll -p +cp -p "$builddir"/compilers/$compiler/* "$cldir"/$compiler +cp -p "$builddir"/compilers/$compiler/static/* "$cldir"/$compiler/static +cp -p "$builddir"/compilers/$compiler/dll/* "$cldir"/$compiler/dll +for b in 'static' 'dll' ; do + cp -pr "$builddir"/compilers/$compiler/$b/inc "$cldir"/$compiler/$b + for c in 'DebugMT' 'ReleaseMT' 'DebugDLL' 'ReleaseDLL'; do + cp -pr "$builddir"/compilers/$compiler/$b/$c "$cldir"/$compiler/$b + done +done + +# Makefile.*.mk files +find "$builddir/src" -type f -name 'Makefile.*.mk' -exec cp -pr {} "$srcdir"/build-system/ \; + +# Copy info files +cp -p "$builddir"/*_info "$target" + +exit 0 diff --git a/c++/compilers/vs2015/lock_ptb_config.bat b/c++/compilers/vs2015/lock_ptb_config.bat new file mode 100644 index 00000000..94da10dc --- /dev/null +++ b/c++/compilers/vs2015/lock_ptb_config.bat @@ -0,0 +1,94 @@ +@echo off +REM $Id: lock_ptb_config.bat 492980 2016-02-23 16:24:57Z gouriano $ +REM =========================================================================== +REM +REM PUBLIC DOMAIN NOTICE +REM National Center for Biotechnology Information +REM +REM This software/database is a "United States Government Work" under the +REM terms of the United States Copyright Act. It was written as part of +REM the author's official duties as a United States Government employee and +REM thus cannot be copyrighted. This software/database is freely available +REM to the public for use. The National Library of Medicine and the U.S. +REM Government have not placed any restriction on its use or reproduction. +REM +REM Although all reasonable efforts have been taken to ensure the accuracy +REM and reliability of the software and data, the NLM and the U.S. +REM Government do not and cannot warrant the performance or results that +REM may be obtained by using this software or data. The NLM and the U.S. +REM Government disclaim all warranties, express or implied, including +REM warranties of performance, merchantability or fitness for any particular +REM purpose. +REM +REM Please cite the author in any work or product based on this material. +REM +REM =========================================================================== +REM +REM Author: Andrei Gourianov +REM +REM Check platform name and create a lock to prevent +REM running more than one instance of project_tree_builder.exe at the same time. +REM +REM =========================================================================== + +set CFG_PLATFORM=__configured_platform +set CFG_LIST=Win32 x64 +set PTB_RUNNING=__configure.lock + +if _%PTB_PLATFORM%==_ ( + echo PTB_PLATFORM is undefined + goto return_error +) +if _%1%==_ goto report_usage +if _%2%==_ goto report_usage +set MSVC_PRJ=%~2% +if %1%==ON goto do_ON +if %1%==OFF goto do_OFF + + +:report_usage +echo The script checks MSVC platform name and creates a lock to prevent +echo running more than one -CONFIGURE- at the same time. +echo Usage: +echo lock_ptb_config ON msvc_prj_folder, or +echo lock_ptb_config OFF msvc_prj_folder +goto return_error + +:return_error +exit /b 1 + +:do_ON +for %%c in ( %CFG_LIST% ) do ( + if exist "%MSVC_PRJ%%CFG_PLATFORM%.%%c" ( + if not %%c==%PTB_PLATFORM% ( + echo ****************************************************************************** + echo Requested platform %PTB_PLATFORM% does not match already configured %%c + echo If you believe it is not so, - delete '%MSVC_PRJ%%CFG_PLATFORM%.%%c' file + echo ****************************************************************************** + goto return_error + ) + goto do_ON_lock + ) +) +echo %CFG_PLATFORM% > "%MSVC_PRJ%%CFG_PLATFORM%.%PTB_PLATFORM%" + +:do_ON_lock +if exist "%MSVC_PRJ%%PTB_RUNNING%" ( + echo ****************************************************************************** + echo There is another CONFIGURE process running in this tree. + echo If you believe it is not so, - delete '%MSVC_PRJ%%PTB_RUNNING%' file + echo ****************************************************************************** + goto return_error +) +echo ptb_running > "%MSVC_PRJ%%PTB_RUNNING%" +goto done + + +:do_OFF +if exist "%MSVC_PRJ%%PTB_RUNNING%" ( + del "%MSVC_PRJ%%PTB_RUNNING%" +) +goto done + +:done + diff --git a/c++/compilers/vs2015/make.bat b/c++/compilers/vs2015/make.bat new file mode 100644 index 00000000..88352cd1 --- /dev/null +++ b/c++/compilers/vs2015/make.bat @@ -0,0 +1,223 @@ +@ECHO OFF +REM $Id: make.bat 509501 2016-08-05 19:08:31Z fukanchi $ +REM =========================================================================== +REM +REM PUBLIC DOMAIN NOTICE +REM National Center for Biotechnology Information +REM +REM This software/database is a "United States Government Work" under the +REM terms of the United States Copyright Act. It was written as part of +REM the author's official duties as a United States Government employee and +REM thus cannot be copyrighted. This software/database is freely available +REM to the public for use. The National Library of Medicine and the U.S. +REM Government have not placed any restriction on its use or reproduction. +REM +REM Although all reasonable efforts have been taken to ensure the accuracy +REM and reliability of the software and data, the NLM and the U.S. +REM Government do not and cannot warrant the performance or results that +REM may be obtained by using this software or data. The NLM and the U.S. +REM Government disclaim all warranties, express or implied, including +REM warranties of performance, merchantability or fitness for any particular +REM purpose. +REM +REM Please cite the author in any work or product based on this material. +REM +REM =========================================================================== +REM +REM Author: Vladimir Ivanov +REM +REM Configure/build/check NCBI C++ tree in specified configuration(s) +REM +REM make.bat <32|64> [cfgs..] +REM +REM %1% - Configure, build, make (configure and build_ or check build tree. +REM %2% - Solution file name without extention (relative path from build directory). +REM %3% - Type of used libraries (static, dll). +REM %4% - 32/64-bits architerture. +REM %5% - Configuration name(s) +REM (DebugDLL, DebugMT, ReleaseDLL, ReleaseMT, Unicode_*). +REM By default (if not specified) build DebugDLL and ReleaseDLL only. +REM ... - Options (--with-openmp) +REM +REM =========================================================================== + + + +rem --- Configuration + +set compiler=vs2015 +set default_cfgs=ReleaseDLL DebugDLL + +rem Always configure with additional Unicode configurations +if _%SRV_NAME% == _ set SRV_NAME=%COMPUTERNAME% + +call msvcvars.bat > NUL + + +rem --- Required parameters + +set cmd=%~1% +set solution=%~2 +set libdll=%~3 +set arch=%~4 + +set archw=Win32 +set archwc=x86 +if _%arch%_ == _64_ set archw=x64 +if _%arch%_ == _64_ set archwc=x64 + +shift +shift +shift +shift + +if "%cmd%" == "" goto NOARGS +if "%solution%" == "" goto USAGE +if "%libdll%" == "" goto USAGE +if "%arch%" == "" goto USAGE + +goto PARSEARGS + + +rem -------------------------------------------------------------------------------- +:NOARGS + +if exist configure_make.bat ( + configure_make.bat +) else ( + goto USAGE +) + +:USAGE + +echo FATAL: Invalid parameters. See script description. +echo FATAL: Passed arguments: %* +goto ABORT + + + +rem -------------------------------------------------------------------------------- +rem Parse arguments +:PARSEARGS + +set with_openmp= +set cfgs= +set unknown= + +:PARSEARGSLOOP +if "%1" == "" goto ENDPARSEARGS +if "%1" == "--with-openmp" (set with_openmp=%1 & goto CONTINUEPARSEARGS) +if "%1" == "DebugDLL" (set cfgs=%cfgs% %1 & goto CONTINUEPARSEARGS) +if "%1" == "DebugMT" (set cfgs=%cfgs% %1 & goto CONTINUEPARSEARGS) +if "%1" == "ReleaseDLL" (set cfgs=%cfgs% %1 & goto CONTINUEPARSEARGS) +if "%1" == "ReleaseMT" (set cfgs=%cfgs% %1 & goto CONTINUEPARSEARGS) +if "%1" == "Unicode_DebugDLL" (set cfgs=%cfgs% %1 & goto CONTINUEPARSEARGS) +if "%1" == "Unicode_DebugMT" (set cfgs=%cfgs% %1 & goto CONTINUEPARSEARGS) +if "%1" == "Unicode_ReleaseDLL" (set cfgs=%cfgs% %1 & goto CONTINUEPARSEARGS) +if "%1" == "Unicode_ReleaseMT" (set cfgs=%cfgs% %1 & goto CONTINUEPARSEARGS) +set unknown=%unknown% %1 +:CONTINUEPARSEARGS +shift +goto PARSEARGSLOOP + +:ENDPARSEARGS + +if not "%unknown%" == "" ( + echo FATAL: Unknown configuration names or options specified:%unknown%. + echo %cmd% + goto ABORT +) + +if "%cfgs%" == "" set cfgs=%default_cfgs% + +rem -- Check command + +if _%cmd% == _configure goto CONFIG +if _%cmd% == _make goto CONFIG +if _%cmd% == _build goto CFGLOOP +if _%cmd% == _check goto CFGLOOP +echo FATAL: Unknown action name %cmd%. Please correct. +echo The following action names are recognized: configure, build, make, check. +goto ABORT + + +rem -------------------------------------------------------------------------------- +rem Configure: always use ReleaseDLL +:CONFIG + +rem --- Process options +if not "%with_openmp%" == "" ( + echo INFO: Ebable OpenMP. + bash -c "./build_util.sh %with_openmp%; exit $?" + if errorlevel 1 goto ABORT +) + +time /t +echo INFO: Configure "%libdll%\%solution% [ReleaseDLL|%arch%]" +%DEVENV% %libdll%\build\%solution%.sln /build "ReleaseDLL|%archwc%" /project "_CONFIGURE_" +if errorlevel 1 goto ABORT +if not _%cmd% == _make goto COMPLETE + + +rem -------------------------------------------------------------------------------- +rem Process all configurations +:CFGLOOP + +for %%c in (%cfgs%) do ( + time /t + if _%cmd% == _build ( + call :build %%c + ) + if _%cmd% == _check ( + call :check %%c + ) + if _%cmd% == _make ( + call :build %%c + if errorlevel 1 goto ABORT + call :check %%c + ) + if errorlevel 1 goto ABORT +) +goto COMPLETE + + +rem -------------------------------------------------------------------------------- +rem Subroutines + +:build + echo INFO: Building "%libdll%\%solution% [%1|%arch%]" + %DEVENV% %libdll%\build\%solution%.sln /build "%1|%archw%" /project "_BUILD_ALL_" + exit /b %errorlevel% + +:check + echo INFO: Checking init + bash -c "../../scripts/common/check/check_make_win_cfg.sh init; exit $?" + set err=0 + echo INFO: Create check script for "%libdll%\%solution% [%1|%arch%]" + bash -c "../../scripts/common/check/check_make_win_cfg.sh create %solution% %libdll% %1; exit $?" + if errorlevel 1 exit /b %errorlevel% + echo INFO: Checking "%libdll%\%solution% [%1|%arch%]" + SET CHECKSH=%libdll%/build/%solution%.check/%1/check.sh + bash -c "%CHECKSH% run; exit $?" + if errorlevel 1 set err=1 + bash -c "cp %CHECKSH%.journal check.sh.%libdll%_%1.journal; cp %CHECKSH%.log check.sh.%libdll%_%1.log" + rem Load testsuite results into DB works only if NCBI_AUTOMATED_BUILD is set to 1 + if _%NCBI_AUTOMATED_BUILD% == _1 ( + bash -c "%CHECKSH% load_to_db; exit $?" + if errorlevel 1 set err=1 + ) + copy /y /b check.sh.*.journal check.sh.journal + copy /y /b check.sh.*.log check.sh.log + exit /b %err% + + +rem -------------------------------------------------------------------------------- + +:ABORT +echo INFO: %cmd% failed. +exit /b 1 + +:COMPLETE +echo INFO: %cmd% complete. +exit /b 0 + diff --git a/c++/compilers/vs2015/make_ncbi.bat b/c++/compilers/vs2015/make_ncbi.bat new file mode 100644 index 00000000..745ee5b8 --- /dev/null +++ b/c++/compilers/vs2015/make_ncbi.bat @@ -0,0 +1,60 @@ +@ECHO OFF +REM $Id: make_ncbi.bat 492980 2016-02-23 16:24:57Z gouriano $ +REM =========================================================================== +REM +REM PUBLIC DOMAIN NOTICE +REM National Center for Biotechnology Information +REM +REM This software/database is a "United States Government Work" under the +REM terms of the United States Copyright Act. It was written as part of +REM the author's official duties as a United States Government employee and +REM thus cannot be copyrighted. This software/database is freely available +REM to the public for use. The National Library of Medicine and the U.S. +REM Government have not placed any restriction on its use or reproduction. +REM +REM Although all reasonable efforts have been taken to ensure the accuracy +REM and reliability of the software and data, the NLM and the U.S. +REM Government do not and cannot warrant the performance or results that +REM may be obtained by using this software or data. The NLM and the U.S. +REM Government disclaim all warranties, express or implied, including +REM warranties of performance, merchantability or fitness for any particular +REM purpose. +REM +REM Please cite the author in any work or product based on this material. +REM +REM =========================================================================== +REM +REM Author: Vladimir Ivanov +REM +REM Configure/build/check NCBI C++ core tree in specified configuration(s) +REM +REM make_ncbi.bat <32|64> [cfgs..] +REM +REM %1% - Configure, build, check or build and configure (make) build tree. +REM %2% - Type of used libraries (static, dll). +REM %3% - 32/64-bits architerture. +REM %4% - Configuration name(s) +REM (DEFAULT, DebugDLL, DebugMT, ReleaseDLL, ReleaseMT, Unicode_*). +REM By default build DebugDLL and ReleaseDLL only. +REM ... - Options (--with-openmp) +REM +REM =========================================================================== + + +set cmd=%~1 +set libdll=%~2 +set arch=%~3 + +shift +shift +shift + +goto:%libdll% 2>NUL + +:static +@call make.bat %cmd% ncbi_cpp %libdll% %arch% %1 %2 %3 %4 %5 %6 %7 %8 %9 +exit %ERRORLEVEL% + +:dll +@call make.bat %cmd% ncbi_cpp_dll %libdll% %arch% %1 %2 %3 %4 %5 %6 %7 %8 %9 +exit %ERRORLEVEL% diff --git a/c++/compilers/vs2015/msvcvars.bat b/c++/compilers/vs2015/msvcvars.bat new file mode 100644 index 00000000..d1729c52 --- /dev/null +++ b/c++/compilers/vs2015/msvcvars.bat @@ -0,0 +1,14 @@ +@echo off +REM +REM $Id: msvcvars.bat 492980 2016-02-23 16:24:57Z gouriano $ +REM + +@if not "%VSINSTALLDIR%"=="" goto devenv +@call "%VS140COMNTOOLS%vsvars32.bat" + +:devenv + +if exist "%VS140COMNTOOLS%..\IDE\VCExpress.*" set DEVENV="%VS140COMNTOOLS%..\IDE\VCExpress" +if exist "%VS140COMNTOOLS%..\IDE\devenv.*" set DEVENV="%VS140COMNTOOLS%..\IDE\devenv" + +:end diff --git a/c++/compilers/vs2015/ncbi.rc b/c++/compilers/vs2015/ncbi.rc new file mode 100644 index 00000000..9bcbca1d --- /dev/null +++ b/c++/compilers/vs2015/ncbi.rc @@ -0,0 +1 @@ +ncbilogo ICON "ncbilogo.ico" diff --git a/c++/compilers/vs2015/ncbilogo.ico b/c++/compilers/vs2015/ncbilogo.ico new file mode 100644 index 0000000000000000000000000000000000000000..44e71d4e80452e14c2d50b68f95e7a394149bb31 GIT binary patch literal 766 zcmc(dF?Pc+2!=^t4$vvH#~h=lA=$E7-t0;C)+_lqJwfqCe~^gPmkik=8^I4qe9zBB z2RvQ(Nw$7Ih)(clSO@!p9q5RiXhQAznovY#nu^1Ykk)mDw}SdhsuscUSjzNkOL$Ig zr!ezn+%u;6+9cAD(NP=3eac+4)T_3lWsbJ11+rABo1g!^g)W8sUG*?}5K~f-+VkZB zm6ry8FjmmsyCi#pgG1HnnPZaiOX}JAEcC&cB%PI%|9=Yl`3$vk^s f;BCgbc*@7A^EX=YVY$`d&;NBf_-x1T@YeMQ&kxbS literal 0 HcmV?d00001 diff --git a/c++/compilers/vs2015/ptb.bat b/c++/compilers/vs2015/ptb.bat new file mode 100644 index 00000000..42dbd490 --- /dev/null +++ b/c++/compilers/vs2015/ptb.bat @@ -0,0 +1,288 @@ +@echo off +REM $Id: ptb.bat 507295 2016-07-18 15:40:58Z gouriano $ +REM =========================================================================== +REM +REM PUBLIC DOMAIN NOTICE +REM National Center for Biotechnology Information +REM +REM This software/database is a "United States Government Work" under the +REM terms of the United States Copyright Act. It was written as part of +REM the author's official duties as a United States Government employee and +REM thus cannot be copyrighted. This software/database is freely available +REM to the public for use. The National Library of Medicine and the U.S. +REM Government have not placed any restriction on its use or reproduction. +REM +REM Although all reasonable efforts have been taken to ensure the accuracy +REM and reliability of the software and data, the NLM and the U.S. +REM Government do not and cannot warrant the performance or results that +REM may be obtained by using this software or data. The NLM and the U.S. +REM Government disclaim all warranties, express or implied, including +REM warranties of performance, merchantability or fitness for any particular +REM purpose. +REM +REM Please cite the author in any work or product based on this material. +REM +REM =========================================================================== +REM +REM Author: Andrei Gourianov +REM +REM Run project_tree_builder.exe to generate MSVC solution and project files +REM +REM DO NOT ATTEMPT to run this bat file manually +REM It should be run by CONFIGURE project only +REM (open a solution and build or rebuild CONFIGURE project) +REM +REM =========================================================================== + +setlocal +set DEFPTB_LOCATION=\\snowman\win-coremake\App\Ncbi\cppcore\ptb +set IDE=1400 +set PTB_EXTRA= + +for %%v in ("%PTB_PATH%" "%SLN_PATH%" "%TREE_ROOT%" "%BUILD_TREE_ROOT%" "%PTB_PLATFORM%") do ( + if %%v=="" ( + echo ERROR: required environment variable is missing + echo DO NOT ATTEMPT to run this bat file manually + echo It should be run by CONFIGURE project only + exit /b 1 + ) +) +set PTBGUI="%TREE_ROOT%\src\build-system\project_tree_builder_gui\bin\ptbgui.jar" +set DEFPTB_VERSION_FILE=%TREE_ROOT%\src\build-system\ptb_version.txt +set PTB_INI=%TREE_ROOT%\src\build-system\project_tree_builder.ini +set PTB_SLN=%BUILD_TREE_ROOT%\static\build\UtilityProjects\PTB.sln +set NCBICONF_MSVC=%TREE_ROOT%\include\common\config\ncbiconf_msvc_site.h +if exist "%NCBICONF_MSVC%" ( + set NCBICONF_MSVC= +) + +REM --- get solution dir --- +call :XSLNPATH %SLN_PATH% +goto DONE +:XSLNPATH +set SLN_DIR=%~dp1 +goto :eof +:DONE +REM --- call pre-configure script if it exists --- +if exist "%SLN_DIR%configure_prebuild.bat" ( + call "%SLN_DIR%configure_prebuild.bat" +) + +call "%BUILD_TREE_ROOT%\msvcvars.bat" + +REM ------------------------------------------------------------------------- +REM get PTB version: from DEFPTB_VERSION_FILE or from PREBUILT_PTB_EXE + +set DEFPTB_VERSION= +if exist "%DEFPTB_VERSION_FILE%" ( + for /f %%a in ('type "%DEFPTB_VERSION_FILE%"') do (set DEFPTB_VERSION=%%a& goto donedf) + :donedf + set DEFPTB_VERSION=%DEFPTB_VERSION: =% +) +if exist "%PREBUILT_PTB_EXE%" ( + set ptbver= + for /f "tokens=2" %%a in ('"%PREBUILT_PTB_EXE%" -version') do (set ptbver=%%a& goto donepb) + :donepb + set ptbver=%ptbver: =% + if not "%DEFPTB_VERSION%"=="%ptbver%" ( + echo WARNING: requested PTB version %ptbver% does not match default one: %DEFPTB_VERSION% + set DEFPTB_VERSION=%ptbver% + ) +) + +if "%DEFPTB_VERSION%"=="" ( + echo ERROR: DEFPTB_VERSION not specified + exit /b 1 +) +for /f "tokens=1-3 delims=." %%a in ('echo %DEFPTB_VERSION%') do (set PTB_VER=%%a%%b%%c& set PTB_VER_MAJOR=%%a) + + +REM ------------------------------------------------------------------------- +REM See if we should and can use Java GUI + +set REQ_GUI_CFG=NO +set USE_GUI_CFG=NO +for /f "tokens=*" %%i in ('echo %PTB_FLAGS%') do call :PARSE %%i +goto :endparse +:PARSE +if "%1"=="" goto :eof +if "%1"=="-cfg" (set REQ_GUI_CFG=YES& goto :eof) +shift +goto :PARSE +:endparse +if "%REQ_GUI_CFG%"=="YES" ( +REM if %PTB_VER_MAJOR% GEQ 2 ( + if exist "%PTBGUI%" ( + java -version >NUL 2>&1 + if errorlevel 1 ( + echo WARNING: Java not found, cannot run configuration GUI + ) else ( + set USE_GUI_CFG=YES + ) + ) else ( + echo WARNING: "%PTBGUI%" not found + ) +REM ) +) + + +REM ------------------------------------------------------------------------- +REM See if we should and can use saved settings + +set PTB_SAVED_CFG= +if not "%PTB_SAVED_CFG_REQ%"=="" ( + if not exist "%PTB_SAVED_CFG_REQ%" ( + echo ERROR: %PTB_SAVED_CFG_REQ% not found + exit /b 1 + ) + if %PTB_VER_MAJOR% GEQ 2 ( + if %PTB_VER% GEQ 220 ( + set PTB_SAVED_CFG=-args %PTB_SAVED_CFG_REQ% +REM PTB will read PTB_PROJECT from the saved settings + set PTB_PROJECT_REQ="" + ) + ) +) + + +REM ------------------------------------------------------------------------- +REM Identify PTB_EXE + +if "%PREBUILT_PTB_EXE%"=="bootstrap" ( + set DEF_PTB=%PTB_PATH%\project_tree_builder.exe +) else if not "%PREBUILT_PTB_EXE%"=="" ( + if exist "%PREBUILT_PTB_EXE%" ( + set DEF_PTB=%PREBUILT_PTB_EXE% + ) else ( + echo ERROR: "%PREBUILT_PTB_EXE%" not found + exit /b 1 + ) +) else ( +REM if %PTB_VER% GEQ 180 ( + set DEF_PTB=%DEFPTB_LOCATION%\msvc\%DEFPTB_VERSION%\project_tree_builder.exe +REM ) else ( +REM if "%PTB_PLATFORM%"=="x64" ( +REM set DEF_PTB=%DEFPTB_LOCATION%\msvc9.64\%DEFPTB_VERSION%\project_tree_builder.exe +REM ) else ( +REM set DEF_PTB=%DEFPTB_LOCATION%\msvc9\%DEFPTB_VERSION%\project_tree_builder.exe +REM ) + ) +) +if exist "%DEF_PTB%" ( + set PTB_EXE=%DEF_PTB% +) else ( + echo project_tree_builder.exe not found at %DEF_PTB% + set PTB_EXE=%PTB_PATH%\project_tree_builder.exe +) + +REM ------------------------------------------------------------------------- +REM Misc settings + +REM if %PTB_VER% GEQ 180 ( + set PTB_EXTRA=%PTB_EXTRA% -ide %IDE% -arch %PTB_PLATFORM% +REM ) +if not exist "%PTB_INI%" ( + echo ERROR: "%PTB_INI%" not found + exit /b 1 +) +set PTB_PROJECT_LST= +if "%PTB_PROJECT%"=="" ( + set PTB_PROJECT_LST=%PTB_PROJECT_REQ% +) else ( + set PTB_PROJECT_LST=%PTB_PROJECT% +) + + +REM ------------------------------------------------------------------------- +REM Build PTB_EXE if needed + +set NCBI_CONFIG__DIAG__POST_FILTER=!(807,9) +if not exist "%PTB_EXE%" ( + echo ****************************************************************************** + echo Building project tree builder locally, please wait + echo ****************************************************************************** + rem --- @echo msbuild "%BUILD_TREE_ROOT%\static\build\ncbi_cpp.sln" /t:"project_tree_builder_exe:Rebuild" /p:Configuration=ReleaseDLL;Platform=%PTB_PLATFORM% /maxcpucount:1 + rem --- msbuild "%BUILD_TREE_ROOT%\static\build\ncbi_cpp.sln" /t:"project_tree_builder_exe:Rebuild" /p:Configuration=ReleaseDLL;Platform=%PTB_PLATFORM% /maxcpucount:1 + if not "%NCBICONF_MSVC%"=="" ( + echo // > "%NCBICONF_MSVC%" + ) + if exist "%PTB_SLN%" ( + @echo %DEVENV% "%PTB_SLN%" /rebuild "ReleaseDLL|%PTB_PLATFORM%" /project "project_tree_builder.exe" + %DEVENV% "%PTB_SLN%" /rebuild "ReleaseDLL|%PTB_PLATFORM%" /project "project_tree_builder.exe" + ) else ( + @echo %DEVENV% "%BUILD_TREE_ROOT%\static\build\ncbi_cpp.sln" /rebuild "ReleaseDLL|%PTB_PLATFORM%" /project "project_tree_builder.exe" + %DEVENV% "%BUILD_TREE_ROOT%\static\build\ncbi_cpp.sln" /rebuild "ReleaseDLL|%PTB_PLATFORM%" /project "project_tree_builder.exe" + ) + if not "%NCBICONF_MSVC%"=="" ( + del "%NCBICONF_MSVC%" + ) +) else ( + echo ****************************************************************************** + echo Using PREBUILT project tree builder at %PTB_EXE% + echo ****************************************************************************** +) +set NCBI_CONFIG__DIAG__POST_FILTER= + +if not exist "%PTB_EXE%" ( + echo ERROR: "%PTB_EXE%" not found + exit /b 1 +) +"%PTB_EXE%" -version +if errorlevel 1 ( + echo ERROR: cannot find working %PTB_EXE% + exit /b 1 +) + + +REM ------------------------------------------------------------------------- +REM Run PTB_EXE + +call "%BUILD_TREE_ROOT%\lock_ptb_config.bat" ON "%BUILD_TREE_ROOT%\" +if errorlevel 1 exit /b 1 + +echo ****************************************************************************** +echo Running -CONFIGURE- please wait +echo ****************************************************************************** +echo "%PTB_EXE%" %PTB_FLAGS% %PTB_EXTRA% %PTB_SAVED_CFG% -logfile "%SLN_PATH%_configuration_log.txt" -conffile "%PTB_INI%" "%TREE_ROOT%" %PTB_PROJECT_LST% "%SLN_PATH%" +if "%USE_GUI_CFG%"=="YES" ( + java -jar %PTBGUI% "%PTB_EXE%" -i %PTB_FLAGS% %PTB_EXTRA% %PTB_SAVED_CFG% -logfile "%SLN_PATH%_configuration_log.txt" -conffile "%PTB_INI%" "%TREE_ROOT%" %PTB_PROJECT_LST% "%SLN_PATH%" +) else ( + "%PTB_EXE%" %PTB_FLAGS% %PTB_EXTRA% %PTB_SAVED_CFG% -logfile "%SLN_PATH%_configuration_log.txt" -conffile "%PTB_INI%" "%TREE_ROOT%" %PTB_PROJECT_LST% "%SLN_PATH%" +) +if errorlevel 1 (set PTB_RESULT=1) else (set PTB_RESULT=0) + +call "%BUILD_TREE_ROOT%\lock_ptb_config.bat" OFF "%BUILD_TREE_ROOT%\" + +if "%PTB_RESULT%"=="1" ( + echo ****************************************************************************** + echo -CONFIGURE- has failed + echo Configuration log was saved at "file://%SLN_PATH%_configuration_log.txt" + echo ****************************************************************************** + if exist "%SLN_PATH%_configuration_log.txt" ( + if "%DIAG_SILENT_ABORT%"=="" start "" "%SLN_PATH%_configuration_log.txt" + ) + exit /b 1 +) else ( + echo ****************************************************************************** + echo -CONFIGURE- has succeeded + echo Configuration log was saved at "file://%SLN_PATH%_configuration_log.txt" + echo ****************************************************************************** +) + +set ALLOBJ="_generate_all_objects.dataspec" +type "%SLN_PATH%" | %SystemRoot%\system32\find /C %ALLOBJ% >NUL 2>&1 +if not errorlevel 1 ( + echo ****************************************************************************** + echo ****************************************************************************** + echo ============== Generating objects source code. ============== + echo ============== DO NOT RELOAD THE SOLUTION NOW! ============== + echo ****************************************************************************** + echo %DEVENV% "%SLN_PATH%" /build "ReleaseDLL|%PTB_PLATFORM%" /project %ALLOBJ% + %DEVENV% "%SLN_PATH%" /build "ReleaseDLL|%PTB_PLATFORM%" /project %ALLOBJ% +) +echo - +echo - +echo ****************************************************************************** +echo ============== It is now safe to reload the solution: ============== +echo ============== Please, close it and open again ============== +echo ****************************************************************************** diff --git a/c++/compilers/vs2015/static/build/UtilityProjects/PTB.sln b/c++/compilers/vs2015/static/build/UtilityProjects/PTB.sln new file mode 100644 index 00000000..ae40085a --- /dev/null +++ b/c++/compilers/vs2015/static/build/UtilityProjects/PTB.sln @@ -0,0 +1,79 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_CONFIGURE_", "_CONFIGURE_.vcxproj", "{8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA105}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_CONFIGURE_DIALOG_", "_CONFIGURE_DIALOG_.vcxproj", "{E7DBEF6D-5DA9-4B0D-9375-C3F26659827B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xncbi.lib", "..\corelib\xncbi.lib.vcxproj", "{1EDB6A26-ADB9-4591-B907-505E8D1A8157}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xser.lib", "..\serial\xser.lib.vcxproj", "{1F5BCB57-26A5-46C7-B87C-FA74072CF5F6}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xutil.lib", "..\util\xutil.lib.vcxproj", "{1DCE18CD-4A7E-43B8-B7AF-48972EFE51E7}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "msbuild_dataobj.lib", "..\build-system\project_tree_builder\msbuild\msbuild_dataobj.lib.vcxproj", "{FCA4C590-AB16-40F4-8C05-C41EF2A0F2FB}" + ProjectSection(ProjectDependencies) = postProject + {BB57FAAE-2EFE-46A0-8157-8879C5AC76C9} = {BB57FAAE-2EFE-46A0-8157-8879C5AC76C9} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "datatool.exe", "..\serial\datatool\datatool.exe.vcxproj", "{BB57FAAE-2EFE-46A0-8157-8879C5AC76C9}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "project_tree_builder.exe", "..\build-system\project_tree_builder\project_tree_builder.exe.vcxproj", "{8D5B9C1E-5941-44F8-B017-25F6201E822B}" + ProjectSection(ProjectDependencies) = postProject + {BB57FAAE-2EFE-46A0-8157-8879C5AC76C9} = {BB57FAAE-2EFE-46A0-8157-8879C5AC76C9} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xregexp.lib", "..\util\xregexp\xregexp.lib.vcxproj", "{E46C5B0B-675C-4C37-B618-02608C379C67}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "regexp.lib", "..\util\regexp\regexp.lib.vcxproj", "{DFDE1494-ED69-4C4F-84D3-0D19DB1B424C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + ReleaseDLL|Win32 = ReleaseDLL|Win32 + ReleaseDLL|x64 = ReleaseDLL|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA105}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA105}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA105}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA105}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + {E7DBEF6D-5DA9-4B0D-9375-C3F26659827B}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32 + {E7DBEF6D-5DA9-4B0D-9375-C3F26659827B}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32 + {E7DBEF6D-5DA9-4B0D-9375-C3F26659827B}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 + {E7DBEF6D-5DA9-4B0D-9375-C3F26659827B}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + {1EDB6A26-ADB9-4591-B907-505E8D1A8157}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32 + {1EDB6A26-ADB9-4591-B907-505E8D1A8157}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32 + {1EDB6A26-ADB9-4591-B907-505E8D1A8157}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 + {1EDB6A26-ADB9-4591-B907-505E8D1A8157}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + {1F5BCB57-26A5-46C7-B87C-FA74072CF5F6}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32 + {1F5BCB57-26A5-46C7-B87C-FA74072CF5F6}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32 + {1F5BCB57-26A5-46C7-B87C-FA74072CF5F6}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 + {1F5BCB57-26A5-46C7-B87C-FA74072CF5F6}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + {1DCE18CD-4A7E-43B8-B7AF-48972EFE51E7}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32 + {1DCE18CD-4A7E-43B8-B7AF-48972EFE51E7}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32 + {1DCE18CD-4A7E-43B8-B7AF-48972EFE51E7}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 + {1DCE18CD-4A7E-43B8-B7AF-48972EFE51E7}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + {FCA4C590-AB16-40F4-8C05-C41EF2A0F2FB}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32 + {FCA4C590-AB16-40F4-8C05-C41EF2A0F2FB}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32 + {FCA4C590-AB16-40F4-8C05-C41EF2A0F2FB}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 + {FCA4C590-AB16-40F4-8C05-C41EF2A0F2FB}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + {BB57FAAE-2EFE-46A0-8157-8879C5AC76C9}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32 + {BB57FAAE-2EFE-46A0-8157-8879C5AC76C9}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32 + {BB57FAAE-2EFE-46A0-8157-8879C5AC76C9}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 + {BB57FAAE-2EFE-46A0-8157-8879C5AC76C9}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + {8D5B9C1E-5941-44F8-B017-25F6201E822B}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32 + {8D5B9C1E-5941-44F8-B017-25F6201E822B}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32 + {8D5B9C1E-5941-44F8-B017-25F6201E822B}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 + {8D5B9C1E-5941-44F8-B017-25F6201E822B}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + {E46C5B0B-675C-4C37-B618-02608C379C67}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32 + {E46C5B0B-675C-4C37-B618-02608C379C67}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32 + {E46C5B0B-675C-4C37-B618-02608C379C67}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 + {E46C5B0B-675C-4C37-B618-02608C379C67}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + {DFDE1494-ED69-4C4F-84D3-0D19DB1B424C}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32 + {DFDE1494-ED69-4C4F-84D3-0D19DB1B424C}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32 + {DFDE1494-ED69-4C4F-84D3-0D19DB1B424C}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 + {DFDE1494-ED69-4C4F-84D3-0D19DB1B424C}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/c++/compilers/vs2015/static/build/UtilityProjects/_CONFIGURE_.vcxproj b/c++/compilers/vs2015/static/build/UtilityProjects/_CONFIGURE_.vcxproj new file mode 100644 index 00000000..bd6c7585 --- /dev/null +++ b/c++/compilers/vs2015/static/build/UtilityProjects/_CONFIGURE_.vcxproj @@ -0,0 +1,144 @@ + + + + + DebugDLL + Win32 + + + DebugDLL + x64 + + + ReleaseDLL + Win32 + + + ReleaseDLL + x64 + + + + _CONFIGURE_ + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA105} + MasterProject + ManagedCProj + + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_ + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_ + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_ + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_ + + + + X64 + + + + + X64 + + + + + Document + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_cpp.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_cpp.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_cpp.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_cpp.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + + + + + + \ No newline at end of file diff --git a/c++/compilers/vs2015/static/build/UtilityProjects/_CONFIGURE_DIALOG_.vcxproj b/c++/compilers/vs2015/static/build/UtilityProjects/_CONFIGURE_DIALOG_.vcxproj new file mode 100644 index 00000000..74fc0979 --- /dev/null +++ b/c++/compilers/vs2015/static/build/UtilityProjects/_CONFIGURE_DIALOG_.vcxproj @@ -0,0 +1,144 @@ + + + + + DebugDLL + Win32 + + + DebugDLL + x64 + + + ReleaseDLL + Win32 + + + ReleaseDLL + x64 + + + + _CONFIGURE_DIALOG_ + {E7DBEF6D-5DA9-4B0D-9375-C3F26659827B} + MasterProject + ManagedCProj + + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_DIALOG_ + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_DIALOG_ + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_DIALOG_ + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_DIALOG_ + + + + X64 + + + + + X64 + + + + + Document + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_cpp.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_cpp.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_cpp.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_cpp.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + + + + + + \ No newline at end of file diff --git a/c++/compilers/vs2015/static/build/UtilityProjects/configure._ b/c++/compilers/vs2015/static/build/UtilityProjects/configure._ new file mode 100644 index 00000000..49cbd649 --- /dev/null +++ b/c++/compilers/vs2015/static/build/UtilityProjects/configure._ @@ -0,0 +1,4 @@ +set PTB_FLAGS= +set PTB_PROJECT_REQ=scripts\projects\ncbi_cpp.lst +call "%BUILD_TREE_ROOT%\ptb.bat" +if errorlevel 1 exit 1 diff --git a/c++/compilers/vs2015/static/build/UtilityProjects/configure_dialog._ b/c++/compilers/vs2015/static/build/UtilityProjects/configure_dialog._ new file mode 100644 index 00000000..cdd8acd4 --- /dev/null +++ b/c++/compilers/vs2015/static/build/UtilityProjects/configure_dialog._ @@ -0,0 +1,4 @@ +set PTB_FLAGS= -cfg +set PTB_PROJECT_REQ=scripts\projects\ncbi_cpp.lst +call "%BUILD_TREE_ROOT%\ptb.bat" +if errorlevel 1 exit 1 diff --git a/c++/compilers/vs2015/static/build/all.bat b/c++/compilers/vs2015/static/build/all.bat new file mode 100644 index 00000000..5e748b57 --- /dev/null +++ b/c++/compilers/vs2015/static/build/all.bat @@ -0,0 +1,39 @@ +@ECHO OFF +REM $Id: all.bat 493022 2016-02-23 18:18:54Z gouriano $ +REM =========================================================================== +REM +REM PUBLIC DOMAIN NOTICE +REM National Center for Biotechnology Information +REM +REM This software/database is a "United States Government Work" under the +REM terms of the United States Copyright Act. It was written as part of +REM the author's official duties as a United States Government employee and +REM thus cannot be copyrighted. This software/database is freely available +REM to the public for use. The National Library of Medicine and the U.S. +REM Government have not placed any restriction on its use or reproduction. +REM +REM Although all reasonable efforts have been taken to ensure the accuracy +REM and reliability of the software and data, the NLM and the U.S. +REM Government do not and cannot warrant the performance or results that +REM may be obtained by using this software or data. The NLM and the U.S. +REM Government disclaim all warranties, express or implied, including +REM warranties of performance, merchantability or fitness for any particular +REM purpose. +REM +REM Please cite the author in any work or product based on this material. +REM +REM =========================================================================== +REM +REM Author: Vladimir Ivanov +REM +REM Build all C++ Toolkit STATIC projects +REM +REM =========================================================================== + + +CALL all_ncbi.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 +IF ERRORLEVEL 1 GOTO _ABORT_ + +CALL all_gui.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 + +:_ABORT_ \ No newline at end of file diff --git a/c++/compilers/vs2015/static/build/all_gui.bat b/c++/compilers/vs2015/static/build/all_gui.bat new file mode 100644 index 00000000..4881c6a2 --- /dev/null +++ b/c++/compilers/vs2015/static/build/all_gui.bat @@ -0,0 +1,79 @@ +@ECHO OFF +REM $Id: all_gui.bat 493022 2016-02-23 18:18:54Z gouriano $ +REM =========================================================================== +REM +REM PUBLIC DOMAIN NOTICE +REM National Center for Biotechnology Information +REM +REM This software/database is a "United States Government Work" under the +REM terms of the United States Copyright Act. It was written as part of +REM the author's official duties as a United States Government employee and +REM thus cannot be copyrighted. This software/database is freely available +REM to the public for use. The National Library of Medicine and the U.S. +REM Government have not placed any restriction on its use or reproduction. +REM +REM Although all reasonable efforts have been taken to ensure the accuracy +REM and reliability of the software and data, the NLM and the U.S. +REM Government do not and cannot warrant the performance or results that +REM may be obtained by using this software or data. The NLM and the U.S. +REM Government disclaim all warranties, express or implied, including +REM warranties of performance, merchantability or fitness for any particular +REM purpose. +REM +REM Please cite the author in any work or product based on this material. +REM +REM =========================================================================== +REM +REM Author: Anton Lavrentiev +REM +REM Build NCBI C++ GUI core libraries, tests and samples +REM +REM =========================================================================== + +call "..\..\msvcvars.bat" + +IF _%1% == _ GOTO BUILDALL +IF _%1% == _ALL GOTO BUILDALL +GOTO CONFIG + +:BUILDALL +CALL %0 DebugDLL ReleaseDLL +GOTO EXIT + +:CONFIG +TIME /T +ECHO INFO: Configure "static\gui" +msbuild gui\ncbi_gui.sln /t:"_CONFIGURE_:Rebuild" /p:Configuration=ReleaseDLL +IF ERRORLEVEL 1 GOTO ABORT + +SET CFG=%1% + +:ARGLOOP +IF %CFG% == DebugMT GOTO CONTINUE +IF %CFG% == DebugDLL GOTO CONTINUE +IF %CFG% == ReleaseMT GOTO CONTINUE +IF %CFG% == ReleaseDLL GOTO CONTINUE +ECHO INFO: The following configuration names are recognized: +ECHO DebugMT DebugDLL ReleaseMT ReleaseDLL +ECHO FATAL: Unknown configuration name %CFG%. Please correct. +GOTO EXIT + +:CONTINUE +TIME /T +ECHO INFO: Building "static\gui\%CFG%" +msbuild gui\ncbi_gui.sln /t:"_BUILD_ALL_" /p:Configuration=%CFG% +REM vcbuild /M2 /time gui\ncbi_gui.sln "%CFG%|Win32" +IF ERRORLEVEL 1 GOTO ABORT + +SHIFT +IF _%1% == _ GOTO COMPLETE +SET CFG=%1% +GOTO ARGLOOP + +:ABORT +ECHO INFO: Build failed. +GOTO EXIT +:COMPLETE +ECHO INFO: Build complete. +:EXIT +set CFG= diff --git a/c++/compilers/vs2015/static/build/all_ncbi.bat b/c++/compilers/vs2015/static/build/all_ncbi.bat new file mode 100644 index 00000000..b6259d2b --- /dev/null +++ b/c++/compilers/vs2015/static/build/all_ncbi.bat @@ -0,0 +1,79 @@ +@ECHO OFF +REM $Id: all_ncbi.bat 493022 2016-02-23 18:18:54Z gouriano $ +REM =========================================================================== +REM +REM PUBLIC DOMAIN NOTICE +REM National Center for Biotechnology Information +REM +REM This software/database is a "United States Government Work" under the +REM terms of the United States Copyright Act. It was written as part of +REM the author's official duties as a United States Government employee and +REM thus cannot be copyrighted. This software/database is freely available +REM to the public for use. The National Library of Medicine and the U.S. +REM Government have not placed any restriction on its use or reproduction. +REM +REM Although all reasonable efforts have been taken to ensure the accuracy +REM and reliability of the software and data, the NLM and the U.S. +REM Government do not and cannot warrant the performance or results that +REM may be obtained by using this software or data. The NLM and the U.S. +REM Government disclaim all warranties, express or implied, including +REM warranties of performance, merchantability or fitness for any particular +REM purpose. +REM +REM Please cite the author in any work or product based on this material. +REM +REM =========================================================================== +REM +REM Author: Anton Lavrentiev +REM +REM Build NCBI C++ core libraries, tests and samples +REM +REM =========================================================================== + +call "..\..\msvcvars.bat" + +IF _%1% == _ GOTO BUILDALL +IF _%1% == _ALL GOTO BUILDALL +GOTO CONFIG + +:BUILDALL +CALL %0 DebugDLL ReleaseDLL +GOTO EXIT + +:CONFIG +TIME /T +ECHO INFO: Configure "static\ncbi" +msbuild ncbi_cpp.sln /t:"_CONFIGURE_:Rebuild" /p:Configuration=ReleaseDLL +IF ERRORLEVEL 1 GOTO ABORT + +SET CFG=%1% + +:ARGLOOP +IF %CFG% == DebugMT GOTO CONTINUE +IF %CFG% == DebugDLL GOTO CONTINUE +IF %CFG% == ReleaseMT GOTO CONTINUE +IF %CFG% == ReleaseDLL GOTO CONTINUE +ECHO INFO: The following configuration names are recognized: +ECHO DebugMT DebugDLL ReleaseMT ReleaseDLL +ECHO FATAL: Unknown configuration name %CFG%. Please correct. +GOTO EXIT + +:CONTINUE +TIME /T +ECHO INFO: Building "static\ncbi\%CFG%" +msbuild ncbi_cpp.sln /t:"_BUILD_ALL_" /p:Configuration=%CFG% +REM vcbuild /M2 /time ncbi_cpp.sln "%CFG%|Win32" +IF ERRORLEVEL 1 GOTO ABORT + +SHIFT +IF _%1% == _ GOTO COMPLETE +SET CFG=%1% +GOTO ARGLOOP + +:ABORT +ECHO INFO: Build failed. +GOTO EXIT +:COMPLETE +ECHO INFO: Build complete. +:EXIT +set CFG= diff --git a/c++/compilers/vs2015/static/build/build-system/project_tree_builder/msbuild/msbuild_dataobj.lib.vcxproj b/c++/compilers/vs2015/static/build/build-system/project_tree_builder/msbuild/msbuild_dataobj.lib.vcxproj new file mode 100644 index 00000000..fa1d48af --- /dev/null +++ b/c++/compilers/vs2015/static/build/build-system/project_tree_builder/msbuild/msbuild_dataobj.lib.vcxproj @@ -0,0 +1,149 @@ + + + {FCA4C590-AB16-40F4-8C05-C41EF2A0F2FB}Win32Projmsbuild_dataobj.lib + + + + ReleaseDLL + Win32 + + + ReleaseDLL + x64 + + + + StaticLibraryMultiByte + v140 + + StaticLibraryMultiByte + v140 + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + ..\..\..\..\lib\$(Configuration)\ + $(Configuration)\ + msbuild_dataobj + ..\..\..\..\lib\$(Configuration)\ + $(Configuration)\ + msbuild_dataobj + + + + ..\..\..\..\..\..\..\include\ + + Default + false + TRUE + Cdecl + Default + + + TRUE + Speed + FALSE + OnlyExplicitInline + FALSE + TRUE + MaxSpeed + + NDEBUG;WIN32;_LIB;_SECURE_SCL=0;_CRT_SECURE_NO_DEPRECATE=1; + $(IntDir)msbuild_dataobj.pdb + MultiThreadedDLL + TRUE + FALSE + Default + + Level3 + + + + + FALSE + + $(OutDir)$(TargetName)$(TargetExt) + + + + + + + + + + X64 + + + ..\..\..\..\..\..\..\include\ + + Default + false + TRUE + Cdecl + Default + + + TRUE + Speed + FALSE + OnlyExplicitInline + FALSE + TRUE + MaxSpeed + + NDEBUG;WIN32;_LIB;_SECURE_SCL=0;_CRT_SECURE_NO_DEPRECATE=1; + $(IntDir)msbuild_dataobj.pdb + MultiThreadedDLL + TRUE + FALSE + Default + + Level3 + + + + + FALSE + + $(OutDir)$(TargetName)$(TargetExt) + + + + + + + + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + NCBI_USE_PCH;%(PreprocessorDefinitions) + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + NCBI_USE_PCH;%(PreprocessorDefinitions) + + + + + Document + Using datatool to create a C++ object from ASN/DTD/Schema %(FullPath) + set DATATOOL_PATH=$(ProjectDir)..\..\..\..\..\static\bin\ReleaseDLL set TREE_ROOT=$(ProjectDir)..\..\..\..\..\..\.. set PTB_PLATFORM=$(PlatformName) set BUILD_TREE_ROOT=$(ProjectDir)..\..\..\..\..\..\vs2013 call "%BUILD_TREE_ROOT%\datatool.bat" -oex "" -pch ncbi_pch.hpp -m "%(FullPath)" -oA -oc "%(Filename)" -od "%(RootDir)%(Directory)%(Filename).def" -odi -ocvs -or build-system\project_tree_builder\msbuild\ -oR ..\..\..\..\..\..\..\ if errorlevel 1 exit 1 + %(RootDir)%(Directory)%(Filename).def; + %(RootDir)%(Directory)%(Filename).files;%(RootDir)%(Directory)%(Filename)__.cpp;%(RootDir)%(Directory)%(Filename)___.cpp + Using datatool to create a C++ object from ASN/DTD/Schema %(FullPath) + set DATATOOL_PATH=$(ProjectDir)..\..\..\..\..\static\bin\ReleaseDLL set TREE_ROOT=$(ProjectDir)..\..\..\..\..\..\.. set PTB_PLATFORM=$(PlatformName) set BUILD_TREE_ROOT=$(ProjectDir)..\..\..\..\..\..\vs2013 call "%BUILD_TREE_ROOT%\datatool.bat" -oex "" -pch ncbi_pch.hpp -m "%(FullPath)" -oA -oc "%(Filename)" -od "%(RootDir)%(Directory)%(Filename).def" -odi -ocvs -or build-system\project_tree_builder\msbuild\ -oR ..\..\..\..\..\..\..\ if errorlevel 1 exit 1 + %(RootDir)%(Directory)%(Filename).def; + %(RootDir)%(Directory)%(Filename).files;%(RootDir)%(Directory)%(Filename)__.cpp;%(RootDir)%(Directory)%(Filename)___.cpp + + + + + diff --git a/c++/compilers/vs2015/static/build/build-system/project_tree_builder/project_tree_builder.exe.vcxproj b/c++/compilers/vs2015/static/build/build-system/project_tree_builder/project_tree_builder.exe.vcxproj new file mode 100644 index 00000000..cc11884e --- /dev/null +++ b/c++/compilers/vs2015/static/build/build-system/project_tree_builder/project_tree_builder.exe.vcxproj @@ -0,0 +1,415 @@ + + + + + ReleaseDLL + Win32 + + + ReleaseDLL + x64 + + + + {8D5B9C1E-5941-44F8-B017-25F6201E822B} + Win32Proj + + + + Application + MultiByte + v140 + + + Application + MultiByte + v140 + + + + + + + + + + + + + ..\..\..\bin\$(Configuration)\ + $(Configuration)\ + false + ..\..\..\bin\$(Configuration)\ + $(Configuration)\ + false + project_tree_builder + project_tree_builder + + + + %40echo EXPENDABLE project + + + + %(AdditionalOptions) + MaxSpeed + OnlyExplicitInline + Speed + true + ..\..\..\..\..\..\include\;%(AdditionalIncludeDirectories) + NDEBUG;WIN32;_CONSOLE;_SECURE_SCL=0;_CRT_SECURE_NO_DEPRECATE=1;%(PreprocessorDefinitions) + false + false + false + Default + MultiThreadedDLL + $(IntDir)project_tree_builder.pdb + Default + true + true + true + + + + + Level3 + + + Cdecl + Default + %(DisableSpecificWarnings) + %(UndefinePreprocessorDefinitions) + + + %(AdditionalOptions) + NDEBUG;%(PreprocessorDefinitions) + ..\..\..\..\..\..\include\;%(AdditionalIncludeDirectories) + + + ws2_32.lib dbghelp.lib %(AdditionalOptions) + $(OutDir)$(TargetName)$(TargetExt) + %(AdditionalLibraryDirectories) + false + FALSE;%(IgnoreSpecificDefaultLibraries) + false + $(OutDir)project_tree_builder.pdb + Console + true + true + $(OutDir)project_tree_builder.lib + MachineX86 + + + + + %40echo EXPENDABLE project + + + + X64 + + + %(AdditionalOptions) + MaxSpeed + OnlyExplicitInline + Speed + true + ..\..\..\..\..\..\include\;%(AdditionalIncludeDirectories) + NDEBUG;WIN32;_CONSOLE;_SECURE_SCL=0;_CRT_SECURE_NO_DEPRECATE=1;%(PreprocessorDefinitions) + false + false + false + Default + MultiThreadedDLL + $(IntDir)project_tree_builder.pdb + Default + true + true + true + + + + + Level3 + + + Cdecl + Default + %(DisableSpecificWarnings) + %(UndefinePreprocessorDefinitions) + + + %(AdditionalOptions) + NDEBUG;%(PreprocessorDefinitions) + ..\..\..\..\..\..\include\;%(AdditionalIncludeDirectories) + + + ws2_32.lib dbghelp.lib %(AdditionalOptions) + $(OutDir)$(TargetName)$(TargetExt) + %(AdditionalLibraryDirectories) + false + FALSE;%(IgnoreSpecificDefaultLibraries) + false + $(OutDir)project_tree_builder.pdb + Console + true + true + $(OutDir)project_tree_builder.lib + MachineX64 + + + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + Create + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + Create + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Document +Using datatool to create a C++ object from ASN/DTD/Schema %(FullPath) +set DATATOOL_PATH=$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL set TREE_ROOT=$(ProjectDir)..\..\..\..\..\.. set PTB_PLATFORM=$(PlatformName) set BUILD_TREE_ROOT=$(ProjectDir)..\..\..\..\..\vs2013 call "%BUILD_TREE_ROOT%\datatool.bat" -oex "" -pch ncbi_pch.hpp -m "%(FullPath)" -oA -oc "%(Filename)" -od "%(RootDir)%(Directory)%(Filename).def" -odi -ocvs -or build-system\project_tree_builder\ -oR ..\..\..\..\..\..\ if errorlevel 1 exit 1 +%(RootDir)%(Directory)%(Filename).def; +%(RootDir)%(Directory)%(Filename).files;%(RootDir)%(Directory)%(Filename)__.cpp;%(RootDir)%(Directory)%(Filename)___.cpp + +Document +Using datatool to create a C++ object from ASN/DTD/Schema %(FullPath) +set DATATOOL_PATH=$(ProjectDir)..\..\..\..\static\bin\ReleaseDLL set TREE_ROOT=$(ProjectDir)..\..\..\..\..\.. set PTB_PLATFORM=$(PlatformName) set BUILD_TREE_ROOT=$(ProjectDir)..\..\..\..\..\vs2013 call "%BUILD_TREE_ROOT%\datatool.bat" -oex "" -pch ncbi_pch.hpp -m "%(FullPath)" -oA -oc "%(Filename)" -od "%(RootDir)%(Directory)%(Filename).def" -odi -ocvs -or build-system\project_tree_builder\ -oR ..\..\..\..\..\..\ if errorlevel 1 exit 1 +%(RootDir)%(Directory)%(Filename).def; +%(RootDir)%(Directory)%(Filename).files;%(RootDir)%(Directory)%(Filename)__.cpp;%(RootDir)%(Directory)%(Filename)___.cpp + + + + + {1edb6a26-adb9-4591-b907-505e8d1a8157} + + + {1f5bcb57-26a5-46c7-b87c-fa74072cf5f6} + + + {dfde1494-ed69-4c4f-84d3-0d19db1b424c} + + + {e46c5b0b-675c-4c37-b618-02608c379c67} + + + {1dce18cd-4a7e-43b8-b7af-48972efe51e7} + + + {FCA4C590-AB16-40F4-8C05-C41EF2A0F2FB} + + + + + + \ No newline at end of file diff --git a/c++/compilers/vs2015/static/build/corelib/xncbi.lib.vcxproj b/c++/compilers/vs2015/static/build/corelib/xncbi.lib.vcxproj new file mode 100644 index 00000000..b6b136e2 --- /dev/null +++ b/c++/compilers/vs2015/static/build/corelib/xncbi.lib.vcxproj @@ -0,0 +1,509 @@ + + + + + ReleaseDLL + Win32 + + + ReleaseDLL + x64 + + + + {1EDB6A26-ADB9-4591-B907-505E8D1A8157} + Win32Proj + + + + StaticLibrary + MultiByte + v140 + + + StaticLibrary + MultiByte + v140 + + + + + + + + + + + + + ..\..\lib\$(Configuration)\ + $(Configuration)\ + ..\..\lib\$(Configuration)\ + $(Configuration)\ + xncbi + xncbi + + + + %(AdditionalOptions) + MaxSpeed + OnlyExplicitInline + Speed + true + ..\..\..\..\..\include\;%(AdditionalIncludeDirectories) + NDEBUG;WIN32;_LIB;_SECURE_SCL=0;_CRT_SECURE_NO_DEPRECATE=1;%(PreprocessorDefinitions) + false + false + false + Default + MultiThreadedDLL + $(IntDir)xncbi.pdb + Default + true + true + true + + + + + Level3 + + + Cdecl + Default + %(DisableSpecificWarnings) + %(UndefinePreprocessorDefinitions) + + + %(AdditionalOptions) + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + + + %(AdditionalOptions) + $(OutDir)$(TargetName)$(TargetExt) + %(AdditionalLibraryDirectories) + false + FALSE;%(IgnoreSpecificDefaultLibraries) + + + + + X64 + + + %(AdditionalOptions) + MaxSpeed + OnlyExplicitInline + Speed + true + ..\..\..\..\..\include\;%(AdditionalIncludeDirectories) + NDEBUG;WIN32;_LIB;_SECURE_SCL=0;_CRT_SECURE_NO_DEPRECATE=1;%(PreprocessorDefinitions) + false + false + false + Default + MultiThreadedDLL + $(IntDir)xncbi.pdb + Default + true + true + true + + + + + Level3 + + + Cdecl + Default + %(DisableSpecificWarnings) + %(UndefinePreprocessorDefinitions) + + + %(AdditionalOptions) + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + + + %(AdditionalOptions) + $(OutDir)$(TargetName)$(TargetExt) + %(AdditionalLibraryDirectories) + false + FALSE;%(IgnoreSpecificDefaultLibraries) + + + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + Create + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + Create + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + + + Document + CompileAsC + CompileAsC + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/c++/compilers/vs2015/static/build/gui/UtilityProjects/_CONFIGURE_.vcxproj b/c++/compilers/vs2015/static/build/gui/UtilityProjects/_CONFIGURE_.vcxproj new file mode 100644 index 00000000..8be3ea29 --- /dev/null +++ b/c++/compilers/vs2015/static/build/gui/UtilityProjects/_CONFIGURE_.vcxproj @@ -0,0 +1,144 @@ + + + + + DebugDLL + Win32 + + + DebugDLL + x64 + + + ReleaseDLL + Win32 + + + ReleaseDLL + x64 + + + + _CONFIGURE_ + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA7E} + MasterProject + ManagedCProj + + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_ + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_ + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_ + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_ + + + + X64 + + + + + X64 + + + + + Document + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_gui.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_gui.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_gui.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_gui.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + + + + + + \ No newline at end of file diff --git a/c++/compilers/vs2015/static/build/gui/UtilityProjects/_CONFIGURE_DIALOG_.vcxproj b/c++/compilers/vs2015/static/build/gui/UtilityProjects/_CONFIGURE_DIALOG_.vcxproj new file mode 100644 index 00000000..5c3eb4e9 --- /dev/null +++ b/c++/compilers/vs2015/static/build/gui/UtilityProjects/_CONFIGURE_DIALOG_.vcxproj @@ -0,0 +1,144 @@ + + + + + DebugDLL + Win32 + + + DebugDLL + x64 + + + ReleaseDLL + Win32 + + + ReleaseDLL + x64 + + + + _CONFIGURE_DIALOG_ + {FDC9447A-C7F1-492D-B84F-D54A1E610F16} + MasterProject + ManagedCProj + + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_DIALOG_ + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_DIALOG_ + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_DIALOG_ + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_DIALOG_ + + + + X64 + + + + + X64 + + + + + Document + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_gui.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_gui.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_gui.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_gui.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + + + + + + \ No newline at end of file diff --git a/c++/compilers/vs2015/static/build/gui/UtilityProjects/configure._ b/c++/compilers/vs2015/static/build/gui/UtilityProjects/configure._ new file mode 100644 index 00000000..3589c553 --- /dev/null +++ b/c++/compilers/vs2015/static/build/gui/UtilityProjects/configure._ @@ -0,0 +1,4 @@ +set PTB_FLAGS= +set PTB_PROJECT_REQ=scripts\projects\ncbi_gui.lst +call "%BUILD_TREE_ROOT%\ptb.bat" +if errorlevel 1 exit 1 diff --git a/c++/compilers/vs2015/static/build/gui/UtilityProjects/configure_dialog._ b/c++/compilers/vs2015/static/build/gui/UtilityProjects/configure_dialog._ new file mode 100644 index 00000000..4907743b --- /dev/null +++ b/c++/compilers/vs2015/static/build/gui/UtilityProjects/configure_dialog._ @@ -0,0 +1,4 @@ +set PTB_FLAGS= -cfg +set PTB_PROJECT_REQ=scripts\projects\ncbi_gui.lst +call "%BUILD_TREE_ROOT%\ptb.bat" +if errorlevel 1 exit 1 diff --git a/c++/compilers/vs2015/static/build/gui/ncbi_gui.sln b/c++/compilers/vs2015/static/build/gui/ncbi_gui.sln new file mode 100644 index 00000000..a4fd1fb2 --- /dev/null +++ b/c++/compilers/vs2015/static/build/gui/ncbi_gui.sln @@ -0,0 +1,35 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_CONFIGURE_DIALOG_", "UtilityProjects\_CONFIGURE_DIALOG_.vcxproj", "{FDC9447A-C7F1-492D-B84F-D54A1E610F16}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_CONFIGURE_", "UtilityProjects\_CONFIGURE_.vcxproj", "{8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA7E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + DebugDLL|x64 = DebugDLL|x64 + DebugDLL|x86 = DebugDLL|x86 + ReleaseDLL|x64 = ReleaseDLL|x64 + ReleaseDLL|x86 = ReleaseDLL|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {FDC9447A-C7F1-492D-B84F-D54A1E610F16}.DebugDLL|x64.ActiveCfg = DebugDLL|x64 + {FDC9447A-C7F1-492D-B84F-D54A1E610F16}.DebugDLL|x64.Build.0 = DebugDLL|x64 + {FDC9447A-C7F1-492D-B84F-D54A1E610F16}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32 + {FDC9447A-C7F1-492D-B84F-D54A1E610F16}.DebugDLL|x86.Build.0 = DebugDLL|Win32 + {FDC9447A-C7F1-492D-B84F-D54A1E610F16}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 + {FDC9447A-C7F1-492D-B84F-D54A1E610F16}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + {FDC9447A-C7F1-492D-B84F-D54A1E610F16}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32 + {FDC9447A-C7F1-492D-B84F-D54A1E610F16}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA7E}.DebugDLL|x64.ActiveCfg = DebugDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA7E}.DebugDLL|x64.Build.0 = DebugDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA7E}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA7E}.DebugDLL|x86.Build.0 = DebugDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA7E}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA7E}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA7E}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAAA7E}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/c++/compilers/vs2015/static/build/ncbi_cpp.sln b/c++/compilers/vs2015/static/build/ncbi_cpp.sln new file mode 100644 index 00000000..1b1eaec8 --- /dev/null +++ b/c++/compilers/vs2015/static/build/ncbi_cpp.sln @@ -0,0 +1,35 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_CONFIGURE_DIALOG_", "UtilityProjects\_CONFIGURE_DIALOG_.vcxproj", "{E7DBEF6D-5DA9-4B0D-9375-C3F26659827B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_CONFIGURE_", "UtilityProjects\_CONFIGURE_.vcxproj", "{8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA105}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + DebugDLL|x64 = DebugDLL|x64 + DebugDLL|x86 = DebugDLL|x86 + ReleaseDLL|x64 = ReleaseDLL|x64 + ReleaseDLL|x86 = ReleaseDLL|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E7DBEF6D-5DA9-4B0D-9375-C3F26659827B}.DebugDLL|x64.ActiveCfg = DebugDLL|x64 + {E7DBEF6D-5DA9-4B0D-9375-C3F26659827B}.DebugDLL|x64.Build.0 = DebugDLL|x64 + {E7DBEF6D-5DA9-4B0D-9375-C3F26659827B}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32 + {E7DBEF6D-5DA9-4B0D-9375-C3F26659827B}.DebugDLL|x86.Build.0 = DebugDLL|Win32 + {E7DBEF6D-5DA9-4B0D-9375-C3F26659827B}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 + {E7DBEF6D-5DA9-4B0D-9375-C3F26659827B}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + {E7DBEF6D-5DA9-4B0D-9375-C3F26659827B}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32 + {E7DBEF6D-5DA9-4B0D-9375-C3F26659827B}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA105}.DebugDLL|x64.ActiveCfg = DebugDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA105}.DebugDLL|x64.Build.0 = DebugDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA105}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA105}.DebugDLL|x86.Build.0 = DebugDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA105}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA105}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA105}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA105}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/c++/compilers/vs2015/static/build/serial/datatool/datatool.exe.vcxproj b/c++/compilers/vs2015/static/build/serial/datatool/datatool.exe.vcxproj new file mode 100644 index 00000000..e1a2ba83 --- /dev/null +++ b/c++/compilers/vs2015/static/build/serial/datatool/datatool.exe.vcxproj @@ -0,0 +1,506 @@ + + + + + ReleaseDLL + Win32 + + + ReleaseDLL + x64 + + + + {BB57FAAE-2EFE-46A0-8157-8879C5AC76C9} + Win32Proj + + + + Application + MultiByte + v140 + + + Application + MultiByte + v140 + + + + + + + + + + + + + ..\..\..\bin\$(Configuration)\ + $(Configuration)\ + false + ..\..\..\bin\$(Configuration)\ + $(Configuration)\ + false + datatool + datatool + + + + + + + + %(AdditionalOptions) + MaxSpeed + OnlyExplicitInline + Speed + true + ..\..\..\..\..\..\include\;%(AdditionalIncludeDirectories) + NDEBUG;WIN32;_CONSOLE;_SECURE_SCL=0;_CRT_SECURE_NO_DEPRECATE=1;%(PreprocessorDefinitions) + false + false + false + Default + MultiThreadedDLL + $(IntDir)datatool.pdb + Default + true + true + true + + + + + Level3 + + + Cdecl + Default + %(DisableSpecificWarnings) + %(UndefinePreprocessorDefinitions) + + + %(AdditionalOptions) + NDEBUG;%(PreprocessorDefinitions) + ..\..\..\..\..\..\include\;%(AdditionalIncludeDirectories) + + + ws2_32.lib dbghelp.lib %(AdditionalOptions) + $(OutDir)$(TargetName)$(TargetExt) + %(AdditionalLibraryDirectories) + false + FALSE;%(IgnoreSpecificDefaultLibraries) + false + $(OutDir)datatool.pdb + Console + true + true + $(OutDir)datatool.lib + MachineX86 + + + + + + + + + X64 + + + %(AdditionalOptions) + MaxSpeed + OnlyExplicitInline + Speed + true + ..\..\..\..\..\..\include\;%(AdditionalIncludeDirectories) + NDEBUG;WIN32;_CONSOLE;_SECURE_SCL=0;_CRT_SECURE_NO_DEPRECATE=1;%(PreprocessorDefinitions) + false + false + false + Default + MultiThreadedDLL + $(IntDir)datatool.pdb + Default + true + true + true + + + + + Level3 + + + Cdecl + Default + %(DisableSpecificWarnings) + %(UndefinePreprocessorDefinitions) + + + %(AdditionalOptions) + NDEBUG;%(PreprocessorDefinitions) + ..\..\..\..\..\..\include\;%(AdditionalIncludeDirectories) + + + ws2_32.lib dbghelp.lib %(AdditionalOptions) + $(OutDir)$(TargetName)$(TargetExt) + %(AdditionalLibraryDirectories) + false + FALSE;%(IgnoreSpecificDefaultLibraries) + false + $(OutDir)datatool.pdb + Console + true + true + $(OutDir)datatool.lib + MachineX64 + + + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + Create + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + Create + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {1edb6a26-adb9-4591-b907-505e8d1a8157} + + + {1dce18cd-4a7e-43b8-b7af-48972efe51e7} + + + {1f5bcb57-26a5-46c7-b87c-fa74072cf5f6} + + + + + + \ No newline at end of file diff --git a/c++/compilers/vs2015/static/build/serial/xser.lib.vcxproj b/c++/compilers/vs2015/static/build/serial/xser.lib.vcxproj new file mode 100644 index 00000000..032a875d --- /dev/null +++ b/c++/compilers/vs2015/static/build/serial/xser.lib.vcxproj @@ -0,0 +1,533 @@ + + + + + ReleaseDLL + Win32 + + + ReleaseDLL + x64 + + + + {1F5BCB57-26A5-46C7-B87C-FA74072CF5F6} + Win32Proj + + + + StaticLibrary + MultiByte + v140 + + + StaticLibrary + MultiByte + v140 + + + + + + + + + + + + + ..\..\lib\$(Configuration)\ + $(Configuration)\ + ..\..\lib\$(Configuration)\ + $(Configuration)\ + xser + xser + + + + + + + + %(AdditionalOptions) + MaxSpeed + OnlyExplicitInline + Speed + true + ..\..\..\..\..\include\;%(AdditionalIncludeDirectories) + NDEBUG;WIN32;_LIB;_SECURE_SCL=0;_CRT_SECURE_NO_DEPRECATE=1;%(PreprocessorDefinitions) + false + false + false + Default + MultiThreadedDLL + $(IntDir)xser.pdb + Default + true + true + true + + + + + Level3 + + + Cdecl + Default + %(DisableSpecificWarnings) + %(UndefinePreprocessorDefinitions) + + + %(AdditionalOptions) + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + + + %(AdditionalOptions) + $(OutDir)$(TargetName)$(TargetExt) + %(AdditionalLibraryDirectories) + false + FALSE;%(IgnoreSpecificDefaultLibraries) + + + + + + + + + X64 + + + %(AdditionalOptions) + MaxSpeed + OnlyExplicitInline + Speed + true + ..\..\..\..\..\include\;%(AdditionalIncludeDirectories) + NDEBUG;WIN32;_LIB;_SECURE_SCL=0;_CRT_SECURE_NO_DEPRECATE=1;%(PreprocessorDefinitions) + false + false + false + Default + MultiThreadedDLL + $(IntDir)xser.pdb + Default + true + true + true + + + + + Level3 + + + Cdecl + Default + %(DisableSpecificWarnings) + %(UndefinePreprocessorDefinitions) + + + %(AdditionalOptions) + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + + + %(AdditionalOptions) + $(OutDir)$(TargetName)$(TargetExt) + %(AdditionalLibraryDirectories) + false + FALSE;%(IgnoreSpecificDefaultLibraries) + + + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + Create + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + Create + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/c++/compilers/vs2015/static/build/util/regexp/regexp.lib.vcxproj b/c++/compilers/vs2015/static/build/util/regexp/regexp.lib.vcxproj new file mode 100644 index 00000000..64e7191a --- /dev/null +++ b/c++/compilers/vs2015/static/build/util/regexp/regexp.lib.vcxproj @@ -0,0 +1,363 @@ + + + + + ReleaseDLL + Win32 + + + ReleaseDLL + x64 + + + + Win32Proj + {DFDE1494-ED69-4C4F-84D3-0D19DB1B424C} + + + + StaticLibrary + MultiByte + v140 + + + StaticLibrary + MultiByte + v140 + + + + + + + + + + + + + ..\..\..\lib\$(Configuration)\ + $(Configuration)\ + ..\..\..\lib\$(Configuration)\ + $(Configuration)\ + regexp + regexp + + + + MaxSpeed + NDEBUG;WIN32;_LIB;_SECURE_SCL=0;_CRT_SECURE_NO_DEPRECATE=1;HAVE_CONFIG_H;%(PreprocessorDefinitions) + ..\..\..\..\..\..\include\; ..\..\..\..\..\..\include\internal\; ..\..\..\..\..\..\include\util\regexp\;%(AdditionalIncludeDirectories) + Default + MultiThreadedDLL + true + $(IntDir)regexp.pdb + Level3 + + + Default + + + + + false + AnySuitable + true + false + true + %(AdditionalOptions) + Default + Cdecl + false + true + %(DisableSpecificWarnings) + %(UndefinePreprocessorDefinitions) + Speed + + + $(OutDir)$(TargetName)$(TargetExt) + %(AdditionalLibraryDirectories) + %(AdditionalOptions) + false + FALSE;%(IgnoreSpecificDefaultLibraries) + + + + + + + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + %(AdditionalOptions) + + + + + MaxSpeed + NDEBUG;WIN32;_LIB;_SECURE_SCL=0;_CRT_SECURE_NO_DEPRECATE=1;HAVE_CONFIG_H;%(PreprocessorDefinitions) + ..\..\..\..\..\..\include\; ..\..\..\..\..\..\include\internal\; ..\..\..\..\..\..\include\util\regexp\;%(AdditionalIncludeDirectories) + Default + MultiThreadedDLL + true + $(IntDir)regexp.pdb + Level3 + + + Default + + + + + false + AnySuitable + true + false + true + %(AdditionalOptions) + Default + Cdecl + false + true + %(DisableSpecificWarnings) + %(UndefinePreprocessorDefinitions) + Speed + + + $(OutDir)$(TargetName)$(TargetExt) + %(AdditionalLibraryDirectories) + %(AdditionalOptions) + false + FALSE;%(IgnoreSpecificDefaultLibraries) + + + + + + + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + %(AdditionalOptions) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/c++/compilers/vs2015/static/build/util/xregexp/xregexp.lib.vcxproj b/c++/compilers/vs2015/static/build/util/xregexp/xregexp.lib.vcxproj new file mode 100644 index 00000000..f8bcb98d --- /dev/null +++ b/c++/compilers/vs2015/static/build/util/xregexp/xregexp.lib.vcxproj @@ -0,0 +1,176 @@ + + + + + ReleaseDLL + Win32 + + + ReleaseDLL + x64 + + + + Win32Proj + {E46C5B0B-675C-4C37-B618-02608C379C67} + + + + StaticLibrary + MultiByte + v140 + + + StaticLibrary + MultiByte + v140 + + + + + + + + + + + + + ..\..\..\lib\$(Configuration)\ + $(Configuration)\ + ..\..\..\lib\$(Configuration)\ + $(Configuration)\ + xregexp + xregexp + + + + MaxSpeed + NDEBUG;WIN32;_LIB;_SECURE_SCL=0;_CRT_SECURE_NO_DEPRECATE=1;%(PreprocessorDefinitions) + ..\..\..\..\..\..\include\; ..\..\..\..\..\..\include\internal\; ..\..\..\..\..\..\include\util\regexp\;%(AdditionalIncludeDirectories) + Default + MultiThreadedDLL + true + $(IntDir)xregexp.pdb + Level3 + + + Default + + + + + false + AnySuitable + true + false + true + %(AdditionalOptions) + Default + Cdecl + false + true + %(DisableSpecificWarnings) + %(UndefinePreprocessorDefinitions) + Speed + + + $(OutDir)$(TargetName)$(TargetExt) + %(AdditionalLibraryDirectories) + %(AdditionalOptions) + false + FALSE;%(IgnoreSpecificDefaultLibraries) + + + + + + + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + %(AdditionalOptions) + + + + + MaxSpeed + NDEBUG;WIN32;_LIB;_SECURE_SCL=0;_CRT_SECURE_NO_DEPRECATE=1;%(PreprocessorDefinitions) + ..\..\..\..\..\..\include\; ..\..\..\..\..\..\include\internal\; ..\..\..\..\..\..\include\util\regexp\;%(AdditionalIncludeDirectories) + Default + MultiThreadedDLL + true + $(IntDir)xregexp.pdb + Level3 + + + Default + + + + + false + AnySuitable + true + false + true + %(AdditionalOptions) + Default + Cdecl + false + true + %(DisableSpecificWarnings) + %(UndefinePreprocessorDefinitions) + Speed + + + $(OutDir)$(TargetName)$(TargetExt) + %(AdditionalLibraryDirectories) + %(AdditionalOptions) + false + FALSE;%(IgnoreSpecificDefaultLibraries) + + + + + + + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + %(AdditionalOptions) + + + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + Create + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + Create + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + Use + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + Use + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + Use + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + Use + ncbi_pch.hpp + + + + + + + + + + + \ No newline at end of file diff --git a/c++/compilers/vs2015/static/build/util/xutil.lib.vcxproj b/c++/compilers/vs2015/static/build/util/xutil.lib.vcxproj new file mode 100644 index 00000000..2d7988dd --- /dev/null +++ b/c++/compilers/vs2015/static/build/util/xutil.lib.vcxproj @@ -0,0 +1,308 @@ + + + + + ReleaseDLL + Win32 + + + ReleaseDLL + x64 + + + + {1DCE18CD-4A7E-43B8-B7AF-48972EFE51E7} + Win32Proj + + + + StaticLibrary + MultiByte + v140 + + + StaticLibrary + MultiByte + v140 + + + + + + + + + + + + + ..\..\lib\$(Configuration)\ + $(Configuration)\ + ..\..\lib\$(Configuration)\ + $(Configuration)\ + xutil + xutil + + + + + + + + %(AdditionalOptions) + MaxSpeed + OnlyExplicitInline + Speed + true + ..\..\..\..\..\include\;%(AdditionalIncludeDirectories) + NDEBUG;WIN32;_LIB;_SECURE_SCL=0;_CRT_SECURE_NO_DEPRECATE=1;%(PreprocessorDefinitions) + false + false + false + Default + MultiThreadedDLL + $(IntDir)xutil.pdb + Default + true + true + true + + + + + Level3 + + + Cdecl + Default + %(DisableSpecificWarnings) + %(UndefinePreprocessorDefinitions) + + + %(AdditionalOptions) + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + + + %(AdditionalOptions) + $(OutDir)$(TargetName)$(TargetExt) + %(AdditionalLibraryDirectories) + false + FALSE;%(IgnoreSpecificDefaultLibraries) + + + + + + + + + X64 + + + %(AdditionalOptions) + MaxSpeed + OnlyExplicitInline + Speed + true + ..\..\..\..\..\include\;%(AdditionalIncludeDirectories) + NDEBUG;WIN32;_LIB;_SECURE_SCL=0;_CRT_SECURE_NO_DEPRECATE=1;%(PreprocessorDefinitions) + false + false + false + Default + MultiThreadedDLL + $(IntDir)xutil.pdb + Default + true + true + true + + + + + Level3 + + + Cdecl + Default + %(DisableSpecificWarnings) + %(UndefinePreprocessorDefinitions) + + + %(AdditionalOptions) + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + + + %(AdditionalOptions) + $(OutDir)$(TargetName)$(TargetExt) + %(AdditionalLibraryDirectories) + false + FALSE;%(IgnoreSpecificDefaultLibraries) + + + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + Create + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + Create + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + NCBI_USE_PCH;%(PreprocessorDefinitions) + ncbi_pch.hpp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/c++/compilers/vs2015/static/third_party_msvcstatic_install.vcxproj b/c++/compilers/vs2015/static/third_party_msvcstatic_install.vcxproj new file mode 100644 index 00000000..a97d32cf --- /dev/null +++ b/c++/compilers/vs2015/static/third_party_msvcstatic_install.vcxproj @@ -0,0 +1,433 @@ + + + + + DebugDLL + Win32 + + + DebugDLL + x64 + + + DebugMT + Win32 + + + DebugMT + x64 + + + ReleaseDLL + Win32 + + + ReleaseDLL + x64 + + + ReleaseMT + Win32 + + + ReleaseMT + x64 + + + VTune_DebugDLL + Win32 + + + VTune_DebugDLL + x64 + + + VTune_DebugMT + Win32 + + + VTune_DebugMT + x64 + + + VTune_ReleaseDLL + Win32 + + + VTune_ReleaseDLL + x64 + + + VTune_ReleaseMT + Win32 + + + VTune_ReleaseMT + x64 + + + Unicode_DebugDLL + Win32 + + + Unicode_DebugDLL + x64 + + + Unicode_DebugMT + Win32 + + + Unicode_DebugMT + x64 + + + Unicode_ReleaseDLL + Win32 + + + Unicode_ReleaseDLL + x64 + + + Unicode_ReleaseMT + Win32 + + + Unicode_ReleaseMT + x64 + + + + {9E4B5381-9B6C-4867-BF8A-F1AAA1FD581E} + MakeFileProj + + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015" + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015.64" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015.64" + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015" + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015.64" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015.64" + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015" + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015.64" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015.64" + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015" + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015.64" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015.64" + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015" + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015.64" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015.64" + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015" + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015.64" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015.64" + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015" + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015.64" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015.64" + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015" + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015.64" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015.64" + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015" + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015.64" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015.64" + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015" + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015.64" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015.64" + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015" + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015.64" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015.64" + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015" + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015" + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_install IntDir=$(IntDir) MSVC_SRC="vs2015.64" + nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_rebuild IntDir=$(IntDir) MSVC_SRC="vs2015.64" + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" msvc_clean IntDir=$(IntDir) MSVC_SRC="vs2015.64" + dlls-install.exe + + + + + + + + + + diff --git a/c++/compilers/vs2015/static/third_party_static_install.mak b/c++/compilers/vs2015/static/third_party_static_install.mak new file mode 100644 index 00000000..9405bdc8 --- /dev/null +++ b/c++/compilers/vs2015/static/third_party_static_install.mak @@ -0,0 +1,62 @@ +# $Id: third_party_static_install.mak 493015 2016-02-23 18:12:07Z gouriano $ +################################################################# + + +INSTALL = .\bin +INSTALL_BINPATH = $(INSTALL)\$(INTDIR) +THIRDPARTY_MAKEFILES_DIR = . + + +META_MAKE = $(THIRDPARTY_MAKEFILES_DIR)\..\third_party_install.meta.mk +!IF EXIST($(META_MAKE)) +!INCLUDE $(META_MAKE) +!ELSE +!ERROR $(META_MAKE) not found +!ENDIF + +THIRD_PARTY_LIBS = \ + install_berkeleydb \ + install_gnutls \ + install_glew \ + install_lzo \ + install_mssql \ + install_mysql \ + install_openssl \ + install_sqlite \ + install_sqlite3 \ + install_sybase \ + install_wxwidgets \ + install_wxwindows \ + install_xalan \ + install_xerces \ + install_libxml \ + install_libxslt \ + install_vdb + +CLEAN_THIRD_PARTY_LIBS = \ + clean_berkeleydb \ + clean_gnutls \ + clean_glew \ + clean_lzo \ + clean_mssql \ + clean_mysql \ + clean_openssl \ + clean_sqlite \ + clean_sqlite3 \ + clean_sybase \ + clean_wxwidgets \ + clean_wxwindows \ + clean_xalan \ + clean_xerces \ + clean_libxml \ + clean_libxslt \ + clean_vdb + +all : dirs $(THIRD_PARTY_LIBS) + +clean : $(CLEAN_THIRD_PARTY_LIBS) + +rebuild : clean all + +dirs : + @if not exist $(INSTALL_BINPATH) (echo Creating directory $(INSTALL_BINPATH)... & mkdir $(INSTALL_BINPATH)) diff --git a/c++/compilers/vs2015/static/third_party_static_install.vcxproj b/c++/compilers/vs2015/static/third_party_static_install.vcxproj new file mode 100644 index 00000000..ce23796a --- /dev/null +++ b/c++/compilers/vs2015/static/third_party_static_install.vcxproj @@ -0,0 +1,433 @@ + + + + + DebugDLL + Win32 + + + DebugDLL + x64 + + + DebugMT + Win32 + + + DebugMT + x64 + + + ReleaseDLL + Win32 + + + ReleaseDLL + x64 + + + ReleaseMT + Win32 + + + ReleaseMT + x64 + + + Unicode_DebugDLL + Win32 + + + Unicode_DebugDLL + x64 + + + Unicode_DebugMT + Win32 + + + Unicode_DebugMT + x64 + + + Unicode_ReleaseDLL + Win32 + + + Unicode_ReleaseDLL + x64 + + + Unicode_ReleaseMT + Win32 + + + Unicode_ReleaseMT + x64 + + + VTune_DebugDLL + Win32 + + + VTune_DebugDLL + x64 + + + VTune_DebugMT + Win32 + + + VTune_DebugMT + x64 + + + VTune_ReleaseDLL + Win32 + + + VTune_ReleaseDLL + x64 + + + VTune_ReleaseMT + Win32 + + + VTune_ReleaseMT + x64 + + + + {9E4B5381-9B6C-4867-BF8A-F1AAA1FD580E} + MakeFileProj + + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + Makefile + v140 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_static_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" clean IntDir=$(IntDir) + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_static_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" clean IntDir=$(IntDir) + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_static_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" clean IntDir=$(IntDir) + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_static_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" clean IntDir=$(IntDir) + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_static_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" clean IntDir=$(IntDir) + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_static_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" clean IntDir=$(IntDir) + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_static_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" clean IntDir=$(IntDir) + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_static_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" clean IntDir=$(IntDir) + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_static_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" clean IntDir=$(IntDir) + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_static_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" clean IntDir=$(IntDir) + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_static_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" clean IntDir=$(IntDir) + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_static_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" clean IntDir=$(IntDir) + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_static_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" clean IntDir=$(IntDir) + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_static_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" clean IntDir=$(IntDir) + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_static_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" clean IntDir=$(IntDir) + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_static_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" clean IntDir=$(IntDir) + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_static_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" clean IntDir=$(IntDir) + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_static_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" clean IntDir=$(IntDir) + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_static_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" clean IntDir=$(IntDir) + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_static_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" clean IntDir=$(IntDir) + gbench-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_static_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" clean IntDir=$(IntDir) + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_static_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" clean IntDir=$(IntDir) + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_static_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" clean IntDir=$(IntDir) + dlls-install.exe + $(Configuration)\ + $(Configuration)\ + nmake -f "$(ProjectDir)\third_party_static_install.mak" all IntDir=$(IntDir) + nmake -f "$(ProjectDir)\third_party_static_install.mak" rebuild IntDir=$(IntDir) + call "$(ProjectDir)..\msvcvars.bat" & nmake -f "$(ProjectDir)\third_party_static_install.mak" clean IntDir=$(IntDir) + dlls-install.exe + + + + + + + + + + diff --git a/c++/compilers/vs2015/third_party_install.meta.mk b/c++/compilers/vs2015/third_party_install.meta.mk new file mode 100644 index 00000000..581fee15 --- /dev/null +++ b/c++/compilers/vs2015/third_party_install.meta.mk @@ -0,0 +1,330 @@ +# $Id: third_party_install.meta.mk 492980 2016-02-23 16:24:57Z gouriano $ + +################################################################# +# +# Third party DLLs installation makefile +# +# Author: Andrei Gourianov +# +################################################################# + + +# Build configuration name +INTDIR = $(INTDIR:.\=) +ALTDIR = $(INTDIR:VTune_=) +!IF ("$(INTDIR)"=="$(ALTDIR)") +ALTDIR = $(INTDIR:Unicode_=) +!ENDIF + +# Extensions of files to copy +EXTENSIONS = dll pdb manifest + +# MSVC DLLs +# MSVC_SRC must be defined elsewhere (eg, in command line) +#MSVCRT_SRC = \\snowman\win-coremake\Lib\ThirdParty\msvc\msvc71\7.1\bin +#MSVCRT_SRC = \\snowman\win-coremake\Lib\ThirdParty\msvc\msvc8\8\bin + +MSVCRT_SRC = \\snowman\win-coremake\Lib\ThirdParty\msvc\$(MSVC_SRC)\bin + + + +################################################################# +# Source folders +# +# x_BINPATH macros are defined in Makefile.third_party.mk +# generated by project_tree_builder +# + +PTB_GENERATED = $(THIRDPARTY_MAKEFILES_DIR)\$(INTDIR)\Makefile.third_party.mk +!IF EXIST($(PTB_GENERATED)) +!INCLUDE $(PTB_GENERATED) +!ELSE +!ERROR $(PTB_GENERATED) not found +!ENDIF + + +BERKELEYDB_SRC = $(BERKELEYDB_BINPATH)\$(INTDIR) +!IF !EXIST($(BERKELEYDB_SRC)) +BERKELEYDB_SRC = $(BERKELEYDB_BINPATH)\$(ALTDIR) +!ENDIF + +GNUTLS_SRC = $(GNUTLS_BINPATH)\$(INTDIR) +!IF !EXIST($(GNUTLS_SRC)) +GNUTLS_SRC = $(GNUTLS_BINPATH)\$(ALTDIR) +!ENDIF + +GLEW_SRC = $(GLEW_BINPATH)\$(INTDIR) +!IF !EXIST($(GLEW_SRC)) +GLEW_SRC = $(GLEW_BINPATH)\$(ALTDIR) +!ENDIF + +LZO_SRC = $(LZO_BINPATH)\$(INTDIR) +!IF !EXIST($(LZO_SRC)) +LZO_SRC = $(LZO_BINPATH)\$(ALTDIR) +!ENDIF + +MSSQL_SRC = $(MSSQL_BINPATH)\$(INTDIR) +!IF !EXIST($(MSSQL_SRC)) +MSSQL_SRC = $(MSSQL_BINPATH)\$(ALTDIR) +!ENDIF + +MYSQL_SRC = $(MYSQL_BINPATH)\$(INTDIR) +!IF !EXIST($(MYSQL_SRC)) +MYSQL_SRC = $(MYSQL_BINPATH)\$(ALTDIR) +!ENDIF + +OPENSSL_SRC = $(OPENSSL_BINPATH)\$(INTDIR) +!IF !EXIST($(OPENSSL_SRC)) +OPENSSL_SRC = $(OPENSSL_BINPATH)\$(ALTDIR) +!ENDIF + +SQLITE_SRC = $(SQLITE_BINPATH)\$(INTDIR) +!IF !EXIST($(SQLITE_SRC)) +SQLITE_SRC = $(SQLITE_BINPATH)\$(ALTDIR) +!ENDIF + +SQLITE3_SRC = $(SQLITE3_BINPATH)\$(INTDIR) +!IF !EXIST($(SQLITE3_SRC)) +SQLITE3_SRC = $(SQLITE3_BINPATH)\$(ALTDIR) +!ENDIF + +# SYBASE_SRC = $(SYBASE_BINPATH)\$(INTDIR) +# !IF !EXIST($(SYBASE_SRC)) +# SYBASE_SRC = $(SYBASE_BINPATH)\$(ALTDIR) +# !ENDIF +SYBASE_SRC = $(SYBASE_BINPATH)\$(INTDIR:Debug=Release) +!IF !EXIST($(SYBASE_SRC)) +SYBASE_SRC = $(SYBASE_BINPATH)\$(ALTDIR:Debug=Release) +!ENDIF + +WXWIDGETS_SRC = $(WXWIDGETS_BINPATH)\$(INTDIR) +!IF !EXIST($(WXWIDGETS_SRC)) +WXWIDGETS_SRC = $(WXWIDGETS_BINPATH)\$(ALTDIR) +!ENDIF + +WXWINDOWS_SRC = $(WXWINDOWS_BINPATH)\$(INTDIR) +!IF !EXIST($(WXWINDOWS_SRC)) +WXWINDOWS_SRC = $(WXWINDOWS_BINPATH)\$(ALTDIR) +!ENDIF + +XALAN_SRC = $(XALAN_BINPATH)\$(INTDIR) +!IF !EXIST($(XALAN_SRC)) +XALAN_SRC = $(XALAN_BINPATH)\$(ALTDIR) +!ENDIF + +XERCES_SRC = $(XERCES_BINPATH)\$(INTDIR) +!IF !EXIST($(XERCES_SRC)) +XERCES_SRC = $(XERCES_BINPATH)\$(ALTDIR) +!ENDIF + +LIBXML_SRC = $(LIBXML_BINPATH)\$(INTDIR) +!IF !EXIST($(LIBXML_SRC)) +LIBXML_SRC = $(LIBXML_BINPATH)\$(ALTDIR) +!ENDIF + +LIBXSLT_SRC = $(LIBXSLT_BINPATH)\$(INTDIR) +!IF !EXIST($(LIBXSLT_SRC)) +LIBXSLT_SRC = $(LIBXSLT_BINPATH)\$(ALTDIR) +!ENDIF + +VDB_SRC = $(VDB_BINPATH) + + + +################################################################# + +INSTALL_CMD = \ + @if exist "$*" ( for %%e in ($(EXTENSIONS)) do @( \ + if exist "$*\*.%%e" ( \ + for /f "delims=" %%i in ('dir /a-d/b "$*\*.%%e"') do @( \ + xcopy /Y /D /F "$*\%%i" "$(INSTALL_BINPATH)" ) \ + )) \ + ) else (echo WARNING: "$*" not found) + +CLEAN_CMD = \ + @if exist "$*" ( for %%e in ($(EXTENSIONS)) do @( \ + if exist "$*\*.%%e" ( \ + for /f "delims=" %%i in ('dir /a-d/b "$*\*.%%e"') do @( \ + if exist "$(INSTALL_BINPATH)\%%i" ( \ + echo $(INSTALL_BINPATH)\%%i & del /F "$(INSTALL_BINPATH)\%%i" )))) \ + ) else (echo WARNING: "$*" not found) + + + +################################################################# +# Targets +# + +$(BERKELEYDB_SRC).berkeleydb_install : + @echo ---- & echo Copying BerkeleyDB DLLs & $(INSTALL_CMD) +$(BERKELEYDB_SRC).berkeleydb_clean : + @echo ---- & echo Deleting BerkeleyDB DLLs & $(CLEAN_CMD) +install_berkeleydb : $(BERKELEYDB_SRC).berkeleydb_install +clean_berkeleydb : $(BERKELEYDB_SRC).berkeleydb_clean + + + +$(GNUTLS_SRC).gnutls_install : + @echo ---- & echo Copying GNUTLS DLLs & $(INSTALL_CMD) +$(GNUTLS_SRC).gnutls_clean : + @echo ---- & echo Deleting GNUTLS DLLs & $(CLEAN_CMD) +install_gnutls : $(GNUTLS_SRC).gnutls_install +clean_gnutls : $(GNUTLS_SRC).gnutls_clean + + + +$(GLEW_SRC).glew_install : + @echo ---- & echo Copying GLEW DLLs & $(INSTALL_CMD) +$(GLEW_SRC).glew_clean : + @echo ---- & echo Deleting GLEW DLLs & $(CLEAN_CMD) +install_glew : $(GLEW_SRC).glew_install +clean_glew : $(GLEW_SRC).glew_clean + + + +$(LZO_SRC).lzo_install : + @echo ---- & echo Copying LZO DLLs & $(INSTALL_CMD) +$(LZO_SRC).lzo_clean : + @echo ---- & echo Deleting LZO DLLs & $(CLEAN_CMD) +install_lzo : $(LZO_SRC).lzo_install +clean_lzo : $(LZO_SRC).lzo_clean + + + +$(MYSQL_SRC).mysql_install : + @echo ---- & echo Copying MySQL DLLs & $(INSTALL_CMD) +$(MYSQL_SRC).mysql_clean : + @echo ---- & echo Deleting MySQL DLLs & $(CLEAN_CMD) +install_mysql : $(MYSQL_SRC).mysql_install +clean_mysql : $(MYSQL_SRC).mysql_clean + + + +$(MSSQL_SRC).mssql_install : + @echo ---- & echo Copying MSSQL DLLs & $(INSTALL_CMD) +$(MSSQL_SRC).mssql_clean : + @echo ---- & echo Deleting MSSQL DLLs & $(CLEAN_CMD) +install_mssql : $(MSSQL_SRC).mssql_install +clean_mssql : $(MSSQL_SRC).mssql_clean + + + +$(OPENSSL_SRC).openssl_install : + @echo ---- & echo Copying OpenSSL DLLs & $(INSTALL_CMD) +$(OPENSSL_SRC).openssl_clean : + @echo ---- & echo Deleting OpenSSL DLLs & $(CLEAN_CMD) +install_openssl : $(OPENSSL_SRC).openssl_install +clean_openssl : $(OPENSSL_SRC).openssl_clean + + + +$(SQLITE_SRC).sqlite_install : + @echo ---- & echo Copying SQLite DLLs & $(INSTALL_CMD) +$(SQLITE_SRC).sqlite_clean : + @echo ---- & echo Deleting SQLite DLLs & $(CLEAN_CMD) +install_sqlite : $(SQLITE_SRC).sqlite_install +clean_sqlite : $(SQLITE_SRC).sqlite_clean + + + +$(SQLITE3_SRC).sqlite3_install : + @echo ---- & echo Copying SQLite3 DLLs & $(INSTALL_CMD) +$(SQLITE3_SRC).sqlite3_clean : + @echo ---- & echo Deleting SQLite3 DLLs & $(CLEAN_CMD) +install_sqlite3 : $(SQLITE3_SRC).sqlite3_install +clean_sqlite3 : $(SQLITE3_SRC).sqlite3_clean + + + +$(SYBASE_SRC).sybase_install : + @echo ---- & echo Copying Sybase DLLs & $(INSTALL_CMD) +$(SYBASE_SRC).sybase_clean : + @echo ---- & echo Deleting Sybase DLLs & $(CLEAN_CMD) +install_sybase : $(SYBASE_SRC).sybase_install +clean_sybase : $(SYBASE_SRC).sybase_clean + + + +$(WXWIDGETS_SRC).wxwidgets_install : + @echo ---- & echo Copying wxWidgets DLLs & $(INSTALL_CMD) +$(WXWIDGETS_SRC).wxwidgets_clean : + @echo ---- & echo Deleting wxWidgets DLLs & $(CLEAN_CMD) +install_wxwidgets : $(WXWIDGETS_SRC).wxwidgets_install +clean_wxwidgets : $(WXWIDGETS_SRC).wxwidgets_clean + + + +$(WXWINDOWS_SRC).wxwindows_install : + @echo ---- & echo Copying wxWindows DLLs & $(INSTALL_CMD) +$(WXWINDOWS_SRC).wxwindows_clean : + @echo ---- & echo Deleting wxWindows DLLs & $(CLEAN_CMD) +install_wxwindows : $(WXWINDOWS_SRC).wxwindows_install +clean_wxwindows : $(WXWINDOWS_SRC).wxwindows_clean + + + +$(XALAN_SRC).xalan_install : + @echo ---- & echo Copying Xalan DLLs & $(INSTALL_CMD) +$(XALAN_SRC).xalan_clean : + @echo ---- & echo Deleting Xalan DLLs & $(CLEAN_CMD) +install_xalan : $(XALAN_SRC).xalan_install +clean_xalan : $(XALAN_SRC).xalan_clean + + + +$(XERCES_SRC).xerces_install : + @echo ---- & echo Copying Xerces DLLs & $(INSTALL_CMD) +$(XERCES_SRC).xerces_clean : + @echo ---- & echo Deleting Xerces DLLs & $(CLEAN_CMD) +install_xerces : $(XERCES_SRC).xerces_install +clean_xerces : $(XERCES_SRC).xerces_clean + + + +$(LIBXML_SRC).libxml_install : + @echo ---- & echo Copying LIBXML DLLs & $(INSTALL_CMD) +$(LIBXML_SRC).libxml_clean : + @echo ---- & echo Deleting LIBXML DLLs & $(CLEAN_CMD) +install_libxml : $(LIBXML_SRC).libxml_install +clean_libxml : $(LIBXML_SRC).libxml_clean + + + +$(LIBXSLT_SRC).libxslt_install : + @echo ---- & echo Copying LIBXSLT DLLs & $(INSTALL_CMD) +$(LIBXSLT_SRC).libxslt_clean : + @echo ---- & echo Deleting LIBXSLT DLLs & $(CLEAN_CMD) +install_libxslt : $(LIBXSLT_SRC).libxslt_install +clean_libxslt : $(LIBXSLT_SRC).libxslt_clean + + +VDB_ORIG = $(INSTALL_BINPATH)\ncbi-vdb-md.dll +VDB_COPY = $(INSTALL_BINPATH)\ncbi-vdb-dll-md.dll +$(VDB_SRC).vdb_install : + @echo ---- & echo Copying VDB DLLs & $(INSTALL_CMD) +# The trailing * suppresses a spurious prompt, per +# http://stackoverflow.com/a/26034267/1231 + @if exist "$(VDB_ORIG)" xcopy /Y /D /F "$(VDB_ORIG)" "$(VDB_COPY)"* +$(VDB_SRC).vdb_clean : + @echo ---- & echo Deleting VDB DLLs & $(CLEAN_CMD) + @if exist "$(VDB_COPY)" ( echo $(VDB_COPY) & del /f "$(VDB_COPY)" ) +install_vdb : $(VDB_SRC).vdb_install +clean_vdb : $(VDB_SRC).vdb_clean + + + +# ----------------------------------------- +# MSVC RT DLLs are not included into 'all' + +msvc_install : dirs $(MSVCRT_SRC).msvc_install + +install_msvc : msvc_install +msvc_clean : $(MSVCRT_SRC).msvc_clean +clean_msvc : msvc_clean +msvc_rebuild : msvc_clean msvc_install + +$(MSVCRT_SRC).msvc_install : + @echo ---- & echo Copying MSVC DLLs & $(INSTALL_CMD) +$(MSVCRT_SRC).msvc_clean : + @echo ---- & echo Deleting MSVC DLLs & $(CLEAN_CMD) + diff --git a/c++/compilers/vs2015/user/build/UtilityProjects/_CONFIGURE_.vcxproj b/c++/compilers/vs2015/user/build/UtilityProjects/_CONFIGURE_.vcxproj new file mode 100644 index 00000000..ff660593 --- /dev/null +++ b/c++/compilers/vs2015/user/build/UtilityProjects/_CONFIGURE_.vcxproj @@ -0,0 +1,144 @@ + + + + + DebugDLL + Win32 + + + DebugDLL + x64 + + + ReleaseDLL + Win32 + + + ReleaseDLL + x64 + + + + _CONFIGURE_ + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA108} + MasterProject + ManagedCProj + + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_ + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_ + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_ + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_ + + + + X64 + + + + + X64 + + + + + Document + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\static\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_user.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\static\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\static\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_user.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\static\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\static\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_user.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\static\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\static\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_user.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\static\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + + + + + + \ No newline at end of file diff --git a/c++/compilers/vs2015/user/build/UtilityProjects/_CONFIGURE_DIALOG_.vcxproj b/c++/compilers/vs2015/user/build/UtilityProjects/_CONFIGURE_DIALOG_.vcxproj new file mode 100644 index 00000000..eca71d33 --- /dev/null +++ b/c++/compilers/vs2015/user/build/UtilityProjects/_CONFIGURE_DIALOG_.vcxproj @@ -0,0 +1,144 @@ + + + + + DebugDLL + Win32 + + + DebugDLL + x64 + + + ReleaseDLL + Win32 + + + ReleaseDLL + x64 + + + + _CONFIGURE_DIALOG_ + {EB043EAF-58D4-4179-AC32-538D9059BB8B} + MasterProject + ManagedCProj + + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_DIALOG_ + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_DIALOG_ + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_DIALOG_ + $(SolutionDir)$(Configuration)\ + $(Configuration)\$(TargetName)\ +_CONFIGURE_DIALOG_ + + + + X64 + + + + + X64 + + + + + Document + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\static\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_user.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\static\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\static\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_user.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\static\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\static\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_user.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\static\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + %(AdditionalInputs) + set PTB_PATH=$(ProjectDir)..\..\..\static\bin\ReleaseDLL +set TREE_ROOT=$(ProjectDir)..\..\..\..\.. +set SLN_PATH=$(ProjectDir)..\ncbi_user.sln +set PTB_PLATFORM=$(Platform) +set BUILD_TREE_ROOT=$(ProjectDir)..\..\.. +copy /Y %(Filename)%(Extension) %(Filename).bat +call %(Filename).bat +if errorlevel 1 exit 1 + + %(FullPath).aanofile.out;$(ProjectDir)..\..\..\static\bin\ReleaseDLL\project_tree_builder.exe;%(Outputs) + Configure solution : $(SolutionName) + + + + + + \ No newline at end of file diff --git a/c++/compilers/vs2015/user/build/UtilityProjects/configure._ b/c++/compilers/vs2015/user/build/UtilityProjects/configure._ new file mode 100644 index 00000000..7766ecce --- /dev/null +++ b/c++/compilers/vs2015/user/build/UtilityProjects/configure._ @@ -0,0 +1,4 @@ +set PTB_FLAGS= +set PTB_PROJECT_REQ=scripts\projects\ncbi_user.lst +call "%BUILD_TREE_ROOT%\ptb.bat" +if errorlevel 1 exit 1 diff --git a/c++/compilers/vs2015/user/build/UtilityProjects/configure_dialog._ b/c++/compilers/vs2015/user/build/UtilityProjects/configure_dialog._ new file mode 100644 index 00000000..a9541633 --- /dev/null +++ b/c++/compilers/vs2015/user/build/UtilityProjects/configure_dialog._ @@ -0,0 +1,4 @@ +set PTB_FLAGS= -cfg +set PTB_PROJECT_REQ=scripts\projects\ncbi_user.lst +call "%BUILD_TREE_ROOT%\ptb.bat" +if errorlevel 1 exit 1 diff --git a/c++/compilers/vs2015/user/build/ncbi_user.sln b/c++/compilers/vs2015/user/build/ncbi_user.sln new file mode 100644 index 00000000..8514216c --- /dev/null +++ b/c++/compilers/vs2015/user/build/ncbi_user.sln @@ -0,0 +1,35 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_CONFIGURE_DIALOG_", "UtilityProjects\_CONFIGURE_DIALOG_.vcxproj", "{EB043EAF-58D4-4179-AC32-538D9059BB8B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_CONFIGURE_", "UtilityProjects\_CONFIGURE_.vcxproj", "{8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA108}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + DebugDLL|x64 = DebugDLL|x64 + DebugDLL|x86 = DebugDLL|x86 + ReleaseDLL|x64 = ReleaseDLL|x64 + ReleaseDLL|x86 = ReleaseDLL|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {EB043EAF-58D4-4179-AC32-538D9059BB8B}.DebugDLL|x64.ActiveCfg = DebugDLL|x64 + {EB043EAF-58D4-4179-AC32-538D9059BB8B}.DebugDLL|x64.Build.0 = DebugDLL|x64 + {EB043EAF-58D4-4179-AC32-538D9059BB8B}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32 + {EB043EAF-58D4-4179-AC32-538D9059BB8B}.DebugDLL|x86.Build.0 = DebugDLL|Win32 + {EB043EAF-58D4-4179-AC32-538D9059BB8B}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 + {EB043EAF-58D4-4179-AC32-538D9059BB8B}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + {EB043EAF-58D4-4179-AC32-538D9059BB8B}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32 + {EB043EAF-58D4-4179-AC32-538D9059BB8B}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA108}.DebugDLL|x64.ActiveCfg = DebugDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA108}.DebugDLL|x64.Build.0 = DebugDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA108}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA108}.DebugDLL|x86.Build.0 = DebugDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA108}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA108}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA108}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32 + {8BC9CEB8-8B4A-11D0-8D11-AAAAAAAAA108}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/c++/compilers/xcode30_prj/configure b/c++/compilers/xcode30_prj/configure index 6ea67b61..0346b2a2 100755 --- a/c++/compilers/xcode30_prj/configure +++ b/c++/compilers/xcode30_prj/configure @@ -1,6 +1,6 @@ #!/bin/sh -# $Id: configure 474742 2015-07-31 13:01:07Z gouriano $ +# $Id: configure 509262 2016-08-04 14:17:42Z ivanov $ # Author: Andrei Gourianov, NCBI (gouriano@ncbi.nlm.nih.gov) #----------------------------------------------------------------------------- @@ -15,11 +15,9 @@ use_savedcfg="" use_gui="no" use_debug="yes" use_dll="no" -use_64="no" -use_universal="no" +use_64="yes" use_staticstd="no" use_action="" -use_arch="" srcroot="../.." mk_name="Makefile" @@ -38,6 +36,7 @@ noops="\ --with-plugin-auto-load \ --with-bin-release \ --with-mt \ + --with-64 \ --without-exe \ --with-runpath \ --with-lfs \ @@ -196,9 +195,7 @@ OPTIONS: --with-debug -- build debug versions of libs and apps --without-dll -- build all toolkit libraries as static ones --with-dll -- assemble toolkit libraries into DLLs where requested - --with-64 -- compile to 64-bit code - --with-universal -- build universal binaries - --with-universal=CPU -- build universal binaries targeting the given CPU + --without-64 -- compile to 32-bit code --with-static-exe -- use static C++ standard libraries --with-projects=FILE -- build projects listed in $srcroot/FILE FILE can also be a name of a subdirectory @@ -232,10 +229,8 @@ for cmd_arg in "$@"; do --with-debug ) use_debug="yes" ;; --without-dll ) use_dll="no" ;; --with-dll ) use_dll="yes" ;; - --with-64 ) use_64="yes" ;; - --with-universal ) use_universal="yes" ;; + --without-64 ) use_64="no" ;; --with-static-exe ) use_staticstd="yes" ;; - --with-universal=* ) use_arch="$cmd_arg" ;; --with-projects=* ) use_projectlst="$cmd_arg" ;; --with-extra-action=* ) use_action="$cmd_arg" ;; --ignore-unsupported-options ) ignore_unknown="yes" ;; @@ -275,7 +270,6 @@ if test -n "$use_savedcfg"; then fi fi fi -use_arch=`echo $use_arch | sed -e s/--with-universal=//` use_projectlst=`echo $use_projectlst | sed -e s/--with-projects=//` use_action=`echo $use_action | sed -e s/--with-extra-action=//` #-------------------------------------------------------------------------------- @@ -286,20 +280,10 @@ arch=`arch` platform=`xcodebuild -version 2>/dev/null | grep 'Xcode [0-9][0-9]*' | sed -e 's/[ .]//g'` # ------- target architecture -if test -z "$use_arch"; then - if test "$use_universal" == "yes"; then - if test "$use_64" == "yes"; then - use_arch="ppc64 x86_64" - else - use_arch="ppc i386" - fi - else - if test "$use_64" == "yes"; then - use_arch="x86_64" - else - use_arch="i386" - fi - fi +if test "$use_64" == "yes"; then + use_arch="x86_64" +else + use_arch="i386" fi PTB_PLATFORM="$use_arch" diff --git a/c++/compilers/xcode30_prj/ptb.sh b/c++/compilers/xcode30_prj/ptb.sh index d8e8cba8..9afaf2af 100755 --- a/c++/compilers/xcode30_prj/ptb.sh +++ b/c++/compilers/xcode30_prj/ptb.sh @@ -1,5 +1,5 @@ #!/bin/sh -# $Id: ptb.sh 471603 2015-06-29 18:48:10Z ucko $ +# $Id: ptb.sh 507307 2016-07-18 16:33:11Z gouriano $ # =========================================================================== # # PUBLIC DOMAIN NOTICE @@ -51,6 +51,10 @@ PTBGUI="${TREE_ROOT}/src/build-system/project_tree_builder_gui/bin/ptbgui.jar" DEFPTB_VERSION_FILE="${TREE_ROOT}/src/build-system/ptb_version.txt" PTB_INI="${TREE_ROOT}/src/build-system/${ptbname}.ini" PTB_SLN="${BUILD_TREE_ROOT}/static/UtilityProjects/PTB.xcodeproj" +NCBICONF_MSVC="${TREE_ROOT}/include/common/config/ncbiconf_xcode_site.h" +if test -e "${NCBICONF_MSVC}"; then + NCBICONF_MSVC= +fi # ------------------------------------------------------------------------- # get PTB version: from DEFPTB_VERSION_FILE or from PREBUILT_PTB_EXE @@ -165,7 +169,13 @@ if test ! -x "$PTB_EXE"; then cmd="`dirname $0`/xcodebuild.sh -project $PTB_SLN -target $ptbname -configuration ReleaseDLL" echo "$cmd" echo "==============================================================================" + if test "${NCBICONF_MSVC}" != ""; then + echo // > "${NCBICONF_MSVC}" + fi $cmd + if test "${NCBICONF_MSVC}" != ""; then + rm "${NCBICONF_MSVC}" + fi else echo "==============================================================================" echo "Using PREBUILT $ptbname at $PTB_EXE" diff --git a/c++/configure b/c++/configure index 611b5171..8095f791 100755 --- a/c++/configure +++ b/c++/configure @@ -1,3 +1,3 @@ #!/bin/sh srcdir=`dirname $0` -exec $srcdir/configure.orig --without-debug --with-strip --with-openmp --with-mt --with-build-root=$srcdir/ReleaseMT ${1+"$@"} +exec $srcdir/configure.orig --without-debug --with-strip --with-openmp --with-mt --without-vdb --with-build-root=$srcdir/ReleaseMT ${1+"$@"} diff --git a/c++/include/algo/blast/api/blast_aux.hpp b/c++/include/algo/blast/api/blast_aux.hpp index 2bb1d41d..778a47fb 100644 --- a/c++/include/algo/blast/api/blast_aux.hpp +++ b/c++/include/algo/blast/api/blast_aux.hpp @@ -1,4 +1,4 @@ -/* $Id: blast_aux.hpp 321879 2011-07-26 16:09:25Z camacho $ +/* $Id: blast_aux.hpp 507721 2016-07-21 14:07:53Z fongah2 $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -43,6 +43,7 @@ #include #include // For TSeqRange #include +#include // BLAST includes #include @@ -178,6 +179,29 @@ NCBI_XBLAST_EXPORT CRef MaskedQueryRegionsToPackedSeqLoc( const TMaskedQueryRegions & sloc); +struct NCBI_XBLAST_EXPORT CConstRefCSeqId_LessThan +{ + bool operator() (const CConstRef& a, const CConstRef& b) const { + if (a.Empty() && b.NotEmpty()) { + return true; + } else if (a.NotEmpty() && b.Empty()) { + return false; + } else if (a.Empty() && b.Empty()) { + return true; + } else { + _ASSERT(a.NotEmpty() && b.NotEmpty()); + return *a < *b; + } + } +}; + +/// This method retrieve sequence data in bulk to scope +/// @ids seq id list [in] +/// @ranges seq range list [in] +/// @scope sconfigured with data loader for retrieving seqs [in] | retrieved bioseqs [out] +NCBI_XBLAST_EXPORT +void +LoadSequencesToScope(objects::CScope::TIds& ids, vector& ranges, CRef & scope); /// Converts a BlastMaskLoc internal structure into an object returned by the /// C++ API. diff --git a/c++/include/algo/blast/api/blast_options.hpp b/c++/include/algo/blast/api/blast_options.hpp index 12943c86..50331db8 100644 --- a/c++/include/algo/blast/api/blast_options.hpp +++ b/c++/include/algo/blast/api/blast_options.hpp @@ -1,4 +1,4 @@ -/* $Id: blast_options.hpp 456407 2015-01-12 15:47:18Z fongah2 $ +/* $Id: blast_options.hpp 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -144,6 +144,12 @@ public: int GetWordSize() const; void SetWordSize(int ws); + Uint4 GetLookupTableStride() const; + void SetLookupTableStride(Uint4 val); + + bool GetLookupDbFilter(void) const; + void SetLookupDbFilter(bool val); + /// Megablast only lookup table options unsigned char GetMBTemplateLength() const; void SetMBTemplateLength(unsigned char len); @@ -277,6 +283,12 @@ public: int GetUnifiedP() const; void SetUnifiedP(int u = 0); + int GetMaxMismatches() const; + void SetMaxMismatches(int m); + + int GetMismatchWindow() const; + void SetMismatchWindow(int w); + /******************* Hit saving options *************************/ int GetHitlistSize() const; void SetHitlistSize(int s); @@ -341,6 +353,14 @@ public: double GetLowScorePerc() const; void SetLowScorePerc(double p = 0.0); + // Return only paired reads, for mapping + bool GetPaired() const; + void SetPaired(bool p); + + /// Splice HSPs for each query (for mappring RNA-Seq reads to a genome) + bool GetSpliceAlignments() const; + void SetSpliceAlignments(bool s); + /************************ Scoring options ************************/ const char* GetMatrixName() const; void SetMatrixName(const char* matrix); diff --git a/c++/include/algo/blast/api/blast_options_handle.hpp b/c++/include/algo/blast/api/blast_options_handle.hpp index 65297205..143ac239 100644 --- a/c++/include/algo/blast/api/blast_options_handle.hpp +++ b/c++/include/algo/blast/api/blast_options_handle.hpp @@ -1,7 +1,7 @@ #ifndef ALGO_BLAST_API___BLAST_OPTIONS_HANDLE__HPP #define ALGO_BLAST_API___BLAST_OPTIONS_HANDLE__HPP -/* $Id: blast_options_handle.hpp 472241 2015-07-08 15:24:13Z fongah2 $ +/* $Id: blast_options_handle.hpp 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -111,6 +111,7 @@ public: enum ETaskSets { eNuclNucl, ///< Nucleotide-nucleotide tasks eProtProt, ///< Protein-protein tasks + eMapping, ///< Mapping tasks eAll ///< Retrieve all available tasks }; diff --git a/c++/include/algo/blast/api/blast_seqinfosrc.hpp b/c++/include/algo/blast/api/blast_seqinfosrc.hpp index f7aa39d4..5b21f1d6 100644 --- a/c++/include/algo/blast/api/blast_seqinfosrc.hpp +++ b/c++/include/algo/blast/api/blast_seqinfosrc.hpp @@ -1,7 +1,7 @@ #ifndef ALGO_BLAST_API__BLAST_SEQINFOSRC__HPP #define ALGO_BLAST_API__BLAST_SEQINFOSRC__HPP -/* $Id: blast_seqinfosrc.hpp 499810 2016-04-28 15:43:25Z ivanov $ +/* $Id: blast_seqinfosrc.hpp 499693 2016-04-27 17:19:56Z madden $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/algo/blast/api/blast_seqinfosrc_aux.hpp b/c++/include/algo/blast/api/blast_seqinfosrc_aux.hpp index 75d0ba9e..d50a10e5 100644 --- a/c++/include/algo/blast/api/blast_seqinfosrc_aux.hpp +++ b/c++/include/algo/blast/api/blast_seqinfosrc_aux.hpp @@ -1,7 +1,7 @@ #ifndef ALGO_BLAST_API___BLAST_SEQINFOSRC_AUX__HPP #define ALGO_BLAST_API___BLAST_SEQINFOSRC_AUX__HPP -/* $Id: blast_seqinfosrc_aux.hpp 140187 2008-09-15 16:35:34Z camacho $ +/* $Id: blast_seqinfosrc_aux.hpp 520431 2016-11-28 18:26:12Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -73,8 +73,25 @@ void GetSequenceLengthAndId(const IBlastSeqInfoSrc* seqinfo_src, NCBI_XBLAST_EXPORT void GetFilteredRedundantGis(const IBlastSeqInfoSrc & sisrc, int oid, - vector & gis); + vector & gis); +/// Get Seqids for a sequence in a redundant database. +/// +/// This function returns a list of GIs or Seqids corresponding to the specified +/// OID. This allows a GI list to be built for those GIs found by a +/// search and included in the associated database; the returned GIs +/// will be filtered by any OID and GI list filtering that is applied +/// to the database (if any). +/// +/// @param sisrc Source of sequence information. [in] +/// @param oid OID for which to retrieve GIs. [in] +/// @param seqids SeqIds found for the specified oid. [out] +/// @param use_gis Return only GIs seqids vector [in] +NCBI_XBLAST_EXPORT +void GetFilteredRedundantSeqids(const IBlastSeqInfoSrc & sisrc, + int oid, + vector & seqids, + bool use_gis=true); END_SCOPE(blast) END_NCBI_SCOPE diff --git a/c++/include/algo/blast/api/blast_types.hpp b/c++/include/algo/blast/api/blast_types.hpp index 3499343c..475684c0 100644 --- a/c++/include/algo/blast/api/blast_types.hpp +++ b/c++/include/algo/blast/api/blast_types.hpp @@ -1,4 +1,4 @@ -/* $Id: blast_types.hpp 384426 2012-12-26 23:09:56Z camacho $ +/* $Id: blast_types.hpp 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -70,6 +70,7 @@ enum EProgram { ePHIBlastn, ///< Nucleotide PHI BLAST eDeltaBlast, ///< Delta Blast eVecScreen, ///< Vector screening + eMapper, ///< Jumper alignment for mapping eBlastProgramMax ///< Undefined program }; diff --git a/c++/include/algo/blast/api/magicblast.hpp b/c++/include/algo/blast/api/magicblast.hpp new file mode 100644 index 00000000..faca1c9e --- /dev/null +++ b/c++/include/algo/blast/api/magicblast.hpp @@ -0,0 +1,115 @@ +/* $Id: magicblast.hpp 504861 2016-06-20 15:45:40Z boratyng $ + * =========================================================================== + * + * PUBLIC DOMAIN NOTICE + * National Center for Biotechnology Information + * + * This software/database is a "United States Government Work" under the + * terms of the United States Copyright Act. It was written as part of + * the author's official duties as a United States Government employee and + * thus cannot be copyrighted. This software/database is freely available + * to the public for use. The National Library of Medicine and the U.S. + * Government have not placed any restriction on its use or reproduction. + * + * Although all reasonable efforts have been taken to ensure the accuracy + * and reliability of the software and data, the NLM and the U.S. + * Government do not and cannot warrant the performance or results that + * may be obtained by using this software or data. The NLM and the U.S. + * Government disclaim all warranties, express or implied, including + * warranties of performance, merchantability or fitness for any particular + * purpose. + * + * Please cite the author in any work or product based on this material. + * + * =========================================================================== + * + * Author: Greg Boratyn + * + */ + +/// @file magicblast.hpp +/// Declares CMagicBlast, the C++ API for the BLAST RNA-Seq mapping engine. + +#ifndef ALGO_BLAST_API___MAGICBLAST__HPP +#define ALGO_BLAST_API___MAGICBLAST__HPP + +#include +#include +#include +#include +#include + +/** @addtogroup AlgoBlast + * + * @{ + */ + +BEGIN_NCBI_SCOPE +BEGIN_SCOPE(blast) + +// Forward declarations +class IQueryFactory; + +/// BLAST RNA-Seq mapper +class NCBI_XBLAST_EXPORT CMagicBlast : public CObject, public CThreadable +{ +public: + +public: + /// Constructor to map short reads as queries to a genome as BLAST database + /// @param query_factory + /// Short reads sequence to map [in] + /// @param blastdb + /// Adapter to the BLAST database [in] + /// @param options + /// MAGIC-BLAST options [in] + CMagicBlast(CRef query_factory, + CRef blastdb, + CRef options); + + /// Destructor + ~CMagicBlast() {} + + /// Run the RNA-Seq mapping + CRef Run(void); + + TSearchMessages GetSearchMessages(void) const + {return m_Messages;} + + +protected: + /// Prohibit copy constructor + CMagicBlast(const CMagicBlast& rhs); + /// Prohibit assignment operator + CMagicBlast& operator=(const CMagicBlast& rhs); + + /// Perform sanity checks on input arguments + void x_Validate(void); + + /// Create results + CRef x_CreateSeqAlignSet(BlastMappingResults* results); + +private: + /// Queries + CRef m_Queries; + + /// Reference to a BLAST subject/database object + CRef m_LocalDbAdapter; + + /// Options to configure the search + CRef m_Options; + + /// Internal data strctures + CRef m_InternalData; + + /// Warning and error messages + TSearchMessages m_Messages; +}; + + +END_SCOPE(blast) +END_NCBI_SCOPE + +/* @} */ + +#endif /* ALGO_BLAST_API___MAGICBLAST__HPP */ diff --git a/c++/include/algo/blast/api/magicblast_options.hpp b/c++/include/algo/blast/api/magicblast_options.hpp new file mode 100644 index 00000000..446ca5e8 --- /dev/null +++ b/c++/include/algo/blast/api/magicblast_options.hpp @@ -0,0 +1,211 @@ +#ifndef ALGO_BLAST_API___MAGIC_BLAST_OPTIONS__HPP +#define ALGO_BLAST_API___MAGIC_BLAST_OPTIONS__HPP + +/* $Id: magicblast_options.hpp 504861 2016-06-20 15:45:40Z boratyng $ + * =========================================================================== + * + * PUBLIC DOMAIN NOTICE + * National Center for Biotechnology Information + * + * This software/database is a "United States Government Work" under the + * terms of the United States Copyright Act. It was written as part of + * the author's official duties as a United States Government employee and + * thus cannot be copyrighted. This software/database is freely available + * to the public for use. The National Library of Medicine and the U.S. + * Government have not placed any restriction on its use or reproduction. + * + * Although all reasonable efforts have been taken to ensure the accuracy + * and reliability of the software and data, the NLM and the U.S. + * Government do not and cannot warrant the performance or results that + * may be obtained by using this software or data. The NLM and the U.S. + * Government disclaim all warranties, express or implied, including + * warranties of performance, merchantability or fitness for any particular + * purpose. + * + * Please cite the author in any work or product based on this material. + * + * =========================================================================== + * + * Authors: Greg Boratyn + * + */ + +/// @file blast_mapper_options.hpp +/// Declares the CMagicBlastOptionsHandle class. + +#include + +/** @addtogroup AlgoBlast + * + * @{ + */ + +BEGIN_NCBI_SCOPE +BEGIN_SCOPE(blast) + +/// Handle to the nucleotide mapping options to the BLAST algorithm. +/// +/// Adapter class for nucleotide-nucleotide BLAST comparisons. +/// Exposes an interface to allow manipulation the options that are relevant to +/// this type of search. +/// +/// + +class NCBI_XBLAST_EXPORT CMagicBlastOptionsHandle : + public CBlastOptionsHandle +{ +public: + + /// Creates object with default options set + CMagicBlastOptionsHandle(EAPILocality locality = CBlastOptions::eLocal); + + /// Create Options Handle from Existing CBlastOptions Object + CMagicBlastOptionsHandle(CRef opt); + + /// Sets Defaults + virtual void SetDefaults(); + + virtual void SetRNAToGenomeDefaults(); + virtual void SetRNAToRNADefaults(); + virtual void SetGenomeToGenomeDefaults(); + + /******************* Lookup table options ***********************/ + + /// Return db filtering option for the lookup table + /// + /// The filtering removes from lookup table words that are frequent in the + /// database. + /// @return If true, words that are frequent in the dabase will be removed + bool GetLookupDbFilter() const { return m_Opts->GetLookupDbFilter(); } + + /// Set db filtering option for the lookup table + /// + /// The filtering removes from lookup table words that are frequent in the + /// database. + /// @param b If true, words that are frequent in the dabase will be removed + /// from the lookup table + void SetLookupDbFilter(bool b) { m_Opts->SetLookupDbFilter(b); } + + /// Return number of words skipped betweem collected ones when creating + /// a lookup table + int GetLookupTableStride() const { return m_Opts->GetLookupTableStride(); } + + /// Set lookup table stride: number of words skipped between collected ones + /// when creating a lookup table + /// @param s lookup table stride [in] + void SetLookupTableStride(int s) { m_Opts->SetLookupTableStride(s); } + + + /******************* Query setup options ************************/ + + + /******************* Initial word options ***********************/ + + /// Return word size + int GetWordSize() const { return m_Opts->GetWordSize(); } + + /// Set word size + /// @param w word size [in] + void SetWordSize(int w) { m_Opts->SetWordSize(w); } + + /******************* Gapped extension options *******************/ + + + /************************ Scoring options ************************/ + + /// Returns mismatch penalty + int GetMismatchPenalty() const { return m_Opts->GetMismatchPenalty(); } + + /// Sets mismatch penalty + /// @param p mismatch penalty [in] + void SetMismatchPenalty(int p) { m_Opts->SetMismatchPenalty(p); } + + /// Return gap opening cost + int GetGapOpeningCost() const { return m_Opts->GetGapOpeningCost(); } + + /// Set gap opening cost + /// @param g gap opening cost [in] + void SetGapOpeningCost(int g) { m_Opts->SetGapOpeningCost(g); } + + /// Return gap extension cost + int GetGapExtensionCost() const { return m_Opts->GetGapExtensionCost(); } + + /// Sets gap extension cost + /// @param g gap extension cost [in] + void SetGapExtensionCost(int g) { m_Opts->SetGapExtensionCost(g); } + + /// Return a single alignment cutoff score + int GetCutoffScore() const { return m_Opts->GetCutoffScore(); } + + /// Set a single alignment cutoff score + /// @param s cutoff score [in] + void SetCutoffScore(int s) { m_Opts->SetCutoffScore(s); } + + + /************************ Mapping options ************************/ + + /// Are the mapping reads assumed paired + /// @returns True if reads are assumed paired, false otherwise + bool GetPaired() const { return m_Opts->GetPaired(); } + + /// Set input reads as paired/not paired + /// @param p If true, the input sequences are paired [in] + void SetPaired(bool p) { m_Opts->SetPaired(p); } + + /// Return the splice/unsplice alignments switch value + /// @return True if alignments are spliced, false otherwise + bool GetSpliceAlignments() const { return m_Opts->GetSpliceAlignments(); } + + /// Set splicing alignments + /// @param s if true alignments will be spliced [in] + void SetSpliceAlignments(bool s) { m_Opts->SetSpliceAlignments(s); } + + /// Get max intron length + /// @return Max intron length + int GetLongestIntronLength(void) const + { return m_Opts->GetLongestIntronLength(); } + + /// Set max intron length + /// @param len Max inrton length + void SetLongestIntronLength(int len) {m_Opts->SetLongestIntronLength(len);} + + +protected: + /// Set the program and service name for remote blast. + virtual void SetRemoteProgramAndService_Blast3() + { +// m_Opts->SetRemoteProgramAndService_Blast3("blastn", "megablast"); + } + + /// Overrides LookupTableDefaults for nucleotide options + virtual void SetLookupTableDefaults(); + /// Overrides QueryOptionDefaults for nucleotide options + virtual void SetQueryOptionDefaults(); + /// Overrides InitialWordOptionsDefaults for nucleotide options + virtual void SetInitialWordOptionsDefaults(); + /// Overrides GappedExtensionDefaults for nucleotide options + virtual void SetGappedExtensionDefaults(); + /// Overrides ScoringOptionsDefaults for nucleotide options + virtual void SetScoringOptionsDefaults(); + /// Overrides HitSavingOptionsDefaults for nucleotide options + virtual void SetHitSavingOptionsDefaults(); + /// Overrides EffectiveLengthsOptionsDefaults for nucleotide options + virtual void SetEffectiveLengthsOptionsDefaults(); + /// Overrides SubjectSequenceOptionsDefaults for nucleotide options + virtual void SetSubjectSequenceOptionsDefaults(); + +private: + /// Disallow copy constructor + CMagicBlastOptionsHandle(const CMagicBlastOptionsHandle& rhs); + /// Disallow assignment operator + CMagicBlastOptionsHandle& operator=(const CMagicBlastOptionsHandle& rhs); +}; + +END_SCOPE(blast) +END_NCBI_SCOPE + + +/* @} */ + + +#endif /* ALGO_BLAST_API___MAGIC_BLAST_OPTIONS__HPP */ diff --git a/c++/include/algo/blast/api/objmgrfree_query_data.hpp b/c++/include/algo/blast/api/objmgrfree_query_data.hpp index d84fa4e5..ef0df8cb 100644 --- a/c++/include/algo/blast/api/objmgrfree_query_data.hpp +++ b/c++/include/algo/blast/api/objmgrfree_query_data.hpp @@ -1,4 +1,4 @@ -/* $Id: objmgrfree_query_data.hpp 194794 2010-06-17 14:18:44Z camacho $ +/* $Id: objmgrfree_query_data.hpp 506274 2016-07-06 14:41:04Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -47,8 +47,7 @@ BEGIN_NCBI_SCOPE BEGIN_SCOPE(blast) /// NCBI C++ Object Manager free implementation of IQueryFactory -/// @deprecated Please use CObjMgr_QueryFactory instead -NCBI_DEPRECATED_CLASS NCBI_XBLAST_EXPORT CObjMgrFree_QueryFactory : +class NCBI_XBLAST_EXPORT CObjMgrFree_QueryFactory : public IQueryFactory { public: diff --git a/c++/include/algo/blast/api/remote_blast.hpp b/c++/include/algo/blast/api/remote_blast.hpp index fb58a12e..f0aee84d 100644 --- a/c++/include/algo/blast/api/remote_blast.hpp +++ b/c++/include/algo/blast/api/remote_blast.hpp @@ -1,7 +1,7 @@ #ifndef ALGO_BLAST_API___REMOTE_BLAST__HPP #define ALGO_BLAST_API___REMOTE_BLAST__HPP -/* $Id: remote_blast.hpp 495288 2016-03-16 14:51:11Z ivanov $ +/* $Id: remote_blast.hpp 494040 2016-03-03 14:36:13Z fongah2 $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/algo/blast/api/seqinfosrc_seqdb.hpp b/c++/include/algo/blast/api/seqinfosrc_seqdb.hpp index 827ffe2e..8b5a75a1 100644 --- a/c++/include/algo/blast/api/seqinfosrc_seqdb.hpp +++ b/c++/include/algo/blast/api/seqinfosrc_seqdb.hpp @@ -1,7 +1,7 @@ #ifndef ALGO_BLAST_API__SEQINFOSRC_SEQDB__HPP #define ALGO_BLAST_API__SEQINFOSRC_SEQDB__HPP -/* $Id: seqinfosrc_seqdb.hpp 499810 2016-04-28 15:43:25Z ivanov $ +/* $Id: seqinfosrc_seqdb.hpp 499693 2016-04-27 17:19:56Z madden $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/algo/blast/api/seqinfosrc_seqvec.hpp b/c++/include/algo/blast/api/seqinfosrc_seqvec.hpp index 023db110..88a8afd0 100644 --- a/c++/include/algo/blast/api/seqinfosrc_seqvec.hpp +++ b/c++/include/algo/blast/api/seqinfosrc_seqvec.hpp @@ -1,7 +1,7 @@ #ifndef ALGO_BLAST_API__SEQINFOSRC_SEQVEC__HPP #define ALGO_BLAST_API__SEQINFOSRC_SEQVEC__HPP -/* $Id: seqinfosrc_seqvec.hpp 499810 2016-04-28 15:43:25Z ivanov $ +/* $Id: seqinfosrc_seqvec.hpp 499693 2016-04-27 17:19:56Z madden $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/algo/blast/api/setup_factory.hpp b/c++/include/algo/blast/api/setup_factory.hpp index c30627fa..310fd126 100644 --- a/c++/include/algo/blast/api/setup_factory.hpp +++ b/c++/include/algo/blast/api/setup_factory.hpp @@ -1,4 +1,4 @@ -/* $Id: setup_factory.hpp 354756 2012-02-29 17:40:28Z morgulis $ +/* $Id: setup_factory.hpp 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -262,9 +262,11 @@ public: /// Create a writer to be registered for use by stream /// @param opts_memento Memento options object [in] + /// @param query Concatenanted query sequence [in] /// @param query_info Information about queries [in] static BlastHSPWriter* CreateHspWriter(const CBlastOptionsMemento* opts_memento, + BLAST_SequenceBlk* query, BlastQueryInfo* query_info); /// Create a pipe to be registered for use by stream diff --git a/c++/include/algo/blast/blastinput/blast_args.hpp b/c++/include/algo/blast/blastinput/blast_args.hpp index 23584efd..1d1afe2c 100644 --- a/c++/include/algo/blast/blastinput/blast_args.hpp +++ b/c++/include/algo/blast/blastinput/blast_args.hpp @@ -1,4 +1,4 @@ -/* $Id: blast_args.hpp 484853 2015-11-16 18:32:26Z fongah2 $ +/* $Id: blast_args.hpp 514850 2016-09-26 17:23:32Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -49,6 +49,8 @@ #include #include +#include + BEGIN_NCBI_SCOPE BEGIN_SCOPE(blast) @@ -108,7 +110,8 @@ class NCBI_BLASTINPUT_EXPORT CStdCmdLineArgs : public IBlastCmdLineArgs { public: /** Default constructor */ - CStdCmdLineArgs() : m_InputStream(0), m_OutputStream(0) {}; + CStdCmdLineArgs() : m_InputStream(0), m_OutputStream(0), + m_GzipEnabled(false) {}; /** Interface method, \sa IBlastCmdLineArgs::SetArgumentDescriptions */ virtual void SetArgumentDescriptions(CArgDescriptions& arg_desc); /** Interface method, \sa IBlastCmdLineArgs::SetArgumentDescriptions */ @@ -121,13 +124,26 @@ public: /** Set the input stream if read from a saved search strategy */ void SetInputStream(CRef input_file); + /** Set automatic decompression of the input file is file name is + * recognized + * @param g If true input file will be unzgipped if the file name ends with + * ".gz" [in] + */ + void SetGzipEnabled(bool g) {m_GzipEnabled = g;} + private: CNcbiIstream* m_InputStream; ///< Application's input stream CNcbiOstream* m_OutputStream; ///< Application's output stream + auto_ptr m_DecompressIStream; + auto_ptr m_CompressOStream; /// ASN.1 specification of query sequences when read from a saved search /// strategy CRef m_QueryTmpInputFile; + + /// If true input file will be decompressed with gzip if filename ends + /// with ".gz" + bool m_GzipEnabled; }; /** Argument class to populate an application's name and description */ @@ -145,7 +161,7 @@ public: /** Interface method, \sa IBlastCmdLineArgs::SetArgumentDescriptions */ virtual void SetArgumentDescriptions(CArgDescriptions& arg_desc); -private: +protected: string m_ProgName; ///< Application's name string m_ProgDesc; ///< Application's description }; @@ -615,6 +631,55 @@ public: CBlastOptions& options); }; +/// Argument class to collect options specific to KBLASTP +class NCBI_BLASTINPUT_EXPORT CKBlastpArgs : public IBlastCmdLineArgs +{ +public: + + /// Constructor + CKBlastpArgs(void) : m_JDistance(0.05), m_MinHits(0), m_TargetSeqs(5000) {} + + /// Our virtual destructor + virtual ~CKBlastpArgs() {} + + /** Interface method, \sa IBlastCmdLineArgs::SetArgumentDescriptions */ + virtual void SetArgumentDescriptions(CArgDescriptions& arg_desc); + /** Interface method, \sa IBlastCmdLineArgs::SetArgumentDescriptions */ + virtual void ExtractAlgorithmOptions(const CArgs& cmd_line_args, + CBlastOptions& options); + + + /// Get the Jaccard distance + double GetJaccardDistance(void) { return m_JDistance;} + + /// Get the minimum number of LSH matches. + int GetMinHits(void) {return m_MinHits;} + + /// The database + string GetDatabase(void) {return m_DbIndex;} + + /// Number of target sequences. + int GetTargetSeqs(void) {return m_TargetSeqs;} + +private: + /// Prohibit copy constructor + CKBlastpArgs(const CKBlastpArgs& rhs); + /// Prohibit assignment operator + CKBlastpArgs& operator=(const CKBlastpArgs& rhs); + + /// Jaccard distance + double m_JDistance; + + /// Minimum number of hits + int m_MinHits; + + /// Database/index + string m_DbIndex; + + /// Number of target sequences to try BLAST on. + int m_TargetSeqs; +}; + /// Argument class to collect options specific to DELTA-BLAST class NCBI_BLASTINPUT_EXPORT CDeltaBlastArgs : public IBlastCmdLineArgs { @@ -654,6 +719,20 @@ private: bool m_ShowDomainHits; }; + +class NCBI_BLASTINPUT_EXPORT CMappingArgs : public IBlastCmdLineArgs +{ +public: + CMappingArgs(void) {} + + /** Interface method, \sa IBlastCmdLineArgs::SetArgumentDescriptions */ + virtual void SetArgumentDescriptions(CArgDescriptions& arg_desc); + /** Interface method, \sa IBlastCmdLineArgs::SetArgumentDescriptions */ + virtual void ExtractAlgorithmOptions(const CArgs& cmd_line_args, + CBlastOptions& options); + +}; + /*****************************************************************************/ // Input options @@ -692,6 +771,7 @@ public: /// Is the query sequence protein? bool QueryIsProtein() const { return m_QueryCannotBeNucl; } + private: /// Strand(s) to search objects::ENa_strand m_Strand; @@ -704,9 +784,69 @@ private: /// only false for blast[xn], and tblastx /// true in case of PSI-BLAST - bool m_QueryCannotBeNucl; + bool m_QueryCannotBeNucl; +}; + +/// Argument class to collect query options for BLAST Mapper +class NCBI_BLASTINPUT_EXPORT CMapperQueryOptionsArgs : public CQueryOptionsArgs +{ +public: + + /// Input formats + enum EInputFormat { + eFasta = 0, + eFastc, + eFastq, + eASN1text, + eASN1bin, + eSra + }; + + + CMapperQueryOptionsArgs(void) + : CQueryOptionsArgs(false), + m_IsPaired(false), + m_InputFormat(eFasta), + m_QualityFilter(false), + m_MateInputStream(NULL) + {} + + /** Interface method, \sa IBlastCmdLineArgs::SetArgumentDescriptions */ + virtual void SetArgumentDescriptions(CArgDescriptions& arg_desc); + /** Interface method, \sa IBlastCmdLineArgs::SetArgumentDescriptions */ + virtual void ExtractAlgorithmOptions(const CArgs& args, CBlastOptions& opt); + + /// Are query sequences paired + bool IsPaired(void) const {return m_IsPaired;} + + /// Are queries provided in Fastc format + EInputFormat GetInputFormat(void) const + {return m_InputFormat;} + + /// Should low quality sequences be rejected + bool DoQualityFilter(void) const {return m_QualityFilter;} + + /// Does the mate input stream exits + bool HasMateInputStream(void) const {return m_MateInputStream;} + + /// Get input stream for query mates + CNcbiIstream* GetMateInputStream(void) const {return m_MateInputStream;} + + /// Get a list of SRA accessions + const vector& GetSraAccessions(void) const + {return m_SraAccessions;} + +private: + bool m_IsPaired; + EInputFormat m_InputFormat; + bool m_QualityFilter; + vector m_SraAccessions; + + CNcbiIstream* m_MateInputStream; + auto_ptr m_DecompressIStream; }; + /// Argument class to collect database/subject arguments class NCBI_BLASTINPUT_EXPORT CBlastDatabaseArgs : public IBlastCmdLineArgs { @@ -731,7 +871,8 @@ public: /// @param is_deltablast is it DELTA-BLAST? CBlastDatabaseArgs(bool request_mol_type = false, bool is_rpsblast = false, - bool is_igblast = false); + bool is_igblast = false, + bool is_mapper = false); /** Interface method, \sa IBlastCmdLineArgs::SetArgumentDescriptions */ virtual void SetArgumentDescriptions(CArgDescriptions& arg_desc); /** Interface method, \sa IBlastCmdLineArgs::SetArgumentDescriptions */ @@ -796,6 +937,7 @@ protected: bool m_IsIgBlast; /**< true if the search is Ig-BLAST */ bool m_IsProtein; /**< Is the database/subject(s) protein? */ + bool m_IsMapper; /**< true for short read mapper */ CRef m_Subjects; /**< The subject sequences */ CRef m_Scope; /**< CScope object in which all subject sequences read are kept */ @@ -879,6 +1021,8 @@ public: eXml2_S, /// SAM format eSAM, + + eTaxFormat, /// Sentinel value for error checking eEndValue }; @@ -972,12 +1116,12 @@ public: return m_CustomOutputFormatSpec; } - bool ArchiveFormatRequested(const CArgs& args) const; + virtual bool ArchiveFormatRequested(const CArgs& args) const; size_t GetLineLength() const { return m_LineLength; } -private: +protected: EOutputFormat m_OutputFormat; ///< Choice of formatting output bool m_ShowGis; ///< Display NCBI GIs? TSeqPos m_NumDescriptions; ///< Number of 1-line descr. to show @@ -990,9 +1134,7 @@ private: /// comma-separated value (populated if applicable) string m_CustomOutputFormatSpec; size_t m_LineLength; - EFormatFlags m_FormatFlags; - }; /// Argument class to collect multi-threaded arguments @@ -1046,7 +1188,7 @@ private: }; /// Argument class to collect debugging options. -/// Only show in command line if compiled with _DEBUG +/// Only show in command line if compiled with _BLAST_DEBUG class NCBI_BLASTINPUT_EXPORT CDebugArgs : public IBlastCmdLineArgs { public: diff --git a/c++/include/algo/blast/blastinput/blast_asn1_input.hpp b/c++/include/algo/blast/blastinput/blast_asn1_input.hpp new file mode 100644 index 00000000..8660de06 --- /dev/null +++ b/c++/include/algo/blast/blastinput/blast_asn1_input.hpp @@ -0,0 +1,119 @@ +/* $Id: blast_asn1_input.hpp 504861 2016-06-20 15:45:40Z boratyng $ + * =========================================================================== + * + * PUBLIC DOMAIN NOTICE + * National Center for Biotechnology Information + * + * This software/database is a "United States Government Work" under the + * terms of the United States Copyright Act. It was written as part of + * the author's official duties as a United States Government employee and + * thus cannot be copyrighted. This software/database is freely available + * to the public for use. The National Library of Medicine and the U.S. + * Government have not placed any restriction on its use or reproduction. + * + * Although all reasonable efforts have been taken to ensure the accuracy + * and reliability of the software and data, the NLM and the U.S. + * Government do not and cannot warrant the performance or results that + * may be obtained by using this software or data. The NLM and the U.S. + * Government disclaim all warranties, express or implied, including + * warranties of performance, merchantability or fitness for any particular + * purpose. + * + * Please cite the author in any work or product based on this material. + * + * =========================================================================== + * + * Author: Greg Boratyn + * + */ + +/** @file blast_fasta_input.hpp + * Interface for ASN1 files into blast sequence input + */ + +#ifndef ALGO_BLAST_BLASTINPUT___BLAST_ASN1_INPUT__HPP +#define ALGO_BLAST_BLASTINPUT___BLAST_ASN1_INPUT__HPP + +#include +#include + +BEGIN_NCBI_SCOPE +BEGIN_SCOPE(blast) + + +/// Class representing a text or binary file containing sequences in ASN.1 +/// format as a collection of Seq-entry objects +class NCBI_BLASTINPUT_EXPORT CASN1InputSourceOMF : public CBlastInputSourceOMF +{ +public: + + /// Constructor + /// @param infile Input stream for query sequences [in] + /// @param num_seqs_in_batch Number of sequences to read in a single batch + /// [in] + /// @param is_bin Is input in binary ASN.1 format [in] + /// @param is_paired Are queries paired [in] + /// @param validate Should sequence validation be applied to each read + /// sequence; if true sequences that do not pass validation will be + /// rejected [in] + CASN1InputSourceOMF(CNcbiIstream& infile, TSeqPos num_seqs_in_bacth, + bool is_bin = false, bool is_paired = false, + bool validate = true); + + /// Constructor for reading sequences from two files for paired short reads + /// @param infile1 Input stream for query sequences [in] + /// @param infile2 Input stream for query mates [in] + /// @param num_seqs_in_batch Number of sequences to read in a single batch + /// [in] + /// @param is_bin Is input in binary ASN.1 format [in] + /// @param validate Should sequence validation be applied to each read + /// sequence; if true sequences that do not pass validation will be + /// rejected [in] + CASN1InputSourceOMF(CNcbiIstream& infile1, CNcbiIstream& infile2, + TSeqPos num_seqs_in_bacth, bool is_bin = false, + bool validate = true); + + virtual ~CASN1InputSourceOMF() {} + + virtual void GetNextNumSequences(CBioseq_set& bioseq_set, TSeqPos num_seqs); + virtual bool End(void) {return m_InputStream->eof();} + + +private: + CASN1InputSourceOMF(const CASN1InputSourceOMF&); + CASN1InputSourceOMF& operator=(const CASN1InputSourceOMF&); + + bool x_ValidateSequence(const CSeq_data& seq_data, int length); + /// Compute dimer entropy for sequence in Ncbi2NA format + int x_FindDimerEntropy2NA(const vector& sequence, int length); + + /// Read one sequence from + int x_ReadOneSeq(CNcbiIstream& instream); + + /// Read sequences from one stream + bool x_ReadFromSingleFile(CBioseq_set& bioseq_set); + + /// Read sequences from two streams + bool x_ReadFromTwoFiles(CBioseq_set& bioseq_set); + + TSeqPos m_NumSeqsInBatch; + CNcbiIstream* m_InputStream; + // for reading paired reads from two FASTA files + CNcbiIstream* m_SecondInputStream; + /// Are queries paired + bool m_IsPaired; + /// Validate quereis and reject those that do not pass + bool m_Validate; + /// Is input binary ASN1 + bool m_IsBinary; + /// Used for indexing Seq-entries when reading from two files + int m_Index; + + vector< CRef > m_Entries; +}; + + +END_SCOPE(blast) +END_NCBI_SCOPE + +#endif /* ALGO_BLAST_BLASTINPUT___BLAST_ASN1_INPUT__HPP */ diff --git a/c++/include/algo/blast/blastinput/blast_fasta_input.hpp b/c++/include/algo/blast/blastinput/blast_fasta_input.hpp index 730fa79b..7835f065 100644 --- a/c++/include/algo/blast/blastinput/blast_fasta_input.hpp +++ b/c++/include/algo/blast/blastinput/blast_fasta_input.hpp @@ -1,4 +1,4 @@ -/* $Id: blast_fasta_input.hpp 163387 2009-06-15 18:32:16Z camacho $ +/* $Id: blast_fasta_input.hpp 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -110,6 +110,86 @@ private: void x_InitInputReader(); }; + +class NCBI_BLASTINPUT_EXPORT CShortReadFastaInputSource + : public CBlastInputSourceOMF +{ +public: + /// Input formats + enum EInputFormat { + eFasta = 0, + eFastc, + eFastq + }; + + + CShortReadFastaInputSource(CNcbiIstream& infile, TSeqPos num_seqs_in_bacth, + EInputFormat format = eFasta, + bool paired = false, bool validate = true); + + CShortReadFastaInputSource(CNcbiIstream& infile1, CNcbiIstream& infile2, + TSeqPos num_seqs_in_bacth, + EInputFormat format = eFasta, + bool validate = true); + + virtual ~CShortReadFastaInputSource() {} + + virtual void GetNextNumSequences(CBioseq_set& bioseq_set, TSeqPos num_seqs); + virtual bool End(void) {return m_LineReader->AtEOF();} + + /// Get number of rejected queries + Int4 GetNumRejected(void) const {return m_NumRejected;} + +private: + CShortReadFastaInputSource(const CShortReadFastaInputSource&); + CShortReadFastaInputSource& operator=(const CShortReadFastaInputSource&); + + CTempString x_ParseDefline(CTempString& line); + bool x_ValidateSequence(const char* sequence, int length); + + /// Read sequences in FASTA format + void x_ReadFasta(CBioseq_set& bioseq_set); + + /// Read sequences in FASTQ format + void x_ReadFastq(CBioseq_set& bioseq_set); + + /// Read one sequence from a FASTA file + int x_ReadFastaOneSeq(CRef line_reader); + + /// Read one sequence from a FASTQ file + int x_ReadFastqOneSeq(CRef line_reader); + + /// Read sequences from two FASTA or FASTQ files (for paired reads) + bool x_ReadFromTwoFiles(CBioseq_set& bioseq_set, EInputFormat format); + + /// Read sequences in FASTC format: defline, new line, a pair of sequences + /// on a single line separated by '><' + void x_ReadFastc(CBioseq_set& bioseq_set); + + TSeqPos m_NumSeqsInBatch; + /// string::capacity() can be used instead + TSeqPos m_SeqBuffLen; + CRef m_LineReader; + // for reading paired reads from two FASTA files + CRef m_SecondLineReader; + string m_Sequence; + CTempString m_Line; + /// Are paired sequences in the input + bool m_IsPaired; + /// Validate quereis and reject those that do not pass + bool m_Validate; + /// Number of queries that did not pass validation and were rejected + Int4 m_NumRejected; + /// Input format: FASTA, FASTQ, FASTC + EInputFormat m_Format; + /// Used for indexing Seq-entries when reading from two files + int m_Index; + + vector< CRef > m_SeqIds; + vector< CRef > m_Entries; +}; + + END_SCOPE(blast) END_NCBI_SCOPE diff --git a/c++/include/algo/blast/blastinput/blast_input.hpp b/c++/include/algo/blast/blastinput/blast_input.hpp index 15104b6a..21a3fd8d 100644 --- a/c++/include/algo/blast/blastinput/blast_input.hpp +++ b/c++/include/algo/blast/blastinput/blast_input.hpp @@ -1,4 +1,4 @@ -/* $Id: blast_input.hpp 388133 2013-02-05 19:47:18Z maning $ +/* $Id: blast_input.hpp 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -184,6 +184,16 @@ public: m_SeqLenThreshold2Guess = val; } + /// Retrieve gaps to Ns converstion option value + bool GetConvertGapsToNs(void) const { + return m_GapsToNs; + } + + /// Turn on/off converting gaps to Ns in read FASTA sequences + void SetConvertGapsToNs(bool val) { + m_GapsToNs = val; + } + private: /// Strand to assign to sequences objects::ENa_strand m_Strand; @@ -203,6 +213,8 @@ private: unsigned int m_SeqLenThreshold2Guess; /// Custom prefix string passed to CSeqidGenerator string m_LocalIdPrefix; + /// Convert gaps to Ns in FASTA sequences + bool m_GapsToNs; }; @@ -383,6 +395,43 @@ private: CRef m_scope; }; + +class NCBI_BLASTINPUT_EXPORT CBlastInputSourceOMF : public CObject +{ +protected: + virtual ~CBlastInputSourceOMF() {} + virtual void GetNextNumSequences(CBioseq_set& bioseq_set, + TSeqPos num_seqs) = 0; + + virtual bool End(void) = 0; + + friend class CBlastInputOMF; +}; + + +class NCBI_BLASTINPUT_EXPORT CBlastInputOMF : public CObject +{ +public: + CBlastInputOMF(CRef source, + TSeqPos num_seqs_in_batch = kMax_Int); + + void GetNextSeqBatch(CBioseq_set& bioseq_set); + CRef GetNextSeqBatch(void); + + void SetNumSeqsInBatch(TSeqPos num) {m_NumSeqsInBatch = num;} + TSeqPos GetNumSeqsInBatch(void) {return m_NumSeqsInBatch;} + + bool End(void) {return m_Source->End();} + +private: + CBlastInputOMF(const CBlastInputOMF& rhs); + CBlastInputOMF& operator=(const CBlastInputOMF& rhs); + + CRef m_Source; + TSeqPos m_NumSeqsInBatch; + CRef m_BioseqSet; +}; + END_SCOPE(blast) END_NCBI_SCOPE diff --git a/c++/include/algo/blast/blastinput/blast_input_aux.hpp b/c++/include/algo/blast/blastinput/blast_input_aux.hpp index 8e94033f..1eb41ce0 100644 --- a/c++/include/algo/blast/blastinput/blast_input_aux.hpp +++ b/c++/include/algo/blast/blastinput/blast_input_aux.hpp @@ -1,4 +1,4 @@ -/* $Id: blast_input_aux.hpp 483345 2015-10-30 14:04:13Z boratyng $ +/* $Id: blast_input_aux.hpp 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -265,6 +265,8 @@ GetQueryBatchSize(EProgram program, bool is_ungapped = false, bool remote = fals * @param use_lcase_masking true if the subject lowercase sequence characters * should be interpreted as masked regions [in] * @param sequences output will be placed here [in|out] + * @praram gaps_to_Ns convert all gaps in the sequences to Ns (only for + * nucleotide sequences) [in] * @return CScope object which contains all the sequences read */ NCBI_BLASTINPUT_EXPORT @@ -274,7 +276,8 @@ ReadSequencesToBlast(CNcbiIstream& in, const TSeqRange& range, bool parse_deflines, bool use_lcase_masking, - CRef& sequences); + CRef& sequences, + bool gaps_to_Ns = false); /// Calculates the formatting parameters based on the maximum number of target /// sequences selected (a.k.a.: hitlist size). @@ -327,6 +330,14 @@ CheckForEmptySequences(CRef sequences, string& warnings); NCBI_BLASTINPUT_EXPORT void CheckForEmptySequences(CRef sequences, string& warnings); +/// Compute entropy of 2-mers in a nucleotide IUPACNA sequence +/// @param sequence Nucleotide sequence [in] +/// @param length Sequence length [in] +/// @return Entropy of 2-base words +NCBI_BLASTINPUT_EXPORT int +FindDimerEntropy(const char* sequence, int length); + + END_SCOPE(blast) END_NCBI_SCOPE diff --git a/c++/include/algo/blast/blastinput/blast_scope_src.hpp b/c++/include/algo/blast/blastinput/blast_scope_src.hpp index e7bae2e4..731fcc14 100644 --- a/c++/include/algo/blast/blastinput/blast_scope_src.hpp +++ b/c++/include/algo/blast/blastinput/blast_scope_src.hpp @@ -1,7 +1,7 @@ #ifndef ALGO_BLAST_BLASTINPUT___BLAST_SCOPE_SRC__HPP #define ALGO_BLAST_BLASTINPUT___BLAST_SCOPE_SRC__HPP -/* $Id: blast_scope_src.hpp 165240 2009-07-08 16:21:59Z camacho $ +/* $Id: blast_scope_src.hpp 516396 2016-10-13 12:26:43Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -137,11 +137,11 @@ private: void x_Init(EConfigOpts options, const string& dbname, bool load_proteins); /// Load the DATA_LOADERS configuration value from the config file - void x_LoadDataLoadersConfig(const CMetaRegistry::SEntry& sentry); + void x_LoadDataLoadersConfig(const CNcbiRegistry& registry); /// Load the BLAST database configured to search for the blastdb /// DATA_LOADERS option from the config file - void x_LoadBlastDbDataLoaderConfig(const CMetaRegistry::SEntry& sentry); + void x_LoadBlastDbDataLoaderConfig(const CNcbiRegistry& registry); }; diff --git a/c++/include/algo/blast/blastinput/cmdline_flags.hpp b/c++/include/algo/blast/blastinput/cmdline_flags.hpp index cf8e59c8..449db402 100644 --- a/c++/include/algo/blast/blastinput/cmdline_flags.hpp +++ b/c++/include/algo/blast/blastinput/cmdline_flags.hpp @@ -1,4 +1,4 @@ -/* $Id: cmdline_flags.hpp 499246 2016-04-25 11:32:24Z ivanov $ +/* $Id: cmdline_flags.hpp 514854 2016-09-26 17:24:36Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -296,6 +296,12 @@ NCBI_BLASTINPUT_EXPORT extern const string kArgGLFocusV; NCBI_BLASTINPUT_EXPORT extern const string kArgExtendAlign; ///Argument to specify minimal required V length NCBI_BLASTINPUT_EXPORT extern const string kArgMinVLength; +///Argument to specify minimal required J gene length +NCBI_BLASTINPUT_EXPORT extern const string kArgMinJLength; +///Argument to specify number of clonotype to show +NCBI_BLASTINPUT_EXPORT extern const string kArgNumClonotype; +///Argument to specify number of clonotype file +NCBI_BLASTINPUT_EXPORT extern const string kArgClonotypeFile; /// Arugment to specify if Igblast alignment should be translated to protein NCBI_BLASTINPUT_EXPORT extern const string kArgTranslate; ///Arugment to specify if Igblast min D gene match @@ -344,6 +350,23 @@ NCBI_BLASTINPUT_EXPORT extern const string kArgRpsDb; /// Default value for domain database name NCBI_BLASTINPUT_EXPORT extern const string kDfltArgRpsDb; +/// KBLASTP arguments +/// Specifies Jaccard distance (threshold) +NCBI_BLASTINPUT_EXPORT extern const string kArgJDistance; +/// Default value +NCBI_BLASTINPUT_EXPORT extern const string kDfltArgJDistance; +/// Specifies minimal number of LSH matches +NCBI_BLASTINPUT_EXPORT extern const string kArgMinHits; +/// Default value +NCBI_BLASTINPUT_EXPORT extern const string kDfltArgMinHits; +/// KMER index +NCBI_BLASTINPUT_EXPORT extern const string kArgKIndex; +NCBI_BLASTINPUT_EXPORT extern const string kDfltArgKIndex; +/// Number of sequences to attempt BLAST on. +NCBI_BLASTINPUT_EXPORT extern const string kArgTargetSeqs; +NCBI_BLASTINPUT_EXPORT extern const string kDfltArgTargetSeqs; + + /// Argument to specify inclusion e-value threshold for conserved domains NCBI_BLASTINPUT_EXPORT extern const string kArgDomainInclusionEThreshold; /// Argument to specify whether show domain hits in DELTA-BLAST @@ -360,6 +383,32 @@ NCBI_BLASTINPUT_EXPORT extern const string kArgQueryCovHspPerc; /// Argument to specify line length for displaying alignments NCBI_BLASTINPUT_EXPORT extern const string kArgLineLength; + +// Mapper arguments +/// Argument to specify whether mapped reads are paired +NCBI_BLASTINPUT_EXPORT extern const string kArgPaired; +/// Argument to specify cutoff score for accepting non-spliced alignment +NCBI_BLASTINPUT_EXPORT extern const string kArgScore; +/// Argument to specify filtering lookup tables words by frequency in the +/// searched database +NCBI_BLASTINPUT_EXPORT extern const string kArgLimitLookup; +/// Argument to specify whether to search for spliced alignments +NCBI_BLASTINPUT_EXPORT extern const string kArgSplice; +/// Argument to sepcify the stride when creating a lookup table +NCBI_BLASTINPUT_EXPORT extern const string kArgLookupStride; +/// Argument to specify input format +NCBI_BLASTINPUT_EXPORT extern const string kArgInputFormat; +/// Argyment to specify whether quality filtering is to be done +NCBI_BLASTINPUT_EXPORT extern const string kArgQualityFilter; +/// Mates for the query sequences if given in a separate file +NCBI_BLASTINPUT_EXPORT extern const string kArgQueryMate; +/// Reference type: genome or transcriptome +NCBI_BLASTINPUT_EXPORT extern const string kArgRefType; +/// Argument to specify that the output will be compressed with gzip +NCBI_BLASTINPUT_EXPORT extern const string kArgOutputGzip; +/// Argument to specify SRA accessions +NCBI_BLASTINPUT_EXPORT extern const string kArgSraAccession; + END_SCOPE(blast) END_NCBI_SCOPE diff --git a/c++/include/algo/blast/blastinput/kblastp_args.hpp b/c++/include/algo/blast/blastinput/kblastp_args.hpp new file mode 100644 index 00000000..8797f0ee --- /dev/null +++ b/c++/include/algo/blast/blastinput/kblastp_args.hpp @@ -0,0 +1,75 @@ +/* $Id: kblastp_args.hpp 514851 2016-09-26 17:23:54Z ivanov $ + * =========================================================================== + * + * PUBLIC DOMAIN NOTICE + * National Center for Biotechnology Information + * + * This software/database is a "United States Government Work" under the + * terms of the United States Copyright Act. It was written as part of + * the author's official duties as a United States Government employee and + * thus cannot be copyrighted. This software/database is freely available + * to the public for use. The National Library of Medicine and the U.S. + * Government have not placed any restriction on its use or reproduction. + * + * Although all reasonable efforts have been taken to ensure the accuracy + * and reliability of the software and data, the NLM and the U.S. + * Government do not and cannot warrant the performance or results that + * may be obtained by using this software or data. The NLM and the U.S. + * Government disclaim all warranties, express or implied, including + * warranties of performance, merchantability or fitness for any particular + * purpose. + * + * Please cite the author in any work or product based on this material. + * + * =========================================================================== + * + * Author: Tom Madden + * + */ + +/** @file kblastp_args.hpp + * Main argument class for KBLASTP application + */ + +#ifndef ALGO_BLAST_BLASTINPUT___KBLASTP_ARGS__HPP +#define ALGO_BLAST_BLASTINPUT___KBLASTP_ARGS__HPP + +#include + +BEGIN_NCBI_SCOPE +BEGIN_SCOPE(blast) + +/// Handles command line arguments for blastp binary +class NCBI_BLASTINPUT_EXPORT CKBlastpAppArgs : public CBlastAppArgs +{ +public: + /// Constructor + CKBlastpAppArgs(); + + double GetJaccardDistance() { return m_KBlastpArgs->GetJaccardDistance(); } + + int GetMinHits() { return m_KBlastpArgs->GetMinHits(); } + + string GetDatabase() {return m_KBlastpArgs->GetDatabase(); } + + int GetTargetSeqs() {return m_KBlastpArgs->GetTargetSeqs(); } + + /// @inheritDoc + virtual int GetQueryBatchSize() const; + +protected: + /// @inheritDoc + virtual CRef + x_CreateOptionsHandle(CBlastOptions::EAPILocality locality, + const CArgs& args); + + /// KBlastp search specific arguments + CRef m_KBlastpArgs; + +}; + + +END_SCOPE(blast) +END_NCBI_SCOPE + +#endif /* ALGO_BLAST_BLASTINPUT___KBLASTP_ARGS__HPP */ diff --git a/c++/include/algo/blast/blastinput/magicblast_args.hpp b/c++/include/algo/blast/blastinput/magicblast_args.hpp new file mode 100644 index 00000000..b9d6560f --- /dev/null +++ b/c++/include/algo/blast/blastinput/magicblast_args.hpp @@ -0,0 +1,63 @@ +/* $Id: magicblast_args.hpp 504861 2016-06-20 15:45:40Z boratyng $ + * =========================================================================== + * + * PUBLIC DOMAIN NOTICE + * National Center for Biotechnology Information + * + * This software/database is a "United States Government Work" under the + * terms of the United States Copyright Act. It was written as part of + * the author's official duties as a United States Government employee and + * thus cannot be copyrighted. This software/database is freely available + * to the public for use. The National Library of Medicine and the U.S. + * Government have not placed any restriction on its use or reproduction. + * + * Although all reasonable efforts have been taken to ensure the accuracy + * and reliability of the software and data, the NLM and the U.S. + * Government do not and cannot warrant the performance or results that + * may be obtained by using this software or data. The NLM and the U.S. + * Government disclaim all warranties, express or implied, including + * warranties of performance, merchantability or fitness for any particular + * purpose. + * + * Please cite the author in any work or product based on this material. + * + * =========================================================================== + * + * Author: Greg Boratyn + * + */ + +/** @file blastmaper_args.hpp + * Main argument class for MAGICBLAST application + */ + +#ifndef ALGO_BLAST_BLASTINPUT___MAGICBLAST_ARGS__HPP +#define ALGO_BLAST_BLASTINPUT___MAGICBLAST_ARGS__HPP + +#include + +BEGIN_NCBI_SCOPE +BEGIN_SCOPE(blast) + +/// Handles command line arguments for blastmapper binary +class NCBI_BLASTINPUT_EXPORT CMagicBlastAppArgs : public CBlastAppArgs +{ +public: + /// Constructor + CMagicBlastAppArgs(); + + /// @inheritDoc + virtual int GetQueryBatchSize() const; + +protected: + /// @inheritDoc + virtual CRef + x_CreateOptionsHandle(CBlastOptions::EAPILocality locality, + const CArgs& args); +}; + + +END_SCOPE(blast) +END_NCBI_SCOPE + +#endif /* ALGO_BLAST_BLASTINPUT___MAGICBLAST_ARGS__HPP */ diff --git a/c++/include/algo/blast/composition_adjustment/composition_adjustment.h b/c++/include/algo/blast/composition_adjustment/composition_adjustment.h index 1178c334..592da649 100644 --- a/c++/include/algo/blast/composition_adjustment/composition_adjustment.h +++ b/c++/include/algo/blast/composition_adjustment/composition_adjustment.h @@ -1,4 +1,4 @@ -/* $Id: composition_adjustment.h 500367 2016-05-04 12:06:01Z ivanov $ +/* $Id: composition_adjustment.h 500143 2016-05-02 18:02:52Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/algo/blast/composition_adjustment/redo_alignment.h b/c++/include/algo/blast/composition_adjustment/redo_alignment.h index e1da0bfa..7b5fd46d 100644 --- a/c++/include/algo/blast/composition_adjustment/redo_alignment.h +++ b/c++/include/algo/blast/composition_adjustment/redo_alignment.h @@ -1,4 +1,4 @@ -/* $Id: redo_alignment.h 416845 2013-10-31 17:01:59Z boratyng $ +/* $Id: redo_alignment.h 505234 2016-06-23 13:16:57Z fongah2 $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -487,6 +487,19 @@ int BlastCompo_EarlyTermination(double evalue, BlastCompo_Heap significantMatches[], int numQueries); +#ifndef GET_SEQ_FRAME +#define GET_SEQ_FRAME(f) ((f<0)?ABS(f)+2: f-1) +#endif + +#ifndef GET_NUCL_LENGTH +#define GET_NUCL_LENGTH(l) ((l-5)/2 +2) +#endif + +#ifndef GET_TRANSLATED_LENGTH +#define GET_TRANSLATED_LENGTH(l,f) ((l-f% 3)/3) +#endif + + #ifdef __cplusplus } #endif diff --git a/c++/include/algo/blast/core/blast_engine.h b/c++/include/algo/blast/core/blast_engine.h index a27e703e..d464c665 100644 --- a/c++/include/algo/blast/core/blast_engine.h +++ b/c++/include/algo/blast/core/blast_engine.h @@ -1,4 +1,4 @@ -/* $Id: blast_engine.h 214207 2010-12-02 16:11:26Z maning $ +/* $Id: blast_engine.h 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -46,6 +46,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -237,6 +238,26 @@ typedef Int2 (*BlastWordFinderType) BlastInitHitList*, BlastUngappedStats*); +/** Short read mapper function pointer type */ +typedef Int2 (*JumperGappedType) + (BLAST_SequenceBlk*, + BLAST_SequenceBlk*, + BlastQueryInfo*, + LookupTableWrap*, + const BlastInitialWordParameters*, + const BlastScoringParameters*, + const BlastHitSavingParameters*, + BlastOffsetPair* offset_pairs, + MapperWordHits* mapper_wordhits, + Int4, + BlastGapAlignStruct*, + BlastInitHitList*, + BlastHSPList**, + BlastUngappedStats*, + BlastGappedStats*); + + + #ifdef __cplusplus } #endif diff --git a/c++/include/algo/blast/core/blast_gapalign.h b/c++/include/algo/blast/core/blast_gapalign.h index 8dccbf54..54a1558b 100644 --- a/c++/include/algo/blast/core/blast_gapalign.h +++ b/c++/include/algo/blast/core/blast_gapalign.h @@ -1,4 +1,4 @@ -/* $Id: blast_gapalign.h 389061 2013-02-13 14:45:04Z maning $ +/* $Id: blast_gapalign.h 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -62,6 +62,9 @@ typedef struct { } BlastGapDP; +typedef struct JumperGapAlign JumperGapAlign; + + /** Structure supporting the gapped alignment */ typedef struct BlastGapAlignStruct { Boolean positionBased; /**< Is this PSI-BLAST? */ @@ -76,6 +79,8 @@ typedef struct BlastGapAlignStruct { Int4 dp_mem_alloc; /**< current number of structures allocated */ BlastScoreBlk* sbp; /**< Pointer to the scoring information block */ Int4 gap_x_dropoff; /**< X-dropoff parameter to use */ + Int4 max_mismatches; /**< Max number of mismatches for jumper */ + Int4 mismatch_window; /**< Window sie for mismatches for jumper */ Int4 query_start; /**< query start offset of current alignment */ Int4 query_stop; /**< query end offseet of current alignment */ Int4 subject_start; /**< subject start offset current alignment */ @@ -85,6 +90,8 @@ typedef struct BlastGapAlignStruct { Int4 greedy_subject_seed_start; /**< for greedy alignments, the subject offset of the gapped start point */ Int4 score; /**< Return value: alignment score */ + + JumperGapAlign* jumper; /**< data for jumper alignment */ } BlastGapAlignStruct; /** Initializes the BlastGapAlignStruct structure diff --git a/c++/include/algo/blast/core/blast_hits.h b/c++/include/algo/blast/core/blast_hits.h index b227fff6..003dea31 100644 --- a/c++/include/algo/blast/core/blast_hits.h +++ b/c++/include/algo/blast/core/blast_hits.h @@ -1,4 +1,4 @@ -/* $Id: blast_hits.h 458579 2015-02-06 15:12:03Z fongah2 $ +/* $Id: blast_hits.h 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -49,6 +49,9 @@ extern "C" { #endif + +typedef struct SequenceOverhangs SequenceOverhangs; + /** Keeps prelim_hitlist_size and HitSavingOptions together, mostly for use by hspstream. */ typedef struct SBlastHitsParameters { @@ -103,6 +106,22 @@ typedef struct SPHIHspInfo { Int4 length; /**< Length of this pattern occurrence in subject. */ } SPHIHspInfo; +typedef struct JumperEditsBlock JumperEditsBlock; + +/** Mapping information for an HSP */ +typedef struct BlastHSPMappingInfo +{ + JumperEditsBlock* edits; /**< Information about mismatches and gaps, used + for mapping short reads */ + Uint1 left_edge; /**< Two subject bases before the alignment in the four + least significant bits and flags in most significat + bits (for RNA-seq mapping) */ + Uint1 right_edge; /** < Same as above for subject bases after the alignment + (for RNA-seq mapping) */ + Int4 flags; /**< Additional information about this HSP */ + SequenceOverhangs* subject_overhangs; /**< Unaligned subject subsequence */ +} BlastHSPMappingInfo; + /** Structure holding all information about an HSP */ typedef struct BlastHSP { Int4 score; /**< This HSP's raw score */ @@ -123,6 +142,9 @@ typedef struct BlastHSP { SPHIHspInfo* pat_info; /**< In PHI BLAST, information about this pattern match. */ Int4 num_positives; + + BlastHSPMappingInfo* map_info; + } BlastHSP; /** The structure to hold all HSPs for a given sequence after the gapped @@ -154,6 +176,7 @@ typedef struct BlastHitList { BlastHSPList** hsplist_array; /**< Array of HSP lists for individual database hits */ Int4 hsplist_current; /**< Number of allocated HSP list arrays. */ + Int4 num_hits; /**< Number of similar hits for the query (for mapping) */ } BlastHitList; /** The structure to contain all BLAST results, for multiple queries */ @@ -226,6 +249,21 @@ Blast_HSPInit(Int4 query_start, Int4 query_end, Int4 query_context, Int2 query_frame, Int2 subject_frame, Int4 score, GapEditScript* *gap_edit, BlastHSP** ret_hsp); +/** Make a deep copy of an HSP */ +NCBI_XBLAST_EXPORT +BlastHSP* +Blast_HSPClone(const BlastHSP* hsp); + +/** Deallocate memory for an HSP's additional data structure */ +NCBI_XBLAST_EXPORT +BlastHSPMappingInfo* BlastHSPMappingInfoFree(BlastHSPMappingInfo* info); + +/** Allocate memory for an HSP's additional data structure */ +NCBI_XBLAST_EXPORT +BlastHSPMappingInfo* BlastHSPMappingInfoNew(void); + + + /** Reevaluate the HSP's score and percent identity after taking * into account the ambiguity information. Used only for blastn after a greedy * gapped extension with traceback. This function can remove part of the @@ -650,6 +688,8 @@ Int2 Blast_HSPListAppend(BlastHSPList** old_hsp_list_ptr, * sequence region containing hsp_list and that * containing combined_hsp_list [in] * @param allow_gap Allow merging HSPs at different diagonals [in] + * @param short_reads Assume that queries are shorter than the database + * overlap region [in] * @return 0 if HSP lists have been merged successfully, -1 otherwise. */ NCBI_XBLAST_EXPORT @@ -658,7 +698,8 @@ Int2 Blast_HSPListsMerge(BlastHSPList** hsp_list, Int4 hsp_num_max, Int4* split_points, Int4 contexts_per_query, Int4 chunk_overlap_size, - Boolean allow_gap); + Boolean allow_gap, + Boolean short_reads); /** Adjust subject offsets in an HSP list if only part of the subject sequence * was searched. Used when long subject sequence is split into more manageable @@ -894,6 +935,63 @@ Int2 Blast_HSPResultsApplyMasklevel(BlastHSPResults *results, const BlastQueryInfo *query_info, Int4 masklevel, Int4 query_length); + +/******************************************************************************** + Mapping hits API. +********************************************************************************/ + + +/** Structre to store a spliced alignment */ +typedef struct BlastHSPChain +{ + Int4 num_hsps; /**< Number of HSPs in the chain */ + BlastHSP** hsp_array; /**< Array of pointers to HSPs */ + + Int4 query_index; /**< Index of query sequence */ + Int4 oid; /**< Oid for the subject sequence */ + Int4 score; /**< Alignment score for the chain */ + Int4 adapter; /**< Position of detected adapted sequence in + the query */ + Int4 polyA; /**< Position of PolyA seqence in the query */ + + struct BlastHSPChain* pair; /**< Pointer to mapped mate alignment for + paired short reads */ + + Int4 multiplicity; /**< Number of idependent mappings for the same + query (including this one) */ +} BlastHSPChain; + + +/** Structure that contains BLAST mapping results */ +typedef struct BlastMappingResults +{ + Int4 num_results; + BlastHSPChain** chain_array; +} BlastMappingResults; + + +/** Initialize the chain structure. + */ +NCBI_XBLAST_EXPORT +BlastHSPChain* Blast_HSPChainNew(void); + +/** Free the chain structure + * @param ch Chain to be freed + */ +NCBI_XBLAST_EXPORT +BlastHSPChain* Blast_HSPChainFree(BlastHSPChain* ch); + +/** Initialize BlastMappingResults structure + */ +NCBI_XBLAST_EXPORT +BlastMappingResults* Blast_MappingResultsNew(void); + +/** Free BlastMappingResults structure + */ +NCBI_XBLAST_EXPORT +BlastMappingResults* Blast_MappingResultsFree(BlastMappingResults* results); + + #ifdef __cplusplus } #endif diff --git a/c++/include/algo/blast/core/blast_hspfilter.h b/c++/include/algo/blast/core/blast_hspfilter.h index 6b6b79ad..7287fec2 100644 --- a/c++/include/algo/blast/core/blast_hspfilter.h +++ b/c++/include/algo/blast/core/blast_hspfilter.h @@ -1,4 +1,4 @@ -/* $Id: blast_hspfilter.h 161402 2009-05-27 17:35:47Z camacho $ +/* $Id: blast_hspfilter.h 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -48,11 +48,12 @@ extern "C" { typedef struct BlastHSPWriter BlastHSPWriter; /** Function pointer typedef to implement hsp_writer */ -typedef BlastHSPWriter* (*BlastHSPWriterNewFn) (void*, BlastQueryInfo*); +typedef BlastHSPWriter* (*BlastHSPWriterNewFn) (void*, BlastQueryInfo*, + BLAST_SequenceBlk*); typedef BlastHSPWriter* (*BlastHSPWriterFreeFn) (BlastHSPWriter*); -typedef int (*BlastHSPWriterInitFn) (void*, BlastHSPResults*); +typedef int (*BlastHSPWriterInitFn) (void*, void*); typedef int (*BlastHSPWriterRunFn) (void*, BlastHSPList*); -typedef int (*BlastHSPWriterFinalFn)(void*, BlastHSPResults*); +typedef int (*BlastHSPWriterFinalFn)(void*, void*); /** ADT definition of BlastHSPWriter */ @@ -77,7 +78,8 @@ typedef struct BlastHSPWriterInfo { */ NCBI_XBLAST_EXPORT BlastHSPWriter* -BlastHSPWriterNew(BlastHSPWriterInfo** writer_info, BlastQueryInfo *query_info); +BlastHSPWriterNew(BlastHSPWriterInfo** writer_info, BlastQueryInfo *query_info, + BLAST_SequenceBlk* query); /**--------------------------------pipe------------------------------*/ /** forwarded declarations */ diff --git a/c++/include/algo/blast/core/blast_hspstream.h b/c++/include/algo/blast/core/blast_hspstream.h index 1d763df5..1a75e898 100644 --- a/c++/include/algo/blast/core/blast_hspstream.h +++ b/c++/include/algo/blast/core/blast_hspstream.h @@ -1,4 +1,4 @@ -/* $Id: blast_hspstream.h 419225 2013-11-22 17:08:29Z camacho $ +/* $Id: blast_hspstream.h 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -146,6 +146,23 @@ BlastHSPStream* BlastHSPStreamFree(BlastHSPStream* hsp_stream); NCBI_XBLAST_EXPORT void BlastHSPStreamClose(BlastHSPStream* hsp_stream); +/** Closes the BlastHSPStream structure for writing without any sorting as done + * in BlastHSPStreamClose. Any subsequent attempt to write to the stream will + * return error. + * @param hsp_stream The stream to close [in] [out] + */ +NCBI_XBLAST_EXPORT +void BlastHSPStreamSimpleClose(BlastHSPStream* hsp_stream); + +/** Closes BlastHSPStream structure for mapping and produces + * BlastMappingResults + * @param hsp_stream The stream to close [in] [out] + * @param results The results [in] [out] +*/ +NCBI_XBLAST_EXPORT +void BlastHSPStreamMappingClose(BlastHSPStream* hsp_stream, + BlastMappingResults* results); + /** Closes the BlastHSPStream structure after traceback. * This is mainly to provide a chance to apply post-traceback pipes. * @param hsp_stream The stream to close [in] [out] diff --git a/c++/include/algo/blast/core/blast_kappa.h b/c++/include/algo/blast/core/blast_kappa.h index a7d5d5c8..f3601523 100644 --- a/c++/include/algo/blast/core/blast_kappa.h +++ b/c++/include/algo/blast/core/blast_kappa.h @@ -1,4 +1,4 @@ -/* $Id: blast_kappa.h 496008 2016-03-23 11:29:15Z ivanov $ +/* $Id: blast_kappa.h 495576 2016-03-18 14:26:46Z rackerst $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/algo/blast/core/blast_lookup.h b/c++/include/algo/blast/core/blast_lookup.h index e190cff7..79a605dd 100644 --- a/c++/include/algo/blast/core/blast_lookup.h +++ b/c++/include/algo/blast/core/blast_lookup.h @@ -1,4 +1,4 @@ -/* $Id: blast_lookup.h 103491 2007-05-04 17:18:18Z kazimird $ +/* $Id: blast_lookup.h 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -127,6 +127,57 @@ static NCBI_INLINE Int4 ComputeTableIndexIncremental(Int4 wordsize, return ((index << charsize) | word[wordsize - 1]) & mask; } + +/** Thin backbone cell for nucleotide lookup table with hashed words */ +typedef struct BackboneCell +{ + Uint4 word; + Int4* offsets; + Int4 num_offsets; + Int4 allocated; + struct BackboneCell* next; +} BackboneCell; + + +/** Hash function type for the lookup table */ +typedef Uint4 (*TNaLookupHashFunction)(Uint1*, Uint4); + + +BackboneCell* BackboneCellFree(BackboneCell* cell); + +/** Create a new cell for a given word and offset + *@param word Nucleotide word in 2na [in] + *@param offset Offset for the word [in] + *@param size Size of the offset array to be allocated [in] + */ +BackboneCell* BackboneCellNew(Uint4 word, Int4 offset, Int4 size); + + +/** Add all applicable query offsets to a hashed lookup table + * + * @param backbone The current list of hashtable cells [in][out] + * @param word_length Number of letters in a word [in] + * @param charsize Number of bits in one letter [in] + * @param lut_word_length Width of the lookup table in letters + * (must be <= word_length) [in] + * @param query The query sequence [in] + * @param locations What locations on the query sequence to index? [in] + * @param hash_func Hash function for words in 2na [in] + * @param counts Word counts in a database, to limit lookup table by databse + * word frequency [in] + */ +void BlastHashLookupIndexQueryExactMatches(BackboneCell **backbone, + Int4 word_length, + Int4 charsize, + Int4 lut_word_length, + BLAST_SequenceBlk* query, + BlastSeqLoc* locations, + TNaLookupHashFunction hash_func, + Uint4 mask, + Uint1* counts); + + + #ifdef __cplusplus } #endif diff --git a/c++/include/algo/blast/core/blast_nalookup.h b/c++/include/algo/blast/core/blast_nalookup.h index a1d27881..11c1eda9 100644 --- a/c++/include/algo/blast/core/blast_nalookup.h +++ b/c++/include/algo/blast/core/blast_nalookup.h @@ -1,4 +1,4 @@ -/* $Id: blast_nalookup.h 178819 2009-12-16 19:48:29Z maning $ +/* $Id: blast_nalookup.h 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -36,6 +36,8 @@ #include #include +#include + #ifdef __cplusplus extern "C" { #endif @@ -237,7 +239,7 @@ typedef struct BlastMBLookupTable { Int4 word_length; /**< number of exact letter matches that will trigger an ungapped extension */ Int4 lut_word_length; /**< number of letters in a lookup table word */ - Int4 hashsize; /**< = 4^(lut_word_length) */ + Int8 hashsize; /**< = 4^(lut_word_length) */ Boolean discontiguous; /**< Are discontiguous words used? */ Int4 template_length; /**< Length of the discontiguous word template */ EDiscTemplateType template_type; /**< Type of the discontiguous @@ -245,6 +247,8 @@ typedef struct BlastMBLookupTable { Boolean two_templates; /**< Use two templates simultaneously */ EDiscTemplateType second_template_type; /**< Type of the second discontiguous word template */ + + Boolean stride; /**< is lookup table created with a stride */ Int4 scan_step; /**< Step size for scanning the database */ Int4* hashtable; /**< Array of positions */ Int4* hashtable2; /**< Array of positions for second template */ @@ -262,7 +266,6 @@ typedef struct BlastMBLookupTable { Int4 num_unique_pos_added; /**< Number of positions added to the l.t. */ Int4 num_words_added; /**< Number of words added to the l.t. */ BlastSeqLoc* masked_locations; /**< masked locations, only non-NULL for soft-masking. */ - } BlastMBLookupTable; /** @@ -277,13 +280,15 @@ typedef struct BlastMBLookupTable { * @param approx_table_entries An upper bound on the number of words * that must be added to the lookup table [in] * @param lut_width The number of nucleotides in one lookup table word [in] + * @param seqsrc Database sequences [in] */ Int2 BlastMBLookupTableNew(BLAST_SequenceBlk* query, BlastSeqLoc* location, BlastMBLookupTable** mb_lt_ptr, const LookupTableOptions* lookup_options, const QuerySetUpOptions* query_options, Int4 approx_table_entries, - Int4 lut_width); + Int4 lut_width, + BlastSeqSrc* seqsrc); /** * Deallocate memory used by the Mega BLAST lookup table @@ -582,6 +587,105 @@ static NCBI_INLINE Int4 ComputeDiscontiguousIndex(Uint8 accum, return index; } +/** Find an index into a sparse array using pv_array as a bit field + * @param index Index to translate [in] + * @param pv_array Bit field (lookup table pv_array) [in] + * @param pv_array_bts Log2 of pv_array size [in] + * @param pv_counts Array of set bit counts, where pv_counts[i] is the number + * of bits set in pv_array[0..i-1] [in] + * @param words_per_bit Number of words represented by one bit in the + * pv_array [in] + * @return Index into the sparse array + */ +Int8 FindSparseIndex(Int8 index, PV_ARRAY_TYPE* pv_array, Int4 pv_array_bts, + Int4* pv_counts, Int4 words_per_bit); + + +/** Find an index into a sparse array using pv_array as a bit field, for a + * batch of indices + * @param in_array Input array of indices to translate [in] + * @param out_array Output array of indices to translate [out] + * @param length Number of indices to translate [in] + * @param pv_array Bit field (lookup table pv_array) [in] + * @param pv_array_bts Log2 of pv_array size [in] + * @param pv_counts Array of set bit counts, where pv_counts[i] is the number + * of bits set in pv_array[0..i-1] [in] + * @param words_per_bit Number of words represented by one bit in the + * pv_array [in] + * @return Index into the sparse array + */ +Int2 FindSparseIndices(Int8* NCBI_RESTRICT in_array, Int8* out_array, Int4 length, + PV_ARRAY_TYPE* pv_array, Int4 pv_array_bts, + Int4* counts, Int4 elems_per_bit); + + +/*----------------------- Hashed Na lookup table -------------------------*/ + +/** Structure defining one cell of the compacted lookup table */ +typedef struct NaHashLookupBackboneCell { + + Int1 num_words; /**< number of words stored under the same hash value */ + Int1 num_offsets[3]; /**< number of offsets for each word if there are + fewer than 3 */ + + Uint4 words[3]; /**< words stored under this hash value */ + Int4 offsets[9]; /**< offset locations for each word */ + +} NaHashLookupBackboneCell; + + +typedef struct BlastNaHashLookupTable { + Int4 mask; /**< part of index to mask off, that is, top + (wordsize*charsize) bits should be discarded. */ + Int4 word_length; /**< Length in bases of the full word match + required to trigger extension */ + Int4 lut_word_length; /**< Length in bases of a word indexed by the + lookup table */ + Int4 scan_step; /**< number of bases between successive words */ + Int4 backbone_size; /**< number of cells in the backbone */ + Int4 longest_chain; /**< length of the longest chain on the backbone */ + NaHashLookupBackboneCell * thick_backbone; /**< the "thick" backbone. after + queries are indexed, compact the + backbone to put at most + NA_HITS_PER_CELL hits on the + backbone, otherwise point to + some overflow storage */ + Int4* overflow; /**< the overflow array for the compacted + lookup table */ + Int4 offsets_size; /**< Number of elements in the overflow array */ + PV_ARRAY_TYPE *pv; /**< Presence vector bitfield; bit positions that + are set indicate that the corresponding thick + backbone cell contains hits */ + Int4 pv_array_bts; /**< power of 2 by which to divide a word to access + PV_ARRAY_TYPE element in pv array */ + void *scansub_callback; /**< function for scanning subject sequences */ + void *hash_callback; /**< hash function to be used for hash table */ + BlastSeqLoc* masked_locations; /**< masked locations, only non-NULL for + soft-masking. */ +} BlastNaHashLookupTable; + +/* Maximum number of words and offsets that can be strored in thich backbone */ +#define NA_WORDS_PER_HASH 3 +#define NA_OFFSETS_PER_HASH 9 + + +Int4 BlastNaHashLookupTableNew(BLAST_SequenceBlk* query, + BlastSeqLoc* locations, + BlastNaHashLookupTable** lut, + const LookupTableOptions* opt, + const QuerySetUpOptions* query_options, + BlastSeqSrc* seqsrc); + + +/** Free a nucleotide lookup table. + * @param lookup The lookup table structure to be freed + * @return NULL + */ +BlastNaHashLookupTable* +BlastNaHashLookupTableDestruct(BlastNaHashLookupTable* lookup); + + + #ifdef __cplusplus } #endif diff --git a/c++/include/algo/blast/core/blast_options.h b/c++/include/algo/blast/core/blast_options.h index bec10f3e..0f2e7547 100644 --- a/c++/include/algo/blast/core/blast_options.h +++ b/c++/include/algo/blast/core/blast_options.h @@ -1,4 +1,4 @@ -/* $Id: blast_options.h 456407 2015-01-12 15:47:18Z fongah2 $ +/* $Id: blast_options.h 506100 2016-07-01 15:46:25Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -70,6 +70,9 @@ extern "C" { the word size is explicitly overridden) */ +#define BLAST_WORDSIZE_MAPPER 16 /**< default word size for mapping rna-seq + to a genome */ + /** Default matrix name: BLOSUM62 */ #define BLAST_DEFAULT_MATRIX "BLOSUM62" @@ -83,6 +86,7 @@ extern "C" { #define BLAST_GAP_OPEN_NUCL 5 /**< default gap open penalty (blastn) */ #define BLAST_GAP_OPEN_MEGABLAST 0 /**< default gap open penalty (megablast with greedy gapped alignment) */ +#define BLAST_GAP_OPEN_MAPPER 0 /** cost to extend a gap. */ #define BLAST_GAP_EXTN_PROT 1 /**< default gap open penalty (all @@ -91,6 +95,8 @@ extern "C" { #define BLAST_GAP_EXTN_MEGABLAST 0 /**< default gap open penalty (megablast) with greedy gapped alignment) */ +#define BLAST_GAP_EXTN_MAPPER 8 + /** neighboring word score thresholds; a threshold of zero * means that only query and subject words that match exactly * will go into the BLAST lookup table when it is generated @@ -141,6 +147,9 @@ extern "C" { #define BLAST_PENALTY -3 /**< default nucleotide mismatch score */ #define BLAST_REWARD 1 /**< default nucleotide match score */ +#define BLAST_PENALTY_MAPPER -8 +#define BLAST_REWARD_MAPPER 1 + /** Default parameters for saving hits */ #define BLAST_EXPECT_VALUE 10.0 /**< by default, alignments whose expect value exceeds this number are discarded */ @@ -172,8 +181,9 @@ typedef enum { ePhiNaLookupTable, /**< nucleotide lookup table for phi-blast */ eRPSLookupTable, /**< RPS lookup table (rpsblast and rpstblastn) */ eIndexedMBLookupTable, /**< use database index as a lookup structure */ - eMixedMBLookupTable /**< use when some volumes are searched with index and + eMixedMBLookupTable, /**< use when some volumes are searched with index and some are not */ + eNaHashLookupTable /**< used for 16-base words */ } ELookupTableType; /** Options needed to construct a lookup table @@ -189,6 +199,11 @@ typedef struct LookupTableOptions { Int4 mb_template_type; /**< Type of a discontiguous word template */ char* phi_pattern; /**< PHI-BLAST pattern */ EBlastProgramType program_number; /**< indicates blastn, blastp, etc. */ + Uint4 stride; /**< number of words to skip after collecting each word */ + Boolean db_filter; /**< scan the database and include only words that appear + in the database between 1 and 9 times + (currently implemented only for MB lookuptable + and lookup table word size 16) */ } LookupTableOptions; /** Options for dust algorithm, applies only to nucl.-nucl. comparisons. @@ -270,6 +285,7 @@ typedef struct BlastInitialWordOptions { typedef enum EBlastPrelimGapExt { eDynProgScoreOnly, /**< standard affine gapping */ eGreedyScoreOnly, /**< Greedy extension (megaBlast) */ + eJumperWithTraceback, /**< Jumper extension (mapping) */ eSmithWatermanScoreOnly /**< Score-only smith-waterman */ } EBlastPrelimGapExt; @@ -302,6 +318,11 @@ typedef struct BlastExtensionOptions { if zero then compositional adjustment is not used */ Int4 unifiedP; /**< Indicates unified P values to be used in blastp or tblastn */ + + Int4 max_mismatches; /**< Maximum number of mismatches allowed for Jumper */ + + Int4 mismatch_window; /**< Widnow for counting mismatches for Jumper */ + EBlastProgramType program_number; /**< indicates blastn, blastp, etc. */ } BlastExtensionOptions; @@ -386,6 +407,11 @@ typedef struct BlastHitSavingOptions { */ Int4 max_hsps_per_subject; + /**< Queries are paired reads, for mapping */ + Boolean paired; + /**< Splice HSPs for each query (for mapping RNA-Seq to a genome) */ + Boolean splice; + } BlastHitSavingOptions; /** Scoring options block diff --git a/c++/include/algo/blast/core/blast_program.h b/c++/include/algo/blast/core/blast_program.h index c6ffc4f7..2859a41f 100644 --- a/c++/include/algo/blast/core/blast_program.h +++ b/c++/include/algo/blast/core/blast_program.h @@ -1,4 +1,4 @@ -/* $Id: blast_program.h 103498 2007-05-04 18:56:48Z camacho $ +/* $Id: blast_program.h 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -62,6 +62,8 @@ extern "C" { #define PSSM_SUBJECT_MASK (0x1<<7) /** This bit is on if the query includes a pattern (PHI-BLAST) */ #define PATTERN_QUERY_MASK (0x1<<8) +/** This bit is on for fast mapping of short reads */ +#define MAPPING_MASK (0x1<<9) /******************** Main BLAST program definitions ***********************/ @@ -83,6 +85,7 @@ typedef enum { eBlastTypeRpsTblastn = (PSSM_SUBJECT_MASK | eBlastTypeBlastx), eBlastTypePhiBlastp = (PATTERN_QUERY_MASK | eBlastTypeBlastp), eBlastTypePhiBlastn = (PATTERN_QUERY_MASK | eBlastTypeBlastn), + eBlastTypeMapping = (eBlastTypeBlastn | MAPPING_MASK), eBlastTypeUndefined = 0x0 } EBlastProgramType; @@ -160,12 +163,22 @@ Boolean Blast_ProgramIsPhiBlast(EBlastProgramType p); NCBI_XBLAST_EXPORT Boolean Blast_ProgramIsRpsBlast(EBlastProgramType p); +NCBI_XBLAST_EXPORT +Boolean Blast_ProgramIsMapping(EBlastProgramType p); + +NCBI_XBLAST_EXPORT +Boolean Blast_QueryIsPattern(EBlastProgramType p); + +NCBI_XBLAST_EXPORT +Boolean Blast_ProgramIsNucleotide(EBlastProgramType p); + /** Returns true if program is not undefined * @param p program type [in] */ NCBI_XBLAST_EXPORT Boolean Blast_ProgramIsValid(EBlastProgramType p); + #ifdef __cplusplus } #endif diff --git a/c++/include/algo/blast/core/blast_query_info.h b/c++/include/algo/blast/core/blast_query_info.h index 086abc67..74cc3a15 100644 --- a/c++/include/algo/blast/core/blast_query_info.h +++ b/c++/include/algo/blast/core/blast_query_info.h @@ -1,4 +1,4 @@ -/* $Id: blast_query_info.h 419225 2013-11-22 17:08:29Z camacho $ +/* $Id: blast_query_info.h 517499 2016-10-25 17:20:41Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -42,6 +42,20 @@ extern "C" { #endif +/** Information about paired segments (for mapping short reads) + */ +typedef enum EMagicBlastSegmentInfo { + eNoSegments = 0, /**< Sequence is not part of a pair */ + fFirstSegmentFlag = 1, /**< The first sequence of a pair */ + fLastSegmentFlag = 1 << 1, /**< The last sequence of a pair */ + fPartialFlag = 1 << 2, /**< The other segment is not present (did not + pass quality filtering */ + eFirstSegment = fFirstSegmentFlag, /**< The first sequence of a pair with + both sequences read and accepted */ + eLastSegment = fLastSegmentFlag /** The last sequence of a pair with + both sequences read and accepted */ +} EMagicBlastSegmentInfo; + /** The context related information */ typedef struct BlastContextInfo { Int4 query_offset; /**< Offset of this query, strand or frame in the @@ -55,6 +69,7 @@ typedef struct BlastContextInfo { This field should be set only by the setup code and read by subsequent stages of the BLAST search */ + Int4 segment_flags; /**< Flags describing segments for paired reads */ } BlastContextInfo; /** Forward declaration of SPHIQueryInfo */ @@ -69,6 +84,8 @@ typedef struct BlastQueryInfo { BlastContextInfo * contexts; /**< Information per context */ Uint4 max_length; /**< Length of the longest among the concatenated queries */ + Uint4 min_length; /**< Length of the shortest among the concatenated + queries */ struct SPHIQueryInfo* pattern_info; /**< Counts of PHI BLAST pattern occurrences, used in PHI BLAST only. */ } BlastQueryInfo; diff --git a/c++/include/algo/blast/core/blast_stat.h b/c++/include/algo/blast/core/blast_stat.h index 0b554f0a..ae7b9025 100644 --- a/c++/include/algo/blast/core/blast_stat.h +++ b/c++/include/algo/blast/core/blast_stat.h @@ -1,4 +1,4 @@ -/* $Id: blast_stat.h 496008 2016-03-23 11:29:15Z ivanov $ +/* $Id: blast_stat.h 495576 2016-03-18 14:26:46Z rackerst $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/algo/blast/core/hspfilter_mapper.h b/c++/include/algo/blast/core/hspfilter_mapper.h new file mode 100644 index 00000000..f4ac1ca8 --- /dev/null +++ b/c++/include/algo/blast/core/hspfilter_mapper.h @@ -0,0 +1,101 @@ +/* $Id: hspfilter_mapper.h 504861 2016-06-20 15:45:40Z boratyng $ + * =========================================================================== + * + * PUBLIC DOMAIN NOTICE + * National Center for Biotechnology Information + * + * This software/database is a "United States Government Work" under the + * terms of the United States Copyright Act. It was written as part of + * the author's official duties as a United States Government employee and + * thus cannot be copyrighted. This software/database is freely available + * to the public for use. The National Library of Medicine and the U.S. + * Government have not placed any restriction on its use or reproduction. + * + * Although all reasonable efforts have been taken to ensure the accuracy + * and reliability of the software and data, the NLM and the U.S. + * Government do not and cannot warrant the performance or results that + * may be obtained by using this software or data. The NLM and the U.S. + * Government disclaim all warranties, express or implied, including + * warranties of performance, merchantability or fitness for any particular + * purpose. + * + * Please cite the author in any work or product based on this material. + * + * =========================================================================== + * + * Author: Greg Boratyn + * + */ + +/** @file hspfilter_mapper.h + * Implementation of a number of BlastHSPWriters to save the best chain + * of RNA-Seq hits to a genome. + */ + +#ifndef ALGO_BLAST_CORE__HSPFILTER_MAPSPLICED__H +#define ALGO_BLAST_CORE__HSPFILTER_MAPSPLICED__H + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct ScoringOptions +{ + Int4 reward; + Int4 penalty; + Int4 gap_open; + Int4 gap_extend; + /* score for lack of splice signal */ + Int4 no_splice_signal; +} ScoringOptions; + +/** Keeps prelim_hitlist_size and HitSavingOptions together. */ +typedef struct BlastHSPMapperParams { + EBlastProgramType program;/**< program type */ + ScoringOptions scoring_options; /**< scores for match, mismatch, and gap */ + Int4 hitlist_size; /**< number of hits saved during preliminary + part of search. */ + Boolean paired; /**< mapping with paired reads */ + Boolean splice; /**< mapping spliced reads (RNA-seq to a genome) */ +} BlastHSPMapperParams; + +/** Sets up parameter set for use by collector. + * @param hit_options field hitlist_size and hsp_num_max needed, a pointer to + * this structure will be stored on resulting structure.[in] + * @param scoring_options needed for mismatch and gap penalties, the pointer + * will be stored [in] + * @return the pointer to the allocated parameter + */ +NCBI_XBLAST_EXPORT +BlastHSPMapperParams* +BlastHSPMapperParamsNew(const BlastHitSavingOptions* hit_options, + const BlastScoringOptions* scoring_options); + +/** Deallocates the BlastHSPMapperParams structure passed in + * @param opts structure to deallocate [in] + * @return NULL + */ +NCBI_XBLAST_EXPORT +BlastHSPMapperParams* +BlastHSPMapperParamsFree(BlastHSPMapperParams* opts); + +/** WriterInfo to create a default writer: the collecter + * @param params The collector parameters. + * @return pointer to WriterInfo + */ +NCBI_XBLAST_EXPORT +BlastHSPWriterInfo* +BlastHSPMapperInfoNew(BlastHSPMapperParams* params); + +#ifdef __cplusplus +} +#endif + +#endif /* !ALGO_BLAST_CORE__HSPFILTER_SPLICED__H */ diff --git a/c++/include/algo/blast/core/lookup_util.h b/c++/include/algo/blast/core/lookup_util.h index 60391d8b..186634a6 100644 --- a/c++/include/algo/blast/core/lookup_util.h +++ b/c++/include/algo/blast/core/lookup_util.h @@ -1,4 +1,4 @@ -/* $Id: lookup_util.h 144893 2008-11-04 19:56:45Z ivanov $ +/* $Id: lookup_util.h 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -57,7 +57,7 @@ Int4 iexp(Int4 x, Int4 n); */ NCBI_XBLAST_EXPORT -Int4 ilog2(Int4 x); +Int4 ilog2(Int8 x); /** * generates a de Bruijn sequence containing all substrings diff --git a/c++/include/algo/blast/core/lookup_wrap.h b/c++/include/algo/blast/core/lookup_wrap.h index d08b6099..d983b4e0 100644 --- a/c++/include/algo/blast/core/lookup_wrap.h +++ b/c++/include/algo/blast/core/lookup_wrap.h @@ -1,4 +1,4 @@ -/* $Id: lookup_wrap.h 369355 2012-07-18 17:07:15Z morgulis $ +/* $Id: lookup_wrap.h 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -40,6 +40,8 @@ #include #include +#include + #ifdef __cplusplus extern "C" { #endif @@ -73,6 +75,7 @@ typedef Boolean (*T_Lookup_Callback)(const LookupTableWrap *, Int4, Int4); * @param lookup_wrap_ptr The initialized lookup table [out] * @param rps_info Structure containing RPS blast setup information [in] * @param error_msg message with warning or errors [in|out] + * @param seqsrc Database sequences [in] */ NCBI_XBLAST_EXPORT Int2 LookupTableWrapInit(BLAST_SequenceBlk* query, @@ -80,7 +83,8 @@ Int2 LookupTableWrapInit(BLAST_SequenceBlk* query, const QuerySetUpOptions* query_options, BlastSeqLoc* lookup_segments, BlastScoreBlk* sbp, LookupTableWrap** lookup_wrap_ptr, const BlastRPSInfo *rps_info, - Blast_Message* *error_msg); + Blast_Message* *error_msg, + BlastSeqSrc* seqsrc); /** Deallocate memory for the lookup table */ NCBI_XBLAST_EXPORT diff --git a/c++/include/algo/blast/core/na_ungapped.h b/c++/include/algo/blast/core/na_ungapped.h index 875fd861..bbbb5158 100644 --- a/c++/include/algo/blast/core/na_ungapped.h +++ b/c++/include/algo/blast/core/na_ungapped.h @@ -1,4 +1,4 @@ -/* $Id: na_ungapped.h 172278 2009-10-02 15:19:28Z maning $ +/* $Id: na_ungapped.h 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -43,6 +43,8 @@ #include #include +#include + #ifdef __cplusplus extern "C" { #endif @@ -95,6 +97,67 @@ Int2 BlastNaWordFinder(BLAST_SequenceBlk* subject, NCBI_XBLAST_EXPORT void BlastChooseNaExtend(LookupTableWrap *lookup_wrap); + +/* A structure to hold several lists of word hits for groups of queries */ +typedef struct MapperWordHits +{ + BlastOffsetPair** pair_arrays; /**< lists of word hits */ + Int4* num; /**< number of hits in the list */ + Int4 num_arrays; /**< number of pair_arrays */ + Int4 array_size; /**< size of each array */ + Int4* last_diag; /**< diagnal for the last word hit for each + query context */ + Int4* last_pos; /**< subject position for the last word hit + for each query context */ + + Int4 divisor; /**< divisor used to find pair_arrays index + based on query offset */ +} MapperWordHits; + +MapperWordHits* MapperWordHitsFree(MapperWordHits* wh); +MapperWordHits* MapperWordHitsNew(const BLAST_SequenceBlk* query, + const BlastQueryInfo* query_info); + + +NCBI_XBLAST_EXPORT +Int2 +JumperNaWordFinder(BLAST_SequenceBlk * subject, + BLAST_SequenceBlk * query, + BlastQueryInfo * query_info, + LookupTableWrap * lookup_wrap, + const BlastInitialWordParameters * word_params, + const BlastScoringParameters* score_params, + const BlastHitSavingParameters* hit_params, + BlastOffsetPair * offset_pairs, + MapperWordHits* word_hits, + Int4 max_hits, + BlastGapAlignStruct* gap_align, + BlastInitHitList* init_hitlist, + BlastHSPList** hsp_list_ptr, + BlastUngappedStats * ungapped_stats, + BlastGappedStats* gapped_stats); + + +NCBI_XBLAST_EXPORT +Int2 ShortRead_IndexedWordFinder( + BLAST_SequenceBlk * subject, + BLAST_SequenceBlk * query, + BlastQueryInfo * query_info, + LookupTableWrap * lookup_wrap, + const BlastInitialWordParameters * word_params, + const BlastScoringParameters* score_params, + const BlastHitSavingParameters* hit_params, + BlastOffsetPair * offset_pairs, + MapperWordHits* word_hits, + Int4 max_hits, + BlastGapAlignStruct* gap_align, + BlastInitHitList* init_hitlist, + BlastHSPList** hsp_list, + BlastUngappedStats* ungapped_stats, + BlastGappedStats* gapped_stats); + + + #ifdef __cplusplus } #endif diff --git a/c++/include/algo/blast/format/blast_format.hpp b/c++/include/algo/blast/format/blast_format.hpp index bc8bb469..1f1a3f86 100644 --- a/c++/include/algo/blast/format/blast_format.hpp +++ b/c++/include/algo/blast/format/blast_format.hpp @@ -1,4 +1,4 @@ -/* $Id: blast_format.hpp 495288 2016-03-16 14:51:11Z ivanov $ +/* $Id: blast_format.hpp 513847 2016-09-15 17:36:25Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -47,6 +47,7 @@ Author: Jason Papadopoulos #include #include #include +#include #include #include #include @@ -55,16 +56,35 @@ Author: Jason Papadopoulos #include #include -BEGIN_NCBI_SCOPE +BEGIN_NCBI_SCOPE +USING_SCOPE(align_format); class CCmdLineBlastXML2ReportData; /// This class formats the BLAST results for command line applications class NCBI_XBLASTFORMAT_EXPORT CBlastFormat { public: - /// The line length of pairwise blast output - static const int kFormatLineLength = 68; + + ///igblast clone info + struct SClone { + string na; + string chain_type; + string aa; + string v_gene; + string d_gene; + string j_gene; + string seqid; + double identity; + string productive; + }; + + + enum { + /// The line length of pairwise blast output + kFormatLineLength = 68, + kMinTaxFormatLineLength = 100 + }; /// Constructor /// @param opts BLAST options used in the search [in] @@ -208,6 +228,8 @@ public: /// @param result position index if index >= 0 [in] void PrintOneResultSet(blast::CIgBlastResults& results, CConstRef queries, + SClone& clone_info, + bool fill_clone_info, int index = -1); /// Print all alignment information for aa PHI-BLAST run. @@ -367,6 +389,9 @@ private: string m_Cmdline; + /// If true, print long sequence ids (database|accession) + bool m_LongSeqId; + /// Output the ancillary data for one query that was searched /// @param summary The ancillary data to report [in] void x_PrintOneQueryFooter(const blast::CBlastAncillaryData& summary); @@ -428,7 +453,9 @@ private: /// Prints IgTabular report for one query /// @param results Results for one query or Phi-blast iteration [in] - void x_PrintIgTabularReport(const blast::CIgBlastResults& results); + void x_PrintIgTabularReport(const blast::CIgBlastResults& results, + SClone& clone_info, + bool fill_clone_info); /// Replace the query with its reversed-compliement /// @param results Ig Blast results [in, out] @@ -458,6 +485,7 @@ private: void x_WriteXML2(CCmdLineBlastXML2ReportData & report_data); void x_InitSAMFormatter(); + void x_PrintTaxReport(const blast::CSearchResults& results); }; END_NCBI_SCOPE diff --git a/c++/include/algo/blast/igblast/igblast.hpp b/c++/include/algo/blast/igblast/igblast.hpp index 0700193d..c5863c5e 100644 --- a/c++/include/algo/blast/igblast/igblast.hpp +++ b/c++/include/algo/blast/igblast/igblast.hpp @@ -1,4 +1,4 @@ -/* $Id: igblast.hpp 499246 2016-04-25 11:32:24Z ivanov $ +/* $Id: igblast.hpp 514854 2016-09-26 17:24:36Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -79,6 +79,7 @@ public: bool m_Translate; // should translation be displayed bool m_ExtendAlign; int m_MinVLength; + int m_MinJLength; }; class CIgAnnotation : public CObject @@ -330,7 +331,7 @@ private: /// Append annotation info to the final results - static void s_SetAnnotation(vector > &annot, + void x_SetAnnotation(vector > &annot, CRef &final_results); void x_FindDJ(CRef& results_D, @@ -354,7 +355,7 @@ private: bool va_or_vd_as_heavy_chain); void x_ExtendAlign(CRef & results); - void x_ScreenV(CRef & results); + void x_ScreenByAlignLength(CRef & results, int length); void x_FillJDomain(CRef & align, CRef & annot); }; diff --git a/c++/include/cgi/cgi_session.hpp b/c++/include/cgi/cgi_session.hpp index 667dc00a..5297bd5a 100644 --- a/c++/include/cgi/cgi_session.hpp +++ b/c++/include/cgi/cgi_session.hpp @@ -1,7 +1,7 @@ #ifndef CGI___SESSION__HPP #define CGI___SESSION__HPP -/* $Id: cgi_session.hpp 497377 2016-04-06 13:21:42Z ivanov $ +/* $Id: cgi_session.hpp 497034 2016-04-04 12:46:26Z dicuccio $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/cgi/cgiapp.hpp b/c++/include/cgi/cgiapp.hpp index c5679fb8..a5e35b27 100644 --- a/c++/include/cgi/cgiapp.hpp +++ b/c++/include/cgi/cgiapp.hpp @@ -1,7 +1,7 @@ #ifndef CGI___CGIAPP__HPP #define CGI___CGIAPP__HPP -/* $Id: cgiapp.hpp 497377 2016-04-06 13:21:42Z ivanov $ +/* $Id: cgiapp.hpp 497034 2016-04-04 12:46:26Z dicuccio $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/cgi/cgictx.hpp b/c++/include/cgi/cgictx.hpp index fe6d312c..8325ac17 100644 --- a/c++/include/cgi/cgictx.hpp +++ b/c++/include/cgi/cgictx.hpp @@ -1,7 +1,7 @@ #ifndef NCBI_CGI_CTX__HPP #define NCBI_CGI_CTX__HPP -/* $Id: cgictx.hpp 433624 2014-04-28 15:39:19Z grichenk $ +/* $Id: cgictx.hpp 500790 2016-05-09 11:30:33Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -203,7 +203,7 @@ public: /// SCHEME://SERVER_NAME[:SERVER_PORT]/SCRIPT_NAME /// @deprecated The flag is ignored, use GetSelfURL(void). NCBI_DEPRECATED - const string& GetSelfURL(ESelfUrlPort use_port) const + const string& GetSelfURL(ESelfUrlPort /*use_port*/) const { return GetSelfURL(); } /// Using HTTP environment variables, compose the CGI's own URL as: diff --git a/c++/include/cgi/error_codes.hpp b/c++/include/cgi/error_codes.hpp index 2bc55094..c8d0ef64 100644 --- a/c++/include/cgi/error_codes.hpp +++ b/c++/include/cgi/error_codes.hpp @@ -1,7 +1,7 @@ #ifndef CGI___ERROR_CODES__HPP #define CGI___ERROR_CODES__HPP -/* $Id: error_codes.hpp 492269 2016-02-16 15:24:58Z ivanov $ +/* $Id: error_codes.hpp 491685 2016-02-08 18:39:43Z grichenk $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/cgi/ncbicgi.hpp b/c++/include/cgi/ncbicgi.hpp index fe18bbdc..a262af45 100644 --- a/c++/include/cgi/ncbicgi.hpp +++ b/c++/include/cgi/ncbicgi.hpp @@ -1,7 +1,7 @@ #ifndef CGI___NCBICGI__HPP #define CGI___NCBICGI__HPP -/* $Id: ncbicgi.hpp 497377 2016-04-06 13:21:42Z ivanov $ +/* $Id: ncbicgi.hpp 497034 2016-04-04 12:46:26Z dicuccio $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/cgi/ncbicgir.hpp b/c++/include/cgi/ncbicgir.hpp index ce94d9e8..54c85f94 100644 --- a/c++/include/cgi/ncbicgir.hpp +++ b/c++/include/cgi/ncbicgir.hpp @@ -1,7 +1,7 @@ #ifndef CGI___NCBICGIR__HPP #define CGI___NCBICGIR__HPP -/* $Id: ncbicgir.hpp 492270 2016-02-16 15:25:22Z ivanov $ +/* $Id: ncbicgir.hpp 500790 2016-05-09 11:30:33Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -348,7 +348,7 @@ inline void CCgiResponse::SetLocation(const CUrl& url, const IUrlEncoder* encoder) { SetHeaderValue(sm_LocationName, - url.ComposeUrl(CCgiArgs::eAmp_Char, encoder)); + url.ComposeUrl(CUrlArgs::eAmp_Char, encoder)); } inline void CCgiResponse::SetMultipartMode(EMultipartMode mode) @@ -363,7 +363,7 @@ inline CCgiResponse::EMultipartMode CCgiResponse::GetMultipartMode(void) } inline void CCgiResponse::BeginPart(const string& name, const string& type, - size_t size) + size_t /*size*/) { BeginPart(name, type, out()); } diff --git a/c++/include/cgi/user_agent.hpp b/c++/include/cgi/user_agent.hpp index aee40b1d..d10ed173 100644 --- a/c++/include/cgi/user_agent.hpp +++ b/c++/include/cgi/user_agent.hpp @@ -1,7 +1,7 @@ #ifndef CGI___USER_AGENT__HPP #define CGI___USER_AGENT__HPP -/* $Id: user_agent.hpp 466541 2015-05-04 14:38:31Z ivanov $ +/* $Id: user_agent.hpp 514810 2016-09-26 15:28:00Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -97,7 +97,9 @@ public: eLynx, ///< Lynx (lynx.browser.org) eNetscape, ///< Netscape (Navigator), versions >=6 are Gecko-based (www.netscape.com) eOpera, ///< Opera (www.opera.com) - eOregano, ///< Oregano (www.castle.org.uk/oregano/) + eOregano, ///< Oregano (www.castle.org.uk/oregano) + ePapers, ///< Papers (papersapp.com) + eUCBrowser, ///< UC Browser (www.ucweb.com/ucbrowser) eW3m, ///< w3m (www.w3m.org) eNagios, ///< check_http/nagios-plugins (nagiosplugins.org) diff --git a/c++/include/common/config/ncbiconf_msvc_site.h b/c++/include/common/config/ncbiconf_msvc_site.h deleted file mode 100644 index c9d5e761..00000000 --- a/c++/include/common/config/ncbiconf_msvc_site.h +++ /dev/null @@ -1,35 +0,0 @@ -/* $Id: ncbiconf_msvc_site.h 125306 2008-04-22 13:29:11Z gouriano $ -* =========================================================================== -* -* PUBLIC DOMAIN NOTICE -* National Center for Biotechnology Information -* -* This software/database is a "United States Government Work" under the -* terms of the United States Copyright Act. It was written as part of -* the author's official duties as a United States Government employee and -* thus cannot be copyrighted. This software/database is freely available -* to the public for use. The National Library of Medicine and the U.S. -* Government have not placed any restriction on its use or reproduction. -* -* Although all reasonable efforts have been taken to ensure the accuracy -* and reliability of the software and data, the NLM and the U.S. -* Government do not and cannot warrant the performance or results that -* may be obtained by using this software or data. The NLM and the U.S. -* Government disclaim all warranties, express or implied, including -* warranties of performance, merchantability or fitness for any particular -* purpose. -* -* Please cite the author in any work or product based on this material. -* -* =========================================================================== -* -* Author: Andrei Gourianov -* -* File Description: -* -* This file is a PLACEHOLDER ONLY -* -* REAL file with the same name is generated by -* project_tree_builder.exe when configuring the toolkit. -* -*/ diff --git a/c++/include/common/config/ncbiconf_universal.h b/c++/include/common/config/ncbiconf_universal.h index e901d265..a92303c4 100644 --- a/c++/include/common/config/ncbiconf_universal.h +++ b/c++/include/common/config/ncbiconf_universal.h @@ -1,7 +1,7 @@ #ifndef NCBICONF_UNIVERSAL_H #define NCBICONF_UNIVERSAL_H -/* $Id: ncbiconf_universal.h 487459 2015-12-17 18:57:21Z ucko $ +/* $Id: ncbiconf_universal.h 509096 2016-08-03 11:33:41Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -31,7 +31,8 @@ */ /** @file ncbiconf_universal.h - ** Architecture-specific settings for universal builds. + ** Architecture-specific settings for Xcode builds + ** (and, historically, universal builds). **/ #ifdef NCBI_OS_DARWIN diff --git a/c++/include/common/config/ncbiconf_xcode.h b/c++/include/common/config/ncbiconf_xcode.h index 32522468..857a2591 100644 --- a/c++/include/common/config/ncbiconf_xcode.h +++ b/c++/include/common/config/ncbiconf_xcode.h @@ -1,4 +1,4 @@ -/* $Id: ncbiconf_xcode.h 487685 2015-12-19 23:48:10Z ucko $ +/* $Id: ncbiconf_xcode.h 509096 2016-08-03 11:33:41Z ivanov $ * By Vlad Lebedev, NCBI (lebedev@ncbi.nlm.nih.gov) * * Mac OS X - xCode Build @@ -110,6 +110,9 @@ /* Define to 1 if necessary to get FIONBIO (e.g., on Solaris) */ /* #undef BSD_COMP */ +/* Define to 1 if you have the header file. */ +#define HAVE_ACCELERATE_ACCELERATE_H 1 + /* Define to 1 if you have the `alarm' function. */ #define HAVE_ALARM 1 @@ -147,6 +150,9 @@ /* Define to 1 if the `Boost.Threads' library is available. */ /* #undef HAVE_BOOST_THREAD */ +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CLAPACK_H */ + /* Define to 1 if the preprocessor supports GNU-style variadic macros. */ #define HAVE_CPP_GNU_VARARGS 1 @@ -270,6 +276,12 @@ /* Define to 1 if you have `ios(_base)::register_callback'. */ #define HAVE_IOS_REGISTER_CALLBACK 1 +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LAPACKE_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LAPACKE_LAPACKE_H */ + /* Define to 1 if you have the `lchown' function. */ /* #undef HAVE_LCHOWN */ @@ -314,6 +326,9 @@ the standard libraries. */ /* #undef HAVE_LIBKSTAT */ +/* Define to 1 if liblapack is available. */ +#define HAVE_LIBLAPACK 1 + /* Define to 1 if liblzo2 is available. */ /* #undef HAVE_LIBLZO */ @@ -643,6 +658,9 @@ /* Define to 1 if wxWidgets is available. */ /* #undef HAVE_WXWIDGETS */ +/* Define to 1 if the system has the type `__CLPK_integer'. */ +#define HAVE___CLPK_INTEGER 1 + /* Define as const if the declaration of iconv() needs const. */ #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 /* MAC_OS_X_VERSION_10_5 */ # define ICONV_CONST @@ -702,11 +720,6 @@ variables, or leave undefined if it doesn't. */ /* #undef NCBI_TLS_VAR */ -/* Define to 1 if building universal (multi-architecture) binaries. */ -/* (Not necessarily the case, but we shouldn't hardcode anything - * PowerPC-specific either.) */ -#define NCBI_UNIVERSAL_BUILD 1 - /* Define to 1 if prototypes can use exception specifications. */ #define NCBI_USE_THROW_SPEC 1 @@ -754,3 +767,6 @@ * Site localization */ #include + +/* Architecture specifics */ +#include diff --git a/c++/include/common/config/ncbiconf_xcode_site.h b/c++/include/common/config/ncbiconf_xcode_site.h deleted file mode 100644 index eb054bf8..00000000 --- a/c++/include/common/config/ncbiconf_xcode_site.h +++ /dev/null @@ -1,123 +0,0 @@ -/* $Id: ncbiconf_xcode_site.h 381201 2012-11-20 14:30:39Z ucko $ -* =========================================================================== -* -* PUBLIC DOMAIN NOTICE -* National Center for Biotechnology Information -* -* This software/database is a "United States Government Work" under the -* terms of the United States Copyright Act. It was written as part of -* the author's official duties as a United States Government employee and -* thus cannot be copyrighted. This software/database is freely available -* to the public for use. The National Library of Medicine and the U.S. -* Government have not placed any restriction on its use or reproduction. -* -* Although all reasonable efforts have been taken to ensure the accuracy -* and reliability of the software and data, the NLM and the U.S. -* Government do not and cannot warrant the performance or results that -* may be obtained by using this software or data. The NLM and the U.S. -* Government disclaim all warranties, express or implied, including -* warranties of performance, merchantability or fitness for any particular -* purpose. -* -* Please cite the author in any work or product based on this material. -* -* =========================================================================== -* -* Author: Andrei Gourianov -* -* File Description: -* -* Mac OS X - xCode Build -* -* When configuring the toolkit, project_tree_builder application -* generates another file with the same name -* -*/ - -/* Define to 1 if NCBI C++ API for BerkeleyDB is available. */ -#define HAVE_BDB 1 - -/* Define to 1 if NCBI C++ API for BerkeleyDB based data cache is available. - */ -#define HAVE_BDB_CACHE 1 - -/* Define to 1 if Berkeley DB libraries are available. */ -#define HAVE_BERKELEY_DB 1 - -/* Define to 1 if the `Boost.Test' libraries are available. */ -/* #undef HAVE_BOOST_TEST */ - -/* Define to 1 if CPPUNIT libraries are available. */ -/* #undef HAVE_CPPUNIT */ - -/* Define to 1 if you have the `FCGX_Accept_r' function. */ -/* #undef HAVE_FCGX_ACCEPT_R */ - -/* Define to 1 if ICU libraries are available. */ -/* #undef HAVE_ICU */ - -/* Define to 1 if non-public CONNECT extensions are available. */ -/* #undef HAVE_LIBCONNEXT */ - -/* Define to 1 if FastCGI libraries are available. */ -/* #undef HAVE_LIBFASTCGI */ - -/* Define to 1 if libgif is available. */ -//#define HAVE_LIBGIF 1 - -/* Define to 1 if libjpeg is available. */ -#define HAVE_LIBJPEG 1 - -/* Define to 1 if liblzo is available. */ -/* #undef HAVE_LIBLZO */ - -/* Define to 1 if libssl is available. */ -/* #undef HAVE_LIBOPENSSL */ - -/* Define to 1 if libpng is available. */ -#define HAVE_LIBPNG 1 - -/* Define to 1 if libsqlite3 is available. */ -/* #undef HAVE_LIBSQLITE3 */ - -/* Define to 1 if SYBASE libraries are available. */ -/* #undef HAVE_LIBSYBASE */ - -/* Define to 1 if libtiff is available. */ -#define HAVE_LIBTIFF 1 - -/* Define to 1 if libxml2 is available. */ -/* #undef HAVE_LIBXML */ - -/* Define to 1 if libxslt is available. */ -/* #undef HAVE_LIBXSLT */ - -/* Define to 1 if MySQL is available. */ -/* #undef HAVE_MYSQL */ - -/* Define to 1 if ODBC libraries are available. */ -/* #undef HAVE_ODBC */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_ODBCSS_H */ - -/* Define to 1 if you have OpenGL (-lGL). */ -#define HAVE_OPENGL 1 - -/* Define to 1 if the PUBSEQ service is available. */ -/* #undef HAVE_PUBSEQ_OS */ - -/* Define to 1 if Python libraries are available. */ -/* #undef HAVE_PYTHON */ - -/* Define to 1 if Xalan-C++ is available. */ -/* #undef HAVE_XALAN */ - -/* Define to 1 if Xerces-C++ is available. */ -/* #undef HAVE_XERCES */ - -/* Define to 1 if using a local copy of bzlib. */ -/* #undef USE_LOCAL_BZLIB */ - -/* Define to 1 if using a local copy of PCRE. */ -#define USE_LOCAL_PCRE 1 diff --git a/c++/include/common/ncbi_build_ver.h.in b/c++/include/common/ncbi_build_ver.h.in new file mode 100644 index 00000000..c986400d --- /dev/null +++ b/c++/include/common/ncbi_build_ver.h.in @@ -0,0 +1,37 @@ +/* $Id: ncbi_build_ver.h.in 513308 2016-09-09 12:04:16Z ivanov $ + * =========================================================================== + * + * PUBLIC DOMAIN NOTICE + * National Center for Biotechnology Information + * + * This software/database is a "United States Government Work" under the + * terms of the United States Copyright Act. It was written as part of + * the author's official duties as a United States Government employee and + * thus cannot be copyrighted. This software/database is freely available + * to the public for use. The National Library of Medicine and the U.S. + * Government have not placed any restriction on its use or reproduction. + * + * Although all reasonable efforts have been taken to ensure the accuracy + * and reliability of the software and data, the NLM and the U.S. + * Government do not and cannot warrant the performance or results that + * may be obtained by using this software or data. The NLM and the U.S. + * Government disclaim all warranties, express or implied, including + * warranties of performance, merchantability or fitness for any particular + * purpose. + * + * Please cite the author in any work or product based on this material. + * + * =========================================================================== + */ + +#if @NCBI_TEAMCITY_BUILD_NUMBER@ != 0 +# define NCBI_TEAMCITY_BUILD_NUMBER @NCBI_TEAMCITY_BUILD_NUMBER@ +#endif + +#if @NCBI_SUBVERSION_REVISION@ != 0 +# define NCBI_SUBVERSION_REVISION @NCBI_SUBVERSION_REVISION@ +#endif + +#if @NCBI_SC_VERSION@ != 0 +# define NCBI_SC_VERSION @NCBI_SC_VERSION@ +#endif diff --git a/c++/include/common/ncbi_export.h b/c++/include/common/ncbi_export.h index f4cc8b31..97ab0d79 100644 --- a/c++/include/common/ncbi_export.h +++ b/c++/include/common/ncbi_export.h @@ -1,7 +1,7 @@ #ifndef COMMON___NCBI_EXPORT__H #define COMMON___NCBI_EXPORT__H -/* $Id: ncbi_export.h 480275 2015-09-29 15:35:34Z vasilche $ +/* $Id: ncbi_export.h 498832 2016-04-19 21:18:13Z vasilche $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -1445,6 +1445,23 @@ #endif +/* Export specifier for library ncbi_xloader_snp + */ +#ifdef NCBI_XLOADER_SNP_EXPORTS +# define NCBI_XLOADER_SNP_EXPORT NCBI_DLL_EXPORT +#else +# define NCBI_XLOADER_SNP_EXPORT NCBI_DLL_IMPORT +#endif + + +/* Export specifier for library ncbi_id2proc_snp + */ +#ifdef NCBI_ID2PROC_SNP_EXPORTS +# define NCBI_ID2PROC_SNP_EXPORT NCBI_DLL_EXPORT +#else +# define NCBI_ID2PROC_SNP_EXPORT NCBI_DLL_IMPORT +#endif + /* STATIC LIBRARIES SECTION */ /* This section is for static-only libraries */ diff --git a/c++/include/common/ncbi_package_ver.h b/c++/include/common/ncbi_package_ver.h index ef342a38..c4b937c4 100644 --- a/c++/include/common/ncbi_package_ver.h +++ b/c++/include/common/ncbi_package_ver.h @@ -7,7 +7,7 @@ #define NCBI_PACKAGE 1 #define NCBI_PACKAGE_NAME "blast" #define NCBI_PACKAGE_VERSION_MAJOR 2 -#define NCBI_PACKAGE_VERSION_MINOR 4 +#define NCBI_PACKAGE_VERSION_MINOR 6 #define NCBI_PACKAGE_VERSION_PATCH 0 #define NCBI_PACKAGE_CONFIG "" diff --git a/c++/include/common/ncbi_source_ver.h b/c++/include/common/ncbi_source_ver.h index c0b214e1..0c86e107 100644 --- a/c++/include/common/ncbi_source_ver.h +++ b/c++/include/common/ncbi_source_ver.h @@ -1,4 +1,4 @@ -/* $Id: ncbi_source_ver.h 498533 2016-04-16 04:03:05Z syncbot $ +/* $Id: ncbi_source_ver.h 510638 2016-08-14 02:48:40Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -24,5 +24,11 @@ * =========================================================================== */ -#define NCBI_PRODUCTION_VER 20160416 -#define NCBI_DEVELOPMENT_VER 20160127 +#include + +#define NCBI_PRODUCTION_VER 20160806 +#define NCBI_DEVELOPMENT_VER 20160726 + +#ifdef HAVE_COMMON_NCBI_BUILD_VER_H +# include +#endif diff --git a/c++/include/common/ncbiconf_impl.h b/c++/include/common/ncbiconf_impl.h index bdd3d14b..e7a0f9d8 100644 --- a/c++/include/common/ncbiconf_impl.h +++ b/c++/include/common/ncbiconf_impl.h @@ -1,7 +1,7 @@ #ifndef COMMON___NCBICONF_IMPL__H #define COMMON___NCBICONF_IMPL__H -/* $Id: ncbiconf_impl.h 469886 2015-06-09 18:23:33Z ucko $ +/* $Id: ncbiconf_impl.h 491618 2016-02-08 14:08:15Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/connect/impl/server_connection.hpp b/c++/include/connect/impl/server_connection.hpp index a8920d6c..de4bcdf8 100644 --- a/c++/include/connect/impl/server_connection.hpp +++ b/c++/include/connect/impl/server_connection.hpp @@ -1,7 +1,7 @@ #ifndef CONNECT___SERVER_CONNECTION__HPP #define CONNECT___SERVER_CONNECTION__HPP -/* $Id: server_connection.hpp 462064 2015-03-16 14:27:31Z satskyse $ +/* $Id: server_connection.hpp 506707 2016-07-11 15:26:50Z satskyse $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -139,6 +139,7 @@ public: } } virtual void Passivate(void) { Close(); } + unsigned short GetPort(void) const { return m_Port; } private: friend class CAcceptRequest; auto_ptr m_Factory; diff --git a/c++/include/connect/impl/thread_pool_for_server.hpp b/c++/include/connect/impl/thread_pool_for_server.hpp index fa7039f5..709b8d5d 100644 --- a/c++/include/connect/impl/thread_pool_for_server.hpp +++ b/c++/include/connect/impl/thread_pool_for_server.hpp @@ -1,7 +1,7 @@ #ifndef CONNECT__IMPL__THREAD_POOL_FOR_SERVER__HPP #define CONNECT__IMPL__THREAD_POOL_FOR_SERVER__HPP -/* $Id: thread_pool_for_server.hpp 387666 2013-01-31 14:49:08Z ucko $ +/* $Id: thread_pool_for_server.hpp 503649 2016-06-06 22:11:35Z satskyse $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -50,7 +50,7 @@ public: CQueueItemBase_ForServer(void) : m_Status(CQueueItemBase::ePending) {} - + const EStatus& GetStatus(void) const { return m_Status; } void MarkAsComplete(void) { x_SetStatus(CQueueItemBase::eComplete); } @@ -126,24 +126,25 @@ public: CQueueItemBase_ForServer::x_SetStatus(new_status); m_Request->OnStatusChange(old_status, new_status); } - + private: friend class CBlockingQueue_ForServer; TRequest m_Request; }; - + protected: /// The type of the queue typedef deque TRealQueue; // Derived classes should take care to use these members properly. - TRealQueue m_Queue; ///< The queue -#ifdef NCBI_HAVE_CONDITIONAL_VARIABLE + TRealQueue m_Queue; ///< The queue + + #ifdef NCBI_HAVE_CONDITIONAL_VARIABLE CConditionVariable m_GetCond; -#else + #else CSemaphore m_GetSem; ///< Raised if the queue contains data -#endif + #endif mutable CMutex m_Mutex; ///< Guards access to queue private: @@ -283,9 +284,8 @@ private: CAtomicCounter m_ThreadCount; /// The guard for m_MaxThreads and m_MaxUrgentThreads CMutex m_Mutex; - CAtomicCounter m_PutQueueNum; - CAtomicCounter m_GetQueueNum; - TQueue** m_Queues; + + TQueue m_Queue; string m_ThrSuffix; typedef list > TThreads; diff --git a/c++/include/connect/ncbi_base64.h b/c++/include/connect/ncbi_base64.h index 6a5917c0..4dd7187d 100644 --- a/c++/include/connect/ncbi_base64.h +++ b/c++/include/connect/ncbi_base64.h @@ -1,7 +1,7 @@ #ifndef CONNECT___NCBI_BASE64__H #define CONNECT___NCBI_BASE64__H -/* $Id: ncbi_base64.h 394629 2013-04-04 15:51:49Z kazimird $ +/* $Id: ncbi_base64.h 501318 2016-05-13 15:59:32Z vakatov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -97,9 +97,9 @@ extern NCBI_XCONNECT_EXPORT int/*bool*/ BASE64_Decode * was successful. */ typedef enum { - eBase64_OK, /** Transcoded successfully. */ - eBase64_BufferTooSmall, /** The output buffer is too small. */ - eBase64_InvalidInput /** Input contains characters outside alphabet. */ + eBase64_OK, /**< Transcoded successfully. */ + eBase64_BufferTooSmall, /**< The output buffer is too small. */ + eBase64_InvalidInput /**< Input contains characters outside alphabet. */ } EBase64_Result; diff --git a/c++/include/connect/ncbi_buffer.h b/c++/include/connect/ncbi_buffer.h index d9443a10..cde5d8fe 100644 --- a/c++/include/connect/ncbi_buffer.h +++ b/c++/include/connect/ncbi_buffer.h @@ -1,7 +1,7 @@ #ifndef CONNECT___NCBI_BUFFER__H #define CONNECT___NCBI_BUFFER__H -/* $Id: ncbi_buffer.h 482179 2015-10-21 15:02:35Z lavr $ +/* $Id: ncbi_buffer.h 491234 2016-02-03 16:17:23Z lavr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -201,7 +201,8 @@ extern NCBI_XCONNECT_EXPORT size_t BUF_PeekAt * at position "pos"), in chunks. Pass "cbdata" as an opaque parameter to the * "callback". Processing stops when all buffer bytes (but no more than * "size" bytes) have been visited by the "callback", or when the "callback" - * returns a value less than its passed "size" argument. + * returns a value less than its passed "size" argument (the "callback" may + * _not_ return a value greater than its "size" argument!). * Return the # of processed bytes (can be less than "size"). * Return zero and do nothing if "buf" is NULL or "pos" >= BUF_Size(buf). * Do nothing and return min(BUF_Size(buf)-pos, size) if "callback" is NULL. diff --git a/c++/include/connect/ncbi_connector.h b/c++/include/connect/ncbi_connector.h index a73793ab..b9f3ac3e 100644 --- a/c++/include/connect/ncbi_connector.h +++ b/c++/include/connect/ncbi_connector.h @@ -1,7 +1,7 @@ #ifndef CONNECT___NCBI_CONNECTOR__H #define CONNECT___NCBI_CONNECTOR__H -/* $Id: ncbi_connector.h 362749 2012-05-10 17:16:55Z lavr $ +/* $Id: ncbi_connector.h 513293 2016-09-09 11:36:15Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -83,7 +83,7 @@ typedef char* (*FConnectorDescr) /** Open connection. Used to setup all related data structures, * but not necessarily has to actually open the data channel. * @note Regardless of the returned status, the connection is considered open - * (so this call does not get repeated) when the call returns. + * (so this call doesn't get re-issued) after this call returns. */ typedef EIO_Status (*FConnectorOpen) (CONNECTOR connector, @@ -107,7 +107,7 @@ typedef EIO_Status (*FConnectorWait) /** Write to connector. * The passed "n_written" is always non-NULL, and "*n_written" is always zero. * The number of bytes actually written gets returned in "*n_written". - * It may not return "eIO_Success" if no data at all have been written. + * It may not return eIO_Success if no data at all have been written. * @note FConnectorWrite() is guaranteed to be called after FConnectorOpen(), * and only if the latter succeeded (returned eIO_Success). */ @@ -164,6 +164,7 @@ typedef EIO_Status (*FConnectorStatus) * and only if the latter succeeded (returned eIO_Success). * @note FConnectorFlush() gets called before FConnectorClose() automatically. * @note It may return eIO_Closed to indicate an unusual close condition. + * @note The same connector may now be either re-opened / re-used or recylced. */ typedef EIO_Status (*FConnectorClose) (CONNECTOR connector, @@ -192,12 +193,12 @@ typedef struct { } SMetaConnector; -#define CONN_TWO2ONE(a, b) a##b +#define _CONN_TWO2ONE(a, b) a##b #define CONN_SET_METHOD(meta, method, function, connector) \ do { \ - meta->method = function; \ - meta->CONN_TWO2ONE(c_,method) = connector; \ + meta->method = function; \ + meta->_CONN_TWO2ONE(c_,method) = connector; \ } while (0) @@ -214,7 +215,7 @@ typedef struct { /** Insert a connector in the beginning of the connection's list of connectors. * Calls connector's FSetupVTable, which must be defined. */ -extern NCBI_XCONNECT_EXPORT EIO_Status METACONN_Add +extern NCBI_XCONNECT_EXPORT EIO_Status METACONN_Insert (SMetaConnector* meta, CONNECTOR connector ); @@ -231,6 +232,7 @@ extern NCBI_XCONNECT_EXPORT EIO_Status METACONN_Remove /** Upcall on request to setup virtual function table (called from connection). + * NB: May not detect any failures (follow up in Open to fail if necessary). */ typedef void (*FSetupVTable) (CONNECTOR connector diff --git a/c++/include/connect/ncbi_connutil.h b/c++/include/connect/ncbi_connutil.h index 5ad9a00e..02835c73 100644 --- a/c++/include/connect/ncbi_connutil.h +++ b/c++/include/connect/ncbi_connutil.h @@ -1,7 +1,7 @@ #ifndef CONNECT___NCBI_CONNUTIL__H #define CONNECT___NCBI_CONNUTIL__H -/* $Id: ncbi_connutil.h 500351 2016-05-04 09:45:13Z ivanov $ +/* $Id: ncbi_connutil.h 513929 2016-09-16 15:08:30Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -150,7 +150,7 @@ typedef enum { typedef unsigned EBDebugPrintout; -/* Network connection related configurable info struct. +/* Network connection-related configurable informational structure. * ATTENTION: Do NOT fill out this structure (SConnNetInfo) "from scratch"! * Instead, use ConnNetInfo_Create() described below to create * it, and then fix (hard-code) some fields, if really necessary. @@ -166,19 +166,20 @@ typedef struct { /* NCBI_FAKE_WARNING: ICC */ EBURLScheme scheme:3; /* only pre-defined types (limited) */ TReqMethod req_method:5; /* method to use in the request (HTTP) */ unsigned version:1; /* HTTP/1.v (or selected by req_method)*/ + unsigned external:1; /* mark service request as external */ EBFWMode firewall:2; /* to use firewall (relay otherwise) */ unsigned stateless:1; /* to connect in HTTP-like fashion only*/ unsigned lb_disable:1; /* to disable local load-balancing */ EBDebugPrintout debug_printout:2; /* switch to printout some debug info */ unsigned http_push_auth:1; /* push authorize tags even w/o 401/407*/ unsigned http_proxy_leak:1;/* non-zero when can fallback to direct*/ - unsigned reserved:15; /* MBZ */ - char user[64]; /* username (if specified) */ - char pass[64]; /* password (if any) */ + unsigned reserved:14; /* MBZ */ + char user[64]; /* username (if specified or required) */ + char pass[64]; /* password (if any for non-empty user)*/ char host[256]; /* host to connect to */ unsigned short port; /* port to connect to, host byte order */ - char path[1024]; /* path (e.g. to a CGI script or page)*/ - char args[1024]; /* args (e.g. for a CGI script) */ + char path[2048]; /* path (e.g. to a CGI script or page)*/ + char args[2048]; /* args (e.g. for a CGI script) */ char http_proxy_host[256]; /* hostname of HTTP proxy server */ unsigned short http_proxy_port; /* port # of HTTP proxy server */ char http_proxy_user[64]; /* http proxy username (if req'd) */ @@ -189,7 +190,8 @@ typedef struct { /* NCBI_FAKE_WARNING: ICC */ const char* http_referer; /* default referrer (when not spec'd) */ NCBI_CRED credentials; /* connection credentials (optional) */ - /* the following field(s) are for the internal use only -- don't touch! */ + /* the following field(s) are for internal use only -- do not touch! */ + unsigned int magic; /* to detect version skew */ STimeout tmo; /* default storage for finite timeout */ const char svc[1]; /* service which this info created for */ } SConnNetInfo; @@ -244,6 +246,9 @@ typedef struct { /* NCBI_FAKE_WARNING: ICC */ #define REG_CONN_MAX_TRY "MAX_TRY" #define DEF_CONN_MAX_TRY 3 +#define REG_CONN_EXTERNAL "EXTERNAL" +#define DEF_CONN_EXTERNAL "" + #define REG_CONN_FIREWALL "FIREWALL" #define DEF_CONN_FIREWALL "" @@ -285,13 +290,14 @@ typedef struct { /* NCBI_FAKE_WARNING: ICC */ * 4. Registry key "param" (with "CONN_", if there was any, stripped) * in the section "[CONN]". * Steps 1 & 2 skipped for "service" passed as NULL or empty (""). - * Steps 3 & 4 skipped for non-empty "service" and "param" already beginning - * with "CONN_". - * If the found match's value has enveloping quotes (single '', or double "") - * then they are stripped from the result (which may then become empty). + * Steps 3 & 4 skipped for non-empty "service" and the "param" that already + * begins with "CONN_". + * If the found match's value has enveloping quotes (either single '' or + * double ""), then they are stripped from the result, which can then become + * empty. * The first "value_size" bytes (including the terminating '\0') of the result - * get copied to the "value" buffer (which may cause truncation!), and - * the passed "value" address gets returned. + * get copied to the "value" buffer (which may cause truncation!), and the + * passed "value" address gets returned. * When no match is found, the "value" gets filled with "def_value" (or an * empty string), which then gets returned. Return 0 only on out of memory. */ @@ -332,6 +338,7 @@ extern NCBI_XCONNECT_EXPORT int/*bool*/ ConnNetInfo_Boolean * http_push_auth HTTP_PUSH_AUTH Send credentials pre-emptively * timeout TIMEOUT ".": "3.00005", "infinite" * max_try MAX_TRY + * external EXTERNAL * firewall FIREWALL * stateless STATELESS * lb_disable LB_DISABLE obsolete diff --git a/c++/include/connect/ncbi_core.h b/c++/include/connect/ncbi_core.h index 0579d602..14caa802 100644 --- a/c++/include/connect/ncbi_core.h +++ b/c++/include/connect/ncbi_core.h @@ -1,7 +1,7 @@ #ifndef CONNECT___NCBI_CORE__H #define CONNECT___NCBI_CORE__H -/* $Id: ncbi_core.h 424634 2014-01-17 18:57:34Z lavr $ +/* $Id: ncbi_core.h 505000 2016-06-21 16:48:46Z vakatov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -283,6 +283,7 @@ typedef struct LOG_tag* LOG; typedef enum { eLOG_Trace = 0, eLOG_Note, + eLOG_Info = eLOG_Note, /**< In C++ Toolkit "Info" is used, not "Note" */ eLOG_Warning, eLOG_Error, eLOG_Critical, diff --git a/c++/include/connect/ncbi_core_cxx.hpp b/c++/include/connect/ncbi_core_cxx.hpp index 026ad45d..baf48bb2 100644 --- a/c++/include/connect/ncbi_core_cxx.hpp +++ b/c++/include/connect/ncbi_core_cxx.hpp @@ -1,7 +1,7 @@ #ifndef CONNECT___NCBI_CORE_CXX__H #define CONNECT___NCBI_CORE_CXX__H -/* $Id: ncbi_core_cxx.hpp 470048 2015-06-10 19:03:03Z lavr $ +/* $Id: ncbi_core_cxx.hpp 507476 2016-07-19 17:46:14Z lavr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -90,13 +90,14 @@ extern NCBI_XCONNECT_EXPORT MT_LOCK MT_LOCK_cxx2c ); -/// CONNECT_Init flags: which parameters to own. +/// CONNECT_Init flags: which parameters to own / initialize. /// @sa /// CONNECT_Init enum EConnectInitFlag { eConnectInit_OwnNothing = 0, ///< Original ownership gets retained eConnectInit_OwnRegistry = 1, ///< Registry ownership gets passed - eConnectInit_OwnLock = 2 ///< Lock ownership gets passed + eConnectInit_OwnLock = 2, ///< Lock ownership gets passed + eConnectInit_NoSSL = 4 ///< Do not init secure socket layer (SSL) }; typedef unsigned int TConnectInitFlags; ///< Bitwise OR of EConnectInitFlag diff --git a/c++/include/connect/ncbi_gnutls.h b/c++/include/connect/ncbi_gnutls.h index 120a071c..c9a40d0b 100644 --- a/c++/include/connect/ncbi_gnutls.h +++ b/c++/include/connect/ncbi_gnutls.h @@ -1,7 +1,7 @@ #ifndef CONNECT___NCBI_GNUTLS__H #define CONNECT___NCBI_GNUTLS__H -/* $Id: ncbi_gnutls.h 422344 2013-12-19 19:33:02Z lavr $ +/* $Id: ncbi_gnutls.h 507002 2016-07-13 21:10:28Z lavr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -47,10 +47,12 @@ extern "C" { #endif -extern SOCKSSL NcbiSetupGnuTls(void); +extern NCBI_XCONNECT_EXPORT +SOCKSSL NcbiSetupGnuTls(void); -extern NCBI_CRED NcbiCredGnuTls(void* xcred); +extern NCBI_XCONNECT_EXPORT +NCBI_CRED NcbiCredGnuTls(void* xcred); #ifdef __cplusplus diff --git a/c++/include/connect/ncbi_http_connector.h b/c++/include/connect/ncbi_http_connector.h index 1464caee..93d53ee9 100644 --- a/c++/include/connect/ncbi_http_connector.h +++ b/c++/include/connect/ncbi_http_connector.h @@ -1,7 +1,7 @@ #ifndef CONNECT___HTTP_CONNECTOR__H #define CONNECT___HTTP_CONNECTOR__H -/* $Id: ncbi_http_connector.h 500355 2016-05-04 09:47:56Z ivanov $ +/* $Id: ncbi_http_connector.h 507766 2016-07-21 16:32:56Z lavr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -104,7 +104,7 @@ extern "C" { * @var fHTTP_NoAutoRetry * Do not attempt any auto-retries in case of failing connections * (this flag effectively means having SConnNetInfo::max_try set to 1). - + * * @var fHTTP_UnsafeRedirects * For security reasons the following redirects comprise security risk, * and thus, are prohibited: switching from https to http, and/or @@ -285,6 +285,8 @@ typedef void (*FHTTP_Cleanup) * When fHTTP_WriteThru is set with HTTP/1.1, writing to the connector begins * upon any write operations, and reading from the connector causes the * request body to finalize and response to be fetched from the server. + * Request method must be explicitly specified with fHTTP_WriteThru, "ANY" + * does not get accepted (the eIO_NotSupported error returned). * * @note * If "fHTTP_AutoReconnect" is set in "flags", then the connector makes an @@ -312,7 +314,8 @@ extern NCBI_XCONNECT_EXPORT CONNECTOR HTTP_CreateConnectorEx * located at "net_info->http_proxy_host:net_info->http_proxy_port". Return * the tunnel as a socket via the last parameter. For compatibility with * future API extensions, please make sure *sock is NULL when making the call. - * If "net_info->scheme == eURL_Https", the returned socket is secure. + * The proxy gets contacted via HTTPS if "net_info->scheme == eURL_Https", and + * the resultant socket is returned secure (with the SSL session still active). * @note * "net_info" can be passed as NULL to be constructed from the environment. * @note diff --git a/c++/include/connect/ncbi_http_session.hpp b/c++/include/connect/ncbi_http_session.hpp index bbd6cc51..666b9cdb 100644 --- a/c++/include/connect/ncbi_http_session.hpp +++ b/c++/include/connect/ncbi_http_session.hpp @@ -1,7 +1,7 @@ #ifndef CONNECT___NCBI_HTTP_SESSION__HPP #define CONNECT___NCBI_HTTP_SESSION__HPP -/* $Id: ncbi_http_session.hpp 492271 2016-02-16 15:25:30Z ivanov $ +/* $Id: ncbi_http_session.hpp 519414 2016-11-15 18:23:40Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -219,7 +219,7 @@ private: CHttpHeaders& operator=(const CHttpHeaders&); // Check if the name is a reserved one (NCBI-SID, NCBI-PHID). - // If yes, log error and _ASSERT(0) - these headers must be set in + // If yes, log error - these headers must be set in // CRequestContext, not directly. // Return 'false' if the header name is not reserved and a value can // be set safely. @@ -489,6 +489,24 @@ public: /// value is used ($CONN_MAX_TRY - 1). void SetRetries(THttpRetries retries) { m_Retries = retries; } + /// Get current deadline for Execute(). + /// For now, effective only for if waiting for actual response + /// (as opposed to a recognized 'retry later' response), infinite by default. + /// @sa Execute() GetRetryProcessing() + const CTimeout& GetDeadline() const { return m_Deadline; } + /// Set new deadline for Execute(). + /// @sa Execute() SetRetryProcessing() + CHttpRequest& SetDeadline(const CTimeout& deadline); + + /// Return whether Execute() will wait for actual response. + /// If on, will wait for deadline expired or actual response + /// (as opposed to a recognized 'retry later' response), off by default. + /// @sa Execute() GetDeadline() + ESwitch GetRetryProcessing() const { return m_RetryProcessing; } + /// Set whether Execute() should wait for actual response. + /// @sa Execute() SetDeadline() + CHttpRequest& SetRetryProcessing(ESwitch on_off); + private: friend class CHttpSession; @@ -523,6 +541,8 @@ private: CRef m_Response; // current response or null CTimeout m_Timeout; THttpRetries m_Retries; + CTimeout m_Deadline; + ESwitch m_RetryProcessing; }; diff --git a/c++/include/connect/ncbi_lbos.hpp b/c++/include/connect/ncbi_lbos.hpp old mode 100755 new mode 100644 index 060b4437..12f8cda2 --- a/c++/include/connect/ncbi_lbos.hpp +++ b/c++/include/connect/ncbi_lbos.hpp @@ -26,88 +26,199 @@ * =========================================================================== * * Authors: Dmitriy Elisov +* Credits: Denis Vakatov +* * @file * File Description: * A client for service discovery API based on LBOS. -* LBOS is a client for ZooKeeper cloud-based DB. +* (LBOS is a client for ZooKeeper cloud-based DB.) * LBOS allows to announce, deannounce and resolve services. */ #include +#include + BEGIN_NCBI_SCOPE +#define LBOS_METADATA + class NCBI_XNCBI_EXPORT LBOS { public: - /** Announce server. +#ifdef LBOS_METADATA + class NCBI_XNCBI_EXPORT CMetaData + { + public: + /** Possible values for "type" meta parameter */ + enum EHostType { + eNone, /**< no "type" meta parameter */ + eHTTP, /**< "HTTP" */ + eHTTP_GET, /**< "HTTP_GET" */ + eHTTP_POST, /**< "HTTP_POST" */ + eStandalone, /**< "STANDALONE" */ + eNCBID, /**< "NCBID" */ + eDNS, /**< "DNS" */ + eFirewall, /**< "FIREWALL" */ + eUnknown /**< a value that has no corresponding enum, + but still valid */ + }; + + CMetaData(); + /** Get any meta parameter, including "known types" which can also be + * obtained via their corresponding individual functions */ + string Get(const string& name) const; + /** Set any metadata, including "known types" - "type", "rate", "extra", + * which can also be set by corresponding special functions. + * "" to unset the value + * @parameter[in] name + * Case-insensitive name of meta parameter (will be converted + * to lower case) + * @parameter[in] val + * Value to announce. "" to unset the value. Any string value will be + * accepted. If name is "extra", whitespace characters are forbidden + * in val. If name is "type", val is converted to upper case. */ + void Set(const CTempString name, const CTempString val); + /** Get names of all meta parameters in this CMetaData instance */ + void GetNames(vector& cont); + /** Get names of all meta parameters in this CMetaData instance */ + void GetNames(list& cont); + /** Get "rate" parameter as double. Returns 0 if value is + * not set */ + double GetRate() const; + /** Set "rate" meta parameter. + * @parameter[in] rate + * Rate to announce. "" to unset the value */ + void SetRate (const string& rate); + /** Set "rate" meta parameter. + * @parameter[in] rate + * Rate to announce. 0 to unset the value */ + void SetRate (double rate); + /** Get "server type" meta parameter. Returns upper-cased string value + * of the "type" meta parameter. + * @param[in] bool_fake_param + * To distinguish between EHostType and string return types */ + string GetType(bool) const; + /** Set "type" meta parameter. + * @parameter[in] host_type + * Host type to announce. EHostType has most popular options. + * LBOS::CMetaData::eNone to clear */ + void SetType (EHostType host_type); + /** Set "type" meta parameter using ncbi_server_info.h enums + * @parameter[in] host_type + * Host type to announce. Only values from ESERV_Type are valid. */ + void SetType (ESERV_Type host_type); + /** Set "type" meta parameter. + * @parameter[in] host_type + * Host type to announce. Integer equivalents of EHostType. 0 to clear + * the value */ + void SetType (int host_type); + /** Set "type" meta parameter. + * @parameter[in] host_type + * Host type to announce. Any string value will be accepted. + * "" to unset the value. + * @note + * host_type will be converted to upper case. */ + void SetType (const string& host_type); + /** Get "extra" meta parameter */ + string GetExtra() const; + /** Set "extra" meta parameter. Usually used to store a URL path to the + * HTTP server. + * @parameter[in] extra + * Extra to announce. Any string value will be accepted. + * "" to unset the value */ + void SetExtra(const string& extra); + /** Get "server type" meta parameter. Returns a corresponding enumerator + * if "type" meta parameter is set and equal to any of HTTP, HTTP_POST, + * DNS, STANDALONE or NCBID (case-insensitively). + * If "type is unset - returns eNone. + * Otherwise, returns eUnknown and actual value can be obtained with + * GetType(bool()); */ + LBOS::CMetaData::EHostType GetType() const; + /** Get a string with all parameters ready to put it into URL */ + string GetMetaString() const; + bool operator==(const CMetaData& other) const; + private: + map m_Meta; + }; + +#endif /* LBOS_METADATA */ + /** Announce server. * * @param [in] service - * Name of service as it will appear in ZK. For services this means that the - * name should start with '/'. + * Name of service as it will appear in ZK. For services this means that + * the name should start with '/'. * @param [in] version * Any non-null non-empty string that will help to identify the version * of service. A good idea is to use [semantic versioning] * (http://semver.org/) like "4.7.2" * @param [in] host - * Optional parameter. Set to "" (empty string) to use host from - * healthcheck_url to make sure that server and healthcheck actually reside + * Optional parameter. Set it to "" (empty string) to use host from + * "healthcheck_url" to make sure that server and healthcheck do reside * on the same machine (it can be important when you specify hostname that * can be resolved to multiple IPs, and LBOS ends up registering server * on one host and healthcheck on another) * @param [in] port - * Port for the service. Can differ from healthcheck port. + * Port for the service. Can differ from the healthcheck port. * @param [in] healthcheck_url * Full absolute URL starting with "http://" or "https://". Must include * hostname or IP (and port, if necessary) + * @param [in] metadata + * Additional meta parameters that will be displayed in "meta" section in + * service discovery * @note * If you want to announce a server that is on the same machine that * announces it (i.e., if server announces itself), you can write * "0.0.0.0" for IP in both "host" and "healthcheck_url". You still have to * provide port, even if you write "0.0.0.0". - * @return - * Returns nothing if announcement was successful. Otherwise, throws an - * exception. * @exception CLBOSException * @sa AnnounceFromRegistry(), Deannounce(), DeannounceAll(), CLBOSException */ - static void - Announce(const string& service, - const string& version, - const string& host, - unsigned short port, - const string& healthcheck_url); - + static void Announce(const string& service, + const string& version, + const string& host, + unsigned short port, + const string& healthcheck_url, + const CMetaData& metadata); - /** Modification of Announce() that gets all the needed parameters from - * registry. + /** @copydoc LBOS::Announce() */ + static void Announce(const string& service, + const string& version, + const string& host, + unsigned short port, + const string& healthcheck_url, + const string& metadata = string()); + + + /** A variant of Announce() that gets all the needed parameters from + * registry. * * @param [in] registry_section - * Name of section in registry where to look for + * Name of section in registry where to look for the * announcement parameters. Please check documentation for Announce() to - * to see requirements for the arguments. + * see requirements for the arguments. * Parameters are: * service, version, host, port, health - * Example: - * -------------- + * @example + * In configuration file: * [LBOS_ANNOUNCEMENT] * service=MYSERVICE * version=1.0.0 * host=0.0.0.0 * port=8080 * health=http://0.0.0.0:8080/health + * extra=http://myserver.com/index.cgi?param=val¶m2=val2 + * type=HTTP + * rate=100 * - * @return - * Returns nothing if announcement was successful. Otherwise, throws an - * exception. * @exception CLBOSException * @sa Announce(), Deannounce(), DeannounceAll(), CLBOSException */ - static void AnnounceFromRegistry(string registry_section); + static void AnnounceFromRegistry(const string& registry_section); - /** Deannounce service. + /** Deannounce service. * @param [in] service * Name of service to be de-announced. * @param [in] version @@ -117,9 +228,6 @@ public: * (NOT "0.0.0.0") to use local host address. * @param [in] port * Port of service to be de-announced. - * @return - * Returns nothing if de-announcement was successful. Otherwise, throws an - * exception. * @exception CLBOSException * @sa Announce(), DeannounceAll(), CLBOSException */ @@ -129,65 +237,27 @@ public: unsigned short port); - /** Deannounce all servers that were announced during runtime. + /** Deannounce all servers that were announced during runtime. * @note * There is no guarantee that all servers were de-announced successfully * after this function returned. There is a guarantee that de-announcement * request was sent to LBOS for each server that was announced by the * running application during runtime. - * @return - * Returns nothing, never throws. + * @note + * Never throws. You have no guarantee that it ran successfully. * @sa Announce(), Deannounce() */ static void DeannounceAll(void); +}; - /** Show default version of a service in ZooKeeper configuration. - * Does no change anything in ZooKeeper or LBOS configuration. - * @param service[in] - * Name of service for which to ask default version. - * @return - * Current default version. - * @exception CLBOSException - * If no record for the service was found, the exception will contain - * e_LBOSNotFound code. - */ - static - string ServiceVersionGet(const string& service, - bool* existed = NULL); - - - /** Set default version for a service in ZooKeeper configuration. - * @param[in] service - * Name of service for which to change the default version. - * @param new_version[out] - * Version that will be used by default for specified service. - * @return - * Version before request. - */ - static - string ServiceVersionSet(const string& service, - const string& new_version, - bool* existed = NULL); - - - /** Remove service from ZooKeeper configuration. Default - * version will be empty. - * @param[in] service - * Name of service to delete from ZooKeeper configuration. - * @return - * Version before request - */ - static - string ServiceVersionDelete(const string& service, - bool* existed = NULL); -}; +ostream& operator<<(ostream& os, const LBOS::CMetaData& metadata); /** CLBOSException is thrown if a request to LBOS fails for any * reason. CLBOSException has overloaded "what()" method that returns * message from LBOS (if there is one), which should contain status code and - * status message. If announcement failed not because of LBOS, but because of + * status message. If announcement failed not because of LBOS but because of * bad arguments, memory error, etc., status code is a non-HTTP status code. * To get its meaning you can call CLBOSException::GetErrCodeString(void) to * see human language description of the exception. @@ -197,61 +267,64 @@ class NCBI_XNCBI_EXPORT CLBOSException : public CException public: typedef int TErrCode; enum EErrCode { - e_LBOSNoLBOS = 0, /**< LBOS was not found */ - e_LBOSDNSResolveError = 1, /**< Local address not resolved */ - e_LBOSInvalidArgs = 2, /**< Arguments not valid */ - e_LBOSNotFound = 3, /**< For de-announcement only. Did not - find such server to deannounce */ - e_LBOSOff = 4, /**< LBOS client is off for any of the - two reasons: either it is not - enabled in registry, or no LBOS - working LBOS instance was found at - initialization */ - e_LBOSMemAllocError = 5, /**< Memory allocation error */ - e_LBOSCorruptOutput = 6, /**< LBOS returned unexpected output */ - e_LBOSBadRequest = 7, /**< LBOS returned "400 Bad Request" */ - e_LBOSUnknown = 8, /**< No information about this error - code meaning */ - e_LBOSServerError = 9 /**< LBOS returned "500 Internal Server - Error" */ + eLbosNotFound, /**< LBOS server was not found */ + eDNSResolve, /**< Local address not resolved */ + eInvalidArgs, /**< Arguments not valid */ + eNotFound, /**< For de-announcement only. Did not + find such server to deannounce */ + eDisabled, /**< LBOS client is off for any of the two reasons: + either it is not enabled in registry, or no + working LBOS instance was found at + initialization */ + eMemAlloc, /**< Memory allocation error */ + eProtocol, /**< LBOS server returned unexpected data */ + eBadVersion, /**< DTab contains empty(!) version for the service */ + eBadRequest, /**< LBOS server returned "400 Bad Request" */ + eUnknown, /**< Unknown or unclassified error */ + eServer /**< LBOS server returned "500 InternalServerError" */ }; - CLBOSException(const CDiagCompileInfo& info, - const CException* prev_exception, EErrCode err_code, - const string& message, unsigned short status_code, - EDiagSev severity = eDiag_Error); + CLBOSException(const CDiagCompileInfo& info, + const CException* prev_exception, + EErrCode err_code, + const string& message, + unsigned short status_code, + EDiagSev severity = eDiag_Error); - CLBOSException(const CDiagCompileInfo& info, - const CException* prev_exception, + CLBOSException(const CDiagCompileInfo& info, + const CException* prev_exception, const CExceptionArgs& args, - const string& message, - unsigned short status_code); + const string& message, + unsigned short status_code); + virtual ~CLBOSException(void) throw(); /** Get original status code and status message from LBOS in a string */ virtual const char* what() const throw(); /** Translate from the error code value to its string representation - * (only for internal errors; real LBOS - * errors will not be processed) */ + * (only for internal errors; real LBOS + * errors will not be processed) */ virtual const char* GetErrCodeString(void) const; - /** Translate from numerical HTTP status code to LBOS-specific - * error code */ + /** Translate from numerical HTTP status code to LBOS-specific err code */ static EErrCode s_HTTPCodeToEnum(unsigned short http_code); unsigned short GetStatusCode(void) const; virtual const char* GetType(void) const; TErrCode GetErrCode(void) const; NCBI_EXCEPTION_DEFAULT_THROW(CLBOSException) + protected: CLBOSException(void); virtual const CException* x_Clone(void) const; + private: unsigned short m_StatusCode; - string m_Message; + string m_Message; }; + END_NCBI_SCOPE #endif /* CONNECT___NCBI_LBOS__HPP */ diff --git a/c++/include/connect/ncbi_monkey.hpp b/c++/include/connect/ncbi_monkey.hpp new file mode 100644 index 00000000..709014dd --- /dev/null +++ b/c++/include/connect/ncbi_monkey.hpp @@ -0,0 +1,405 @@ +/* $Id: ncbi_monkey.hpp 505633 2016-06-27 19:28:13Z elisovdn $ +* =========================================================================== +* +* PUBLIC DOMAIN NOTICE +* National Center for Biotechnology Information +* +* This software/database is a "United States Government Work" under the +* terms of the United States Copyright Act. It was written as part of +* the author's official duties as a United States Government employee and +* thus cannot be copyrighted. This software/database is freely available +* to the public for use. The National Library of Medicine and the U.S. +* Government have not placed any restriction on its use or reproduction. +* +* Although all reasonable efforts have been taken to ensure the accuracy +* and reliability of the software and data, the NLM and the U.S. +* Government do not and cannot warrant the performance or results that +* may be obtained by using this software or data. The NLM and the U.S. +* Government disclaim all warranties, express or implied, including +* warranties of performance, merchantability or fitness for any particular +* purpose. +* +* Please cite the author in any work or product based on this material. +* +* =========================================================================== +* +* Author: Dmitriy Elisov +* +* File Description: +* Chaos Monkey - a library that is hooked with ncbi_socket.c and introduces +* problems in network connectivity - losses, bad data, delays. +* difficulties +* +*/ + +#ifndef CONNECT___NCBI_MONKEY__HPP +#define CONNECT___NCBI_MONKEY__HPP + +#include "../src/connect/ncbi_priv.h" + +#ifdef NCBI_MONKEY +# define NCBI_MONKEY_TESTS /* For Unit Testing */ + +# include +# include +# include +# include +# include "ncbi_socket.h" +# include "../src/connect/ncbi_socketp.h" +# include "ncbi_socket.hpp" +# include + +# include +# include +# include + + +BEGIN_NCBI_SCOPE + +using namespace std; + +enum EMonkeyActionType { + eMonkey_Recv, + eMonkey_Send, + eMonkey_Poll, + eMonkey_Connect +}; + + +class NCBI_XNCBI_EXPORT CMonkeyException : public CException +{ +public: + enum EErrCode { + e_MonkeyInvalidArgs = 0 /**< Incorrect arguments */ + ,e_MonkeyUnknown = 1 /**< Not classified as anything above */ + }; + + /** Get original status code and status message from LBOS in a string */ + virtual const char* what(void) const throw(); + +private: + unsigned short m_StatusCode; + string m_Message; + + NCBI_EXCEPTION_DEFAULT(CMonkeyException, CException); +}; + + +/** A special class which opens access to Monkey Seed + * (only for Monkey rules and plans) */ +class CMonkeySeedKey +{ + friend class CMonkeySeedAccessor; + CMonkeySeedKey() = default; + ~CMonkeySeedKey() = default; + /* No copying allowed */ + CMonkeySeedKey(const CMonkeySeedKey&) = delete; + CMonkeySeedKey& operator=(const CMonkeySeedKey&) = delete; +}; + + +/** Base class for Monkey methods that are allowed to write to MonkeyLog */ +class CMonkeySeedAccessor +{ +protected: + static const CMonkeySeedKey& Key(void); +}; + + +/** Common functionality for all rule types: + * - Runs order (vector m_Runs) + * - How to repeat runs order (ERepeatType m_RepeatType) + * - After how many runs repeat order (size_t m_RunsSize) + */ +class CMonkeyRuleBase : public CMonkeySeedAccessor +{ +public: + enum ERepeatType { + eMonkey_RepeatAgain, + eMonkey_RepeatLast, + eMonkey_RepeatNone + }; + enum ERunMode { + eMonkey_RunProbability, + eMonkey_RunNumber + }; + enum ERunFormat { + eMonkey_RunSequence, + eMonkey_RunRanges + }; + + /** Add socket */ + void AddSocket(MONKEY_SOCKTYPE sock) ; + + /** Check that this rule will trigger on this run (host and port have + * already been successfully matched if this check is run) */ + bool CheckRun(MONKEY_SOCKTYPE sock, + unsigned short probability_left = 100) const; + + /** Get probability that the rule will run next time */ + unsigned short GetProbability(MONKEY_SOCKTYPE sock) const; +protected: + CMonkeyRuleBase(EMonkeyActionType action_type, + const vector& name_value); + int /* EIO_Status or -1 */ GetReturnStatus(void) const; + unsigned long GetDelay(void) const; + + /* Iterate m_Runs */ + void IterateRun(MONKEY_SOCKTYPE sock); +private: + void x_ReadRuns (const string& runs); + void x_ReadEIOStatus(const string& eIOStatus_str); + int m_ReturnStatus; + ERepeatType m_RepeatType; + unsigned long m_Delay; + vector m_Runs; + EMonkeyActionType m_ActionType; + map m_RunPos; + /** If there are no-interception runs before repeating the cycle, + * we know that from m_RunsSize */ + size_t m_RunsSize; + /** Whether trigger settings are stored as probabilities for each run, + or as numbers of runs when the rule should trigger */ + ERunMode m_RunMode; +}; + + +/** Common functionality for CMonkeyWriteRule and CMonkeyReadRule: + * - Predefined text or random garbage? (bool m_Garbage) + * - Predefined text (string m_Text) + * - Text length (unsigned int m_TextLength) + * - How to fill response with text if text predefined (EFillType m_FillType) + * - What EIO_Status to return (EIO_Status m_ReturnStatus) + */ +class CMonkeyRWRuleBase : public CMonkeyRuleBase +{ +public: + enum EFillType { + eMonkey_FillRepeat, + eMonkey_FillLastLetter + }; +protected: + CMonkeyRWRuleBase(EMonkeyActionType action_type, + const vector& name_value); + string GetText (void) const; + size_t GetTextLength(void) const; + bool GetGarbage (void) const; + EFillType GetFillType (void) const; +private: + void x_ReadFill(const string& fill_str); + string m_Text; + size_t m_TextLength; + bool m_Garbage; + EFillType m_FillType; +}; + + +class CMonkeyWriteRule : public CMonkeyRWRuleBase +{ +public: + CMonkeyWriteRule(const vector& name_value); + + MONKEY_RETTYPE Run(MONKEY_SOCKTYPE sock, + const MONKEY_DATATYPE data, + MONKEY_LENTYPE size, + int flags, + SOCK* sock_ptr); +}; + + +class CMonkeyReadRule : public CMonkeyRWRuleBase +{ +public: + CMonkeyReadRule(const vector& name_value); + + MONKEY_RETTYPE Run(MONKEY_SOCKTYPE sock, + MONKEY_DATATYPE buf, + MONKEY_LENTYPE size, + int flags, + SOCK* sock_ptr); +private: + /* A socket that gets timeouts*/ + SOCK m_TimeoutingSocket; +}; + + +class CMonkeyConnectRule : public CMonkeyRuleBase +{ +public: + CMonkeyConnectRule(const vector& name_value); + + int Run(MONKEY_SOCKTYPE sock, + const struct sockaddr* name, + MONKEY_SOCKLENTYPE namelen); +private: + bool m_Allow; +}; + + +class CMonkeyPollRule : public CMonkeyRuleBase +{ +public: + CMonkeyPollRule(const vector& name_value); + + bool Run(size_t* n, + SOCK* sock, + EIO_Status* return_status); +private: + map x_Delays; + bool m_Ignore; +}; + + +class CMonkeyPlan : public CMonkeySeedAccessor +{ +public: +/* + * write1=text=garbage;return_status=eIO_Closed;text_length=500;runs=100%,0%,50.5%,100%,repeat + * write2=text='garbage';text_length=500;fill=last_letter;runs=0%,50%,25%,100%,32%,... + * read=text='read_garbage';text_length=500;fill=repeat;runs=50%;return_status=eIO_Closed + * connect=allow=no;runs=1,2,3,4,100 + * poll=delay=2000;ignore=yes,runs=1 + */ + CMonkeyPlan(const string& section); + + bool Match (const string& host, + unsigned short port, + const string& url, + unsigned short probability_left = 100); + /** Guarantees to have not run send() if returned false. Returning true + can mean either that send() was run or that send() was simulated to be + unsuccessful */ + bool WriteRule (MONKEY_SOCKTYPE sock, + const MONKEY_DATATYPE data, + MONKEY_LENTYPE size, + int flags, + MONKEY_RETTYPE* bytes_written, + SOCK* sock_ptr); + + bool ReadRule (MONKEY_SOCKTYPE sock, + MONKEY_DATATYPE buf, + MONKEY_LENTYPE size, + int flags, + MONKEY_RETTYPE* bytes_read, + SOCK* sock_ptr); + + bool ConnectRule (MONKEY_SOCKTYPE sock, + const struct sockaddr* name, + MONKEY_SOCKLENTYPE namelen, + int* result); + + bool PollRule (size_t* n, + SOCK* sock, + EIO_Status* return_status); + + unsigned short GetProbabilty(void); +private: + /** */ + template + void x_LoadRules(const string& section, + const string& rule_type_str, + vector& container); + + + void x_ReadPortRange(const string& conf); + unsigned short m_Probability; + string m_HostRegex; + /** Port ranges are stored in pairs. + * odd item - from, even - till (both - inclusive). So for one element + * in range "from" and "till" are the same. Example: + * for range "8080-8085, 8089" + * m_PortRanges = { 8080, 8085, 8089, 8089 } */ + vector m_PortRanges; + vector m_WriteRules; + vector m_ReadRules; + vector m_ConnectRules; + vector m_PollRules; + /** Only for debugging purposes */ + string m_Name; +}; + + +enum EMonkeyHookSwitch { + eMonkeyHookSwitch_Disabled = 0, + eMonkeyHookSwitch_Enabled = 1 +}; + + +typedef void (*FMonkeyHookSwitch)(EMonkeyHookSwitch hook_switch); + + +class CMonkey : public CMonkeySeedAccessor +{ +public: + /** This method is not for public use. + * CMonkeySeedLogKey is a special class that allows only some certain + * class to call this method */ + int GetRand(const CMonkeySeedKey& /* key */); + + /** To be able to reproduce Chaos Monkey behavior, you need to tag each + * thread with a unique token. Then you can ask Chaos Monkey to reproduce + * behavior from a previous run, if Monkey saved what it did to a file */ + bool RegisterThread(int token); + + int GetSeed(void); + void SetSeed(int seed); + static CMonkey* Instance(void); + void ReloadConfig(const string& config = ""); + bool IsEnabled(void); + + MONKEY_RETTYPE Send(MONKEY_SOCKTYPE sock, + const MONKEY_DATATYPE data, + MONKEY_LENTYPE size, + int flags, + SOCK* sock_ptr); + + MONKEY_RETTYPE Recv(MONKEY_SOCKTYPE sock, + MONKEY_DATATYPE buf, + MONKEY_LENTYPE size, + int flags, + SOCK* sock_ptr); + + int Connect(MONKEY_SOCKTYPE sock, + const struct sockaddr* name, + MONKEY_SOCKLENTYPE namelen); + + bool Poll(size_t* n, + SSOCK_Poll** polls, + EIO_Status* return_status); + /* Not a real Chaos Monkey interceptor, just a function to remove the socket + * that was closed from m_KnownSockets */ + void Close(MONKEY_SOCKTYPE sock); + + static void MonkeyHookSwitchSet(FMonkeyHookSwitch hook_switch_func); +private: + /* No one can create a separate instance of CMonkey*/ + CMonkey(void); + /** Return plan for the socket, new or already assigned one. If the socket + * is ignored by Chaos Monkey, NULL is returned. + * @param[in] match_host + * Tell whether host has to be matched, too. In case of poll() on + * listening socket it is impossible to know host before accept(), so + * the check is omitted. */ + CMonkeyPlan* x_FindPlan(MONKEY_SOCKTYPE sock, const string& hostname, + const string& host_IP, unsigned short port); + /** Sockets that are already assigned to a plan (or known to be ignored) */ + map m_KnownSockets; + static CMonkey* sm_Instance; + vector m_Plans; + double m_Probability; + bool m_Enabled; + static FMonkeyHookSwitch sm_HookSwitch; + CRef> m_TlsToken; + CRef > > m_TlsRandList; + CRef > m_TlsRandListPos; + unsigned int m_Seed; + /** Remember registered tokens for threads to avoid collisions */ + set m_RegisteredTokens; +}; + + +END_NCBI_SCOPE + +#endif /* #ifdef NCBI_MONKEY */ + +#endif /* CONNECT___NCBI_MONKEY__HPP */ \ No newline at end of file diff --git a/c++/include/connect/ncbi_server_info.h b/c++/include/connect/ncbi_server_info.h index 05a15c5e..c120c76c 100644 --- a/c++/include/connect/ncbi_server_info.h +++ b/c++/include/connect/ncbi_server_info.h @@ -1,7 +1,7 @@ #ifndef CONNECT___NCBI_SERVER_INFO__H #define CONNECT___NCBI_SERVER_INFO__H -/* $Id: ncbi_server_info.h 451391 2014-11-06 15:31:05Z lavr $ +/* $Id: ncbi_server_info.h 494171 2016-03-04 01:46:23Z lavr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -83,9 +83,6 @@ typedef enum { eSERV_Blast = 1, /* Server is tied up to an instant host load */ eSERV_RegularInter = 2, /* Regular server shared between LBSM zones */ eSERV_BlastInter = 3, /* ... same for Blast-type server */ - /* compatibility only, deprecated */ - fSERV_Regular = eSERV_Regular, - fSERV_Blast = eSERV_Blast } ESERV_Flag; diff --git a/c++/include/connect/ncbi_service.h b/c++/include/connect/ncbi_service.h index e7df6110..48024c66 100644 --- a/c++/include/connect/ncbi_service.h +++ b/c++/include/connect/ncbi_service.h @@ -1,7 +1,7 @@ #ifndef CONNECT___NCBI_SERVICE__H #define CONNECT___NCBI_SERVICE__H -/* $Id: ncbi_service.h 472260 2015-07-08 16:43:43Z elisovdn $ +/* $Id: ncbi_service.h 513292 2016-09-09 11:35:38Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -43,9 +43,9 @@ * @{ */ -/** Revision 6.270 */ -#define SERV_CLIENT_REVISION_MAJOR 6 -#define SERV_CLIENT_REVISION_MINOR 270 +/** Revision 7.0 */ +#define SERV_CLIENT_REVISION_MAJOR 7 +#define SERV_CLIENT_REVISION_MINOR 0 /** Special values for the "preferred_host" parameter. * @sa @@ -85,8 +85,8 @@ enum ESERV_TypeSpecial { fSERV_IncludeDown = 0x08000000, fSERV_IncludeStandby = 0x10000000, fSERV_IncludeReserved = 0x20000000, /**< @note Not yet implemented */ - fSERV_IncludePenalized = 0x40000000, - fSERV_IncludeSuppressed = 0x70000000, + fSERV_IncludeSuppressed = 0x40000000, + fSERV_IncludeInactive = 0x70000000, fSERV_Promiscuous = 0x78000000 }; typedef unsigned int TSERV_Type; /** GetListenerPorts(void); + protected: /// Initialize the server /// /// Called by Run method before poll cycle. - virtual void Init(); + virtual void Init() {} /// Cleanup the server /// @@ -164,12 +177,12 @@ protected: /// are stopped, but before releasing listening ports. Here you're still /// guaranteed that another instance running on the same set of ports will /// fail at StartListening point. - virtual void Exit(); + virtual void Exit() {} /// Runs synchronously when no socket activity has occurred in a /// while (as determined by m_AcceptTimeout). /// @sa m_Parameters->accept_timeout - virtual void ProcessTimeout(void) { } + virtual void ProcessTimeout(void) {} /// Runs synchronously between iterations. /// @return @@ -177,7 +190,6 @@ protected: virtual bool ShutdownRequested(void) { return false; } private: - void x_AddRequests(const vector >& reqs); void x_DoRun(void); friend class CNetCacheServer; @@ -274,6 +286,9 @@ public: // See comment for CAcceptRequest::Process and CServer::CreateRequest virtual void OnOverflow(EOverflowReason) { } + /// Runs when a socket error is detected + virtual void OnError(const string & /*err_message*/) { } + /// Get underlying socket CSocket& GetSocket(void) { return *m_Socket; } diff --git a/c++/include/connect/services/grid_client.hpp b/c++/include/connect/services/grid_client.hpp index 2f0b11fd..4ca9e87d 100644 --- a/c++/include/connect/services/grid_client.hpp +++ b/c++/include/connect/services/grid_client.hpp @@ -1,7 +1,7 @@ #ifndef CONNECT_SERVICES_GRID__GRID_CLIENT__HPP #define CONNECT_SERVICES_GRID__GRID_CLIENT__HPP -/* $Id: grid_client.hpp 492603 2016-02-18 19:27:56Z ivanov $ +/* $Id: grid_client.hpp 492431 2016-02-17 17:05:04Z sadyrovr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/connect/services/grid_worker.hpp b/c++/include/connect/services/grid_worker.hpp index f70b9f95..6d099c2d 100644 --- a/c++/include/connect/services/grid_worker.hpp +++ b/c++/include/connect/services/grid_worker.hpp @@ -2,7 +2,7 @@ #define CONNECT_SERVICES__GRID_WORKER_HPP -/* $Id: grid_worker.hpp 492323 2016-02-16 19:37:01Z ivanov $ +/* $Id: grid_worker.hpp 491853 2016-02-09 18:08:45Z sadyrovr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/connect/services/grid_worker_app.hpp b/c++/include/connect/services/grid_worker_app.hpp index 1ccaac1f..b8d8bc2c 100644 --- a/c++/include/connect/services/grid_worker_app.hpp +++ b/c++/include/connect/services/grid_worker_app.hpp @@ -2,7 +2,7 @@ #define CONNECT_SERVICES__GRID_WORKER_APP_HPP -/* $Id: grid_worker_app.hpp 492325 2016-02-16 19:37:51Z ivanov $ +/* $Id: grid_worker_app.hpp 491945 2016-02-10 18:01:31Z sadyrovr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/connect/services/impl/neticache_client_int.hpp b/c++/include/connect/services/impl/neticache_client_int.hpp index bbadd85e..40133a5a 100644 --- a/c++/include/connect/services/impl/neticache_client_int.hpp +++ b/c++/include/connect/services/impl/neticache_client_int.hpp @@ -1,7 +1,7 @@ #ifndef CONNECT_SERVICES_IMPL__NETICACHE_CLIENT_INT__HPP #define CONNECT_SERVICES_IMPL__NETICACHE_CLIENT_INT__HPP -/* $Id: neticache_client_int.hpp 498373 2016-04-15 17:20:10Z ivanov $ +/* $Id: neticache_client_int.hpp 498257 2016-04-14 16:43:26Z sadyrovr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/connect/services/impl/netschedule_api_int.hpp b/c++/include/connect/services/impl/netschedule_api_int.hpp index 5fd4ab48..e4604f5d 100644 --- a/c++/include/connect/services/impl/netschedule_api_int.hpp +++ b/c++/include/connect/services/impl/netschedule_api_int.hpp @@ -1,7 +1,7 @@ #ifndef CONNECT_SERVICES_IMPL__NETSCHEDULE_API_INT__HPP #define CONNECT_SERVICES_IMPL__NETSCHEDULE_API_INT__HPP -/* $Id: netschedule_api_int.hpp 492596 2016-02-18 19:25:31Z ivanov $ +/* $Id: netschedule_api_int.hpp 491948 2016-02-10 18:22:43Z sadyrovr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/connect/services/impl/netstorage_impl.hpp b/c++/include/connect/services/impl/netstorage_impl.hpp index c36c0701..0362c2c1 100644 --- a/c++/include/connect/services/impl/netstorage_impl.hpp +++ b/c++/include/connect/services/impl/netstorage_impl.hpp @@ -1,7 +1,7 @@ #ifndef CONNECT_SERVICES_IMPL__NETSTORAGE_IMPL__HPP #define CONNECT_SERVICES_IMPL__NETSTORAGE_IMPL__HPP -/* $Id: netstorage_impl.hpp 499844 2016-04-28 16:13:26Z ivanov $ +/* $Id: netstorage_impl.hpp 505978 2016-06-30 15:57:38Z sadyrovr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -215,10 +215,10 @@ struct NCBI_XCONNECT_EXPORT SNetStorageImpl : public CObject { typedef SNetStorage::SConfig TConfig; - virtual CNetStorageObject Create(TNetStorageFlags flags = 0) = 0; + virtual CNetStorageObject Create(TNetStorageFlags flags) = 0; virtual CNetStorageObject Open(const string& object_loc) = 0; virtual string Relocate(const string& object_loc, - TNetStorageFlags flags) = 0; + TNetStorageFlags flags, TNetStorageProgressCb cb) = 0; virtual bool Exists(const string& object_loc) = 0; virtual ENetStorageRemoveResult Remove(const string& object_loc) = 0; #ifdef NCBI_GRID_XSITE_CONN_SUPPORT @@ -232,12 +232,13 @@ struct NCBI_XCONNECT_EXPORT SNetStorageByKeyImpl : public CObject typedef SNetStorage::SConfig TConfig; virtual CNetStorageObject Open(const string& unique_key, - TNetStorageFlags flags = 0) = 0; + TNetStorageFlags flags) = 0; virtual string Relocate(const string& unique_key, - TNetStorageFlags flags, TNetStorageFlags old_flags = 0) = 0; - virtual bool Exists(const string& key, TNetStorageFlags flags = 0) = 0; + TNetStorageFlags flags, TNetStorageFlags old_flags, + TNetStorageProgressCb cb) = 0; + virtual bool Exists(const string& key, TNetStorageFlags flags) = 0; virtual ENetStorageRemoveResult Remove(const string& key, - TNetStorageFlags flags = 0) = 0; + TNetStorageFlags flags) = 0; #ifdef NCBI_GRID_XSITE_CONN_SUPPORT virtual void AllowXSiteConnections() {} #endif diff --git a/c++/include/connect/services/impl/netstorage_int.hpp b/c++/include/connect/services/impl/netstorage_int.hpp index c06cc355..e754b99a 100644 --- a/c++/include/connect/services/impl/netstorage_int.hpp +++ b/c++/include/connect/services/impl/netstorage_int.hpp @@ -1,7 +1,7 @@ #ifndef CONNECT_SERVICES_IMPL__NETSTORAGE_INT__HPP #define CONNECT_SERVICES_IMPL__NETSTORAGE_INT__HPP -/* $Id: netstorage_int.hpp 499028 2016-04-21 15:25:58Z ivanov $ +/* $Id: netstorage_int.hpp 498620 2016-04-18 16:34:28Z sadyrovr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/connect/services/json_over_uttp.hpp b/c++/include/connect/services/json_over_uttp.hpp index ca96bd88..a3350d41 100644 --- a/c++/include/connect/services/json_over_uttp.hpp +++ b/c++/include/connect/services/json_over_uttp.hpp @@ -1,7 +1,7 @@ #ifndef JSON_OVER_UTTP__HPP #define JSON_OVER_UTTP__HPP -/* $Id: json_over_uttp.hpp 495785 2016-03-21 16:50:59Z ivanov $ +/* $Id: json_over_uttp.hpp 502215 2016-05-23 15:27:45Z sadyrovr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -278,6 +278,10 @@ class NCBI_XCONNECT_EXPORT CJsonNode /// Return a string representation of this node. string Repr(TReprFlags flags = 0) const; + + static CJsonNode ParseObject(const string& json); + static CJsonNode ParseArray(const string& json); + static CJsonNode ParseJSON(const string& json); }; /// Iterator for JSON arrays and objects. diff --git a/c++/include/connect/services/netcache_api_expt.hpp b/c++/include/connect/services/netcache_api_expt.hpp index d51e58ae..0a9cc19c 100644 --- a/c++/include/connect/services/netcache_api_expt.hpp +++ b/c++/include/connect/services/netcache_api_expt.hpp @@ -1,7 +1,7 @@ #ifndef CONN___NETCACHE_API_EXPT__HPP #define CONN___NETCACHE_API_EXPT__HPP -/* $Id: netcache_api_expt.hpp 490874 2016-01-29 14:28:07Z ivanov $ +/* $Id: netcache_api_expt.hpp 490771 2016-01-28 17:36:51Z sadyrovr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/connect/services/netcache_search.hpp b/c++/include/connect/services/netcache_search.hpp new file mode 100644 index 00000000..fd525cbd --- /dev/null +++ b/c++/include/connect/services/netcache_search.hpp @@ -0,0 +1,169 @@ +#ifndef CONNECT_SERVICES___NETCACHE_SEARCH__HPP +#define CONNECT_SERVICES___NETCACHE_SEARCH__HPP + +/* $Id: netcache_search.hpp 520438 2016-11-28 18:35:31Z ivanov $ + * =========================================================================== + * + * PUBLIC DOMAIN NOTICE + * National Center for Biotechnology Information + * + * This software/database is a "United States Government Work" under the + * terms of the United States Copyright Act. It was written as part of + * the author's official duties as a United States Government employee and + * thus cannot be copyrighted. This software/database is freely available + * to the public for use. The National Library of Medicine and the U.S. + * Government have not placed any restriction on its use or reproduction. + * + * Although all reasonable efforts have been taken to ensure the accuracy + * and reliability of the software and data, the NLM and the U.S. + * Government do not and cannot warrant the performance or results that + * may be obtained by using this software or data. The NLM and the U.S. + * Government disclaim all warranties, express or implied, including + * warranties of performance, merchantability or fitness for any particular + * purpose. + * + * Please cite the author in any work or product based on this material. + * + * =========================================================================== + * + * Author: Rafael Sadyrov + * + */ + + +#include +#include +#include + + +namespace ncbi { +namespace grid { +namespace netcache { +namespace search { + + +/// @internal +/// @{ + +struct SExpressionImpl; +struct SBlobInfoImpl; +struct SExpression { shared_ptr impl; ~SExpression(); }; +struct SBlobInfo { shared_ptr impl; ~SBlobInfo(); }; + +/// @} + + +using time_point = chrono::system_clock::time_point; +using duration = chrono::system_clock::duration; + + +/// @defgroup NetCacheSearch +/// @{ + + +/// Search and output fields +namespace fields { + +const struct KEY {KEY(){}} key; +const struct SUBKEY {SUBKEY(){}} subkey; +const struct CREATED {CREATED(){}} created; +const struct EXPIRES {EXPIRES(){}} expires; +const struct VERSION_EXPIRES {VERSION_EXPIRES(){}} version_expires; +const struct SIZE {SIZE(){}} size; + +} + + +using namespace fields; + +/// Search operators +/// @{ + +struct NCBI_XCONNECT_EXPORT CExpression { SExpression base; }; + +NCBI_XCONNECT_EXPORT CExpression operator==(KEY, string); +NCBI_XCONNECT_EXPORT CExpression operator==(string, KEY); + +NCBI_XCONNECT_EXPORT CExpression operator>=(CREATED, time_point); +NCBI_XCONNECT_EXPORT CExpression operator< (CREATED, time_point); +NCBI_XCONNECT_EXPORT CExpression operator<=(time_point, CREATED); +NCBI_XCONNECT_EXPORT CExpression operator> (time_point, CREATED); + +NCBI_XCONNECT_EXPORT CExpression operator>=(CREATED, duration); +NCBI_XCONNECT_EXPORT CExpression operator< (CREATED, duration); +NCBI_XCONNECT_EXPORT CExpression operator<=(duration, CREATED); +NCBI_XCONNECT_EXPORT CExpression operator> (duration, CREATED); + +NCBI_XCONNECT_EXPORT CExpression operator>=(EXPIRES, time_point); +NCBI_XCONNECT_EXPORT CExpression operator< (EXPIRES, time_point); +NCBI_XCONNECT_EXPORT CExpression operator<=(time_point, EXPIRES); +NCBI_XCONNECT_EXPORT CExpression operator> (time_point, EXPIRES); + +NCBI_XCONNECT_EXPORT CExpression operator>=(EXPIRES, duration); +NCBI_XCONNECT_EXPORT CExpression operator< (EXPIRES, duration); +NCBI_XCONNECT_EXPORT CExpression operator<=(duration, EXPIRES); +NCBI_XCONNECT_EXPORT CExpression operator> (duration, EXPIRES); + +NCBI_XCONNECT_EXPORT CExpression operator>=(VERSION_EXPIRES, time_point); +NCBI_XCONNECT_EXPORT CExpression operator< (VERSION_EXPIRES, time_point); +NCBI_XCONNECT_EXPORT CExpression operator<=(time_point, VERSION_EXPIRES); +NCBI_XCONNECT_EXPORT CExpression operator> (time_point, VERSION_EXPIRES); + +NCBI_XCONNECT_EXPORT CExpression operator>=(VERSION_EXPIRES, duration); +NCBI_XCONNECT_EXPORT CExpression operator< (VERSION_EXPIRES, duration); +NCBI_XCONNECT_EXPORT CExpression operator<=(duration, VERSION_EXPIRES); +NCBI_XCONNECT_EXPORT CExpression operator> (duration, VERSION_EXPIRES); + +NCBI_XCONNECT_EXPORT CExpression operator>=(SIZE, size_t); +NCBI_XCONNECT_EXPORT CExpression operator< (SIZE, size_t); +NCBI_XCONNECT_EXPORT CExpression operator<=(size_t, SIZE); +NCBI_XCONNECT_EXPORT CExpression operator> (size_t, SIZE); + +NCBI_XCONNECT_EXPORT CExpression operator&&(CExpression, CExpression); + +/// @} + + +/// Output fields specification +/// @{ + +struct NCBI_XCONNECT_EXPORT CFields +{ + SExpression base; + + CFields(); + CFields(CREATED); + CFields(EXPIRES); + CFields(VERSION_EXPIRES); + CFields(SIZE); +}; + +NCBI_XCONNECT_EXPORT CFields operator|(CFields, CFields); + +/// @} + + +/// Blob info +struct NCBI_XCONNECT_EXPORT CBlobInfo +{ + SBlobInfo base; + + string operator[](KEY) const; + string operator[](SUBKEY) const; + time_point operator[](CREATED) const; + time_point operator[](EXPIRES) const; + time_point operator[](VERSION_EXPIRES) const; + size_t operator[](SIZE) const; +}; + + +/// @} + + +} +} +} +} + + +#endif diff --git a/c++/include/connect/services/netcomponent.hpp b/c++/include/connect/services/netcomponent.hpp index cab81b65..24f58405 100644 --- a/c++/include/connect/services/netcomponent.hpp +++ b/c++/include/connect/services/netcomponent.hpp @@ -1,7 +1,7 @@ #ifndef CONNECT_SERVICES__NET_OBJECT_HPP #define CONNECT_SERVICES__NET_OBJECT_HPP -/* $Id: netcomponent.hpp 485042 2015-11-18 14:41:49Z sadyrovr $ +/* $Id: netcomponent.hpp 501217 2016-05-12 14:34:55Z vasilche $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -71,6 +71,13 @@ public: CObjectCounterLocker::UnlockRelease( reinterpret_cast(object)); } + + void TransferLock(const S* object, + const CNetComponentCounterLocker& old_locker) const + { + CObjectCounterLocker::TransferLock( + reinterpret_cast(object), old_locker); + } }; #define NCBI_NET_COMPONENT_DEF(Class, Impl) \ diff --git a/c++/include/connect/services/neticache_client.hpp b/c++/include/connect/services/neticache_client.hpp index ec135b71..35735908 100644 --- a/c++/include/connect/services/neticache_client.hpp +++ b/c++/include/connect/services/neticache_client.hpp @@ -1,7 +1,7 @@ #ifndef CONNECT_SERVICES___NETICACHE_CLIENT__HPP #define CONNECT_SERVICES___NETICACHE_CLIENT__HPP -/* $Id: neticache_client.hpp 486447 2015-12-04 15:37:50Z sadyrovr $ +/* $Id: neticache_client.hpp 520437 2016-11-28 18:35:09Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -38,6 +38,7 @@ /// #include "netcache_api.hpp" +#include "netcache_search.hpp" #include @@ -150,6 +151,25 @@ class NCBI_NET_CACHE_EXPORT CNetICacheClient : public ICache /// list GetSubkeyList(const string& key); + typedef grid::netcache::search::CBlobInfo CBlobInfo; + typedef grid::netcache::search::CExpression CExpression; + typedef grid::netcache::search::CFields CFields; + + /// Returns information for all blobs matching provided search expression. + /// @see NetCacheSearch for complete list of classes and operators. + /// + /// @param expression + /// Search expression, + /// e.g. 'created < hours(1) && size >= 1024' + /// @param fields + /// Additional output fields requested in blob info, + /// e.g. 'expires | version_expires' + /// @return + /// Blob info consisting of key, subkey, fields from provided search + /// expression and output fields for all blobs matched the expression + /// + vector Search(CExpression expression, CFields fields = CFields()); + /// @warning /// This method DOES NOT follow ICache::Read() interface /// on returning values/throwing exceptions. diff --git a/c++/include/connect/services/netschedule_api.hpp b/c++/include/connect/services/netschedule_api.hpp index 300402f0..efb08ae5 100644 --- a/c++/include/connect/services/netschedule_api.hpp +++ b/c++/include/connect/services/netschedule_api.hpp @@ -1,7 +1,7 @@ #ifndef CONN___NETSCHEDULE_API__HPP #define CONN___NETSCHEDULE_API__HPP -/* $Id: netschedule_api.hpp 492595 2016-02-18 19:25:07Z ivanov $ +/* $Id: netschedule_api.hpp 507304 2016-07-18 16:15:49Z sadyrovr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -296,19 +296,17 @@ class NCBI_XCONNECT_EXPORT CNetScheduleAPI }; -//////////////////////////////////////////////////////////////////////////////// -//// -/// Job description +/// New job description /// -struct CNetScheduleJob + +struct CNetScheduleNewJob { - explicit CNetScheduleJob(const string& _input = kEmptyStr, + explicit CNetScheduleNewJob(const string& _input = kEmptyStr, const string& _affinity = kEmptyStr, CNetScheduleAPI::TJobMask _mask = CNetScheduleAPI::eEmptyMask) : input(_input), affinity(_affinity), - mask(_mask), - ret_code(0) + mask(_mask) { } @@ -316,20 +314,10 @@ struct CNetScheduleJob { input.erase(); affinity.erase(); - client_ip.erase(); - session_id.erase(); - page_hit_id.erase(); mask = CNetScheduleAPI::eEmptyMask; job_id.erase(); - ret_code = 0; - output.erase(); - error_msg.erase(); - progress_msg.erase(); group.erase(); - auth_token.erase(); - server = NULL; } - // input parameters /// Input data. Arbitrary string that contains input data /// for the job. It is suggested to use NetCache to keep @@ -338,14 +326,46 @@ struct CNetScheduleJob string affinity; - string client_ip; - string session_id; - string page_hit_id; + string group; CNetScheduleAPI::TJobMask mask; - /// Job key. + /// Output job key. string job_id; +}; + + +/// Job description +/// + +struct CNetScheduleJob : CNetScheduleNewJob +{ + explicit CNetScheduleJob(const string& _input = kEmptyStr, + const string& _affinity = kEmptyStr, + CNetScheduleAPI::TJobMask _mask = CNetScheduleAPI::eEmptyMask) : + CNetScheduleNewJob(_input, _affinity, _mask), + ret_code(0) + { + } + + void Reset() + { + CNetScheduleNewJob::Reset(); + client_ip.erase(); + session_id.erase(); + page_hit_id.erase(); + ret_code = 0; + output.erase(); + error_msg.erase(); + progress_msg.erase(); + auth_token.erase(); + server = NULL; + } + + string client_ip; + string session_id; + string page_hit_id; + /// Job return code. int ret_code; /// Job result data. @@ -353,8 +373,6 @@ struct CNetScheduleJob string error_msg; string progress_msg; - string group; - string auth_token; /// The server the job belongs to. @@ -375,7 +393,7 @@ class NCBI_XCONNECT_EXPORT CNetScheduleSubmitter /// Submit job. /// @note on success job.job_id will be set. - string SubmitJob(CNetScheduleJob& job); + string SubmitJob(CNetScheduleNewJob& job); /// Submit job batch. /// Method automatically splits the submission into reasonable sized diff --git a/c++/include/connect/services/netstorage.hpp b/c++/include/connect/services/netstorage.hpp index d6ee6562..889bde93 100644 --- a/c++/include/connect/services/netstorage.hpp +++ b/c++/include/connect/services/netstorage.hpp @@ -1,7 +1,7 @@ #ifndef CONNECT_SERVICES__NETSTORAGE__HPP #define CONNECT_SERVICES__NETSTORAGE__HPP -/* $Id: netstorage.hpp 494456 2016-03-07 17:46:55Z ivanov $ +/* $Id: netstorage.hpp 505855 2016-06-29 16:17:14Z sadyrovr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -42,6 +42,8 @@ #include +#include + BEGIN_NCBI_SCOPE @@ -73,6 +75,7 @@ public: eTimeout, ///< Timeout encountered while performing an op eExpired, ///< Object has expired on server eNotSupported, ///< Feature is not supported + eInterrupted, ///< Operation has been interrupted eUnknown ///< Unknown error }; virtual const char* GetErrCodeString() const; @@ -328,6 +331,14 @@ class NCBI_XCONNECT_EXPORT CNetStorageObject }; +/// Progress callback +/// +/// @param CJsonNode +/// progress info (depends on operation) +/// +typedef function TNetStorageProgressCb; + + /// Result returned by Remove() methods /// /// @see CNetStorage::Remove(), CNetStorageByKey::Remove() @@ -411,13 +422,17 @@ class NCBI_XCONNECT_EXPORT CNetStorage /// An existing object to relocate /// @param flags /// Combination of flags that defines the new object location (storage) - /// + /// @param cb + /// Relocation progress callback (@see TNetStorageProgressCb). + /// CJsonNode input argument (object) will contain two subnodes: + /// number 'BytesRelocated' and string 'Message' /// @return /// New object ID that fully reflects the new object location. /// If possible, this new ID should be used for further access to the /// object. Note however that its original ID still can be used as well. /// - string Relocate(const string& object_loc, TNetStorageFlags flags); + string Relocate(const string& object_loc, TNetStorageFlags flags, + TNetStorageProgressCb cb = TNetStorageProgressCb()); /// Check if the object addressed by 'object_loc' exists. /// @@ -497,6 +512,10 @@ class NCBI_XCONNECT_EXPORT CNetStorageByKey /// Combination of flags that defines the new object location /// @param old_flags /// Combination of flags that defines the current object location + /// @param cb + /// Relocation progress callback (@see TNetStorageProgressCb). + /// CJsonNode input argument (object) will contain two subnodes: + /// number 'BytesRelocated' and string 'Message' /// @return /// A unique full object ID that reflects the new object location (storage) /// and which can be used with CNetStorage::Open(). Note however that the @@ -504,7 +523,8 @@ class NCBI_XCONNECT_EXPORT CNetStorageByKey /// string Relocate(const string& unique_key, TNetStorageFlags flags, - TNetStorageFlags old_flags = 0); + TNetStorageFlags old_flags = 0, + TNetStorageProgressCb cb = TNetStorageProgressCb()); /// Check if a object with the specified key exists in the storage /// hinted by 'flags' diff --git a/c++/include/connect/services/netstorage_ft.hpp b/c++/include/connect/services/netstorage_ft.hpp index dd077bc2..a6685455 100644 --- a/c++/include/connect/services/netstorage_ft.hpp +++ b/c++/include/connect/services/netstorage_ft.hpp @@ -1,7 +1,7 @@ #ifndef CONNECT_SERVICES__NETSTORAGE_FT__HPP #define CONNECT_SERVICES__NETSTORAGE_FT__HPP -/* $Id: netstorage_ft.hpp 493320 2016-02-25 19:43:11Z ivanov $ +/* $Id: netstorage_ft.hpp 493146 2016-02-24 17:38:53Z sadyrovr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/connect/services/ns_output_parser.hpp b/c++/include/connect/services/ns_output_parser.hpp index 4635ce1d..e88ad446 100644 --- a/c++/include/connect/services/ns_output_parser.hpp +++ b/c++/include/connect/services/ns_output_parser.hpp @@ -1,4 +1,4 @@ -/* $Id: ns_output_parser.hpp 479861 2015-09-23 21:07:21Z sadyrovr $ +/* $Id: ns_output_parser.hpp 502472 2016-05-24 21:38:49Z sadyrovr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -37,47 +37,25 @@ BEGIN_NCBI_SCOPE -class NCBI_XCONNECT_EXPORT CNetScheduleStructuredOutputParser + +// Deprecated, use corresponding static method of CJsonNode instead +class NCBI_DEPRECATED NCBI_XCONNECT_EXPORT CNetScheduleStructuredOutputParser { public: CJsonNode ParseObject(const string& ns_output) { - m_Ch = (m_NSOutput = ns_output).c_str(); - - return ParseObject('\0'); + return CJsonNode::ParseObject(ns_output); } CJsonNode ParseArray(const string& ns_output) { - m_Ch = (m_NSOutput = ns_output).c_str(); - - return ParseArray('\0'); + return CJsonNode::ParseArray(ns_output); } - CJsonNode ParseJSON(const string& json); - -private: - size_t GetRemainder() const + CJsonNode ParseJSON(const string& json) { - return m_NSOutput.length() - (m_Ch - m_NSOutput.data()); + return CJsonNode::ParseJSON(json); } - - size_t GetPosition() const - { - return m_Ch - m_NSOutput.data() + 1; - } - - string ParseString(size_t max_len); - Int8 ParseInt(size_t len); - double ParseDouble(size_t len); - bool MoreNodes(); - - CJsonNode ParseObject(char closing_char); - CJsonNode ParseArray(char closing_char); - CJsonNode ParseValue(); - - string m_NSOutput; - const char* m_Ch; }; class NCBI_XCONNECT_EXPORT CAttrListParser diff --git a/c++/include/corelib/ddumpable.hpp b/c++/include/corelib/ddumpable.hpp index 9b43b9f8..e1c8714e 100644 --- a/c++/include/corelib/ddumpable.hpp +++ b/c++/include/corelib/ddumpable.hpp @@ -1,7 +1,7 @@ #ifndef DDUMPABLE__HPP #define DDUMPABLE__HPP -/* $Id: ddumpable.hpp 493118 2016-02-24 15:43:33Z ivanov $ +/* $Id: ddumpable.hpp 493042 2016-02-23 19:38:23Z gouriano $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/corelib/hash_impl/_hash_map.h b/c++/include/corelib/hash_impl/_hash_map.h index d3d3ea53..fb672098 100644 --- a/c++/include/corelib/hash_impl/_hash_map.h +++ b/c++/include/corelib/hash_impl/_hash_map.h @@ -83,71 +83,88 @@ public: private: _Ht _M_ht; public: - hash_map() : _M_ht(100, hasher(), key_equal(), allocator_type()) {} - explicit hash_map(size_type __n) + /// @deprecated Use std::unordered_map + NCBI_DEPRECATED hash_map() : _M_ht(100, hasher(), key_equal(), allocator_type()) {} + /// @deprecated Use std::unordered_map + NCBI_DEPRECATED explicit hash_map(size_type __n) : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} - hash_map(size_type __n, const hasher& __hf) + /// @deprecated Use std::unordered_map + NCBI_DEPRECATED hash_map(size_type __n, const hasher& __hf) : _M_ht(__n, __hf, key_equal(), allocator_type()) {} - hash_map(size_type __n, const hasher& __hf, const key_equal& __eql, + /// @deprecated Use std::unordered_map + NCBI_DEPRECATED hash_map(size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a = allocator_type()) : _M_ht(__n, __hf, __eql, __a) {} #ifdef _STLP_MEMBER_TEMPLATES template - hash_map(_InputIterator __f, _InputIterator __l) + /// @deprecated Use std::unordered_map + NCBI_DEPRECATED hash_map(_InputIterator __f, _InputIterator __l) : _M_ht(100, hasher(), key_equal(), allocator_type()) { _M_ht.insert_unique(__f, __l); } template - hash_map(_InputIterator __f, _InputIterator __l, size_type __n) + /// @deprecated Use std::unordered_map + NCBI_DEPRECATED hash_map(_InputIterator __f, _InputIterator __l, size_type __n) : _M_ht(__n, hasher(), key_equal(), allocator_type()) { _M_ht.insert_unique(__f, __l); } template - hash_map(_InputIterator __f, _InputIterator __l, size_type __n, + /// @deprecated Use std::unordered_map + NCBI_DEPRECATED hash_map(_InputIterator __f, _InputIterator __l, size_type __n, const hasher& __hf) : _M_ht(__n, __hf, key_equal(), allocator_type()) { _M_ht.insert_unique(__f, __l); } # ifdef _STLP_NEEDS_EXTRA_TEMPLATE_CONSTRUCTORS template - hash_map(_InputIterator __f, _InputIterator __l, size_type __n, + /// @deprecated Use std::unordered_map + NCBI_DEPRECATED hash_map(_InputIterator __f, _InputIterator __l, size_type __n, const hasher& __hf, const key_equal& __eql) : _M_ht(__n, __hf, __eql, allocator_type()) { _M_ht.insert_unique(__f, __l); } # endif template - hash_map(_InputIterator __f, _InputIterator __l, size_type __n, + /// @deprecated Use std::unordered_map + NCBI_DEPRECATED hash_map(_InputIterator __f, _InputIterator __l, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a _STLP_ALLOCATOR_TYPE_DFL) : _M_ht(__n, __hf, __eql, __a) { _M_ht.insert_unique(__f, __l); } #else - hash_map(const value_type* __f, const value_type* __l) + /// @deprecated Use std::unordered_map + NCBI_DEPRECATED hash_map(const value_type* __f, const value_type* __l) : _M_ht(100, hasher(), key_equal(), allocator_type()) { _M_ht.insert_unique(__f, __l); } - hash_map(const value_type* __f, const value_type* __l, size_type __n) + /// @deprecated Use std::unordered_map + NCBI_DEPRECATED hash_map(const value_type* __f, const value_type* __l, size_type __n) : _M_ht(__n, hasher(), key_equal(), allocator_type()) { _M_ht.insert_unique(__f, __l); } - hash_map(const value_type* __f, const value_type* __l, size_type __n, + /// @deprecated Use std::unordered_map + NCBI_DEPRECATED hash_map(const value_type* __f, const value_type* __l, size_type __n, const hasher& __hf) : _M_ht(__n, __hf, key_equal(), allocator_type()) { _M_ht.insert_unique(__f, __l); } - hash_map(const value_type* __f, const value_type* __l, size_type __n, + /// @deprecated Use std::unordered_map + NCBI_DEPRECATED hash_map(const value_type* __f, const value_type* __l, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a = allocator_type()) : _M_ht(__n, __hf, __eql, __a) { _M_ht.insert_unique(__f, __l); } - hash_map(const_iterator __f, const_iterator __l) + /// @deprecated Use std::unordered_map + NCBI_DEPRECATED hash_map(const_iterator __f, const_iterator __l) : _M_ht(100, hasher(), key_equal(), allocator_type()) { _M_ht.insert_unique(__f, __l); } - hash_map(const_iterator __f, const_iterator __l, size_type __n) + /// @deprecated Use std::unordered_map + NCBI_DEPRECATED hash_map(const_iterator __f, const_iterator __l, size_type __n) : _M_ht(__n, hasher(), key_equal(), allocator_type()) { _M_ht.insert_unique(__f, __l); } - hash_map(const_iterator __f, const_iterator __l, size_type __n, + /// @deprecated Use std::unordered_map + NCBI_DEPRECATED hash_map(const_iterator __f, const_iterator __l, size_type __n, const hasher& __hf) : _M_ht(__n, __hf, key_equal(), allocator_type()) { _M_ht.insert_unique(__f, __l); } - hash_map(const_iterator __f, const_iterator __l, size_type __n, + /// @deprecated Use std::unordered_map + NCBI_DEPRECATED hash_map(const_iterator __f, const_iterator __l, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a = allocator_type()) : _M_ht(__n, __hf, __eql, __a) @@ -250,71 +267,88 @@ public: private: _Ht _M_ht; public: - hash_multimap() : _M_ht(100, hasher(), key_equal(), allocator_type()) {} - explicit hash_multimap(size_type __n) + /// @deprecated Use std::unordered_multimap + NCBI_DEPRECATED hash_multimap() : _M_ht(100, hasher(), key_equal(), allocator_type()) {} + /// @deprecated Use std::unordered_multimap + NCBI_DEPRECATED explicit hash_multimap(size_type __n) : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} - hash_multimap(size_type __n, const hasher& __hf) + /// @deprecated Use std::unordered_multimap + NCBI_DEPRECATED hash_multimap(size_type __n, const hasher& __hf) : _M_ht(__n, __hf, key_equal(), allocator_type()) {} - hash_multimap(size_type __n, const hasher& __hf, const key_equal& __eql, + /// @deprecated Use std::unordered_multimap + NCBI_DEPRECATED hash_multimap(size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a = allocator_type()) : _M_ht(__n, __hf, __eql, __a) {} #ifdef _STLP_MEMBER_TEMPLATES template - hash_multimap(_InputIterator __f, _InputIterator __l) + /// @deprecated Use std::unordered_multimap + NCBI_DEPRECATED hash_multimap(_InputIterator __f, _InputIterator __l) : _M_ht(100, hasher(), key_equal(), allocator_type()) { _M_ht.insert_equal(__f, __l); } template - hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n) + /// @deprecated Use std::unordered_multimap + NCBI_DEPRECATED hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n) : _M_ht(__n, hasher(), key_equal(), allocator_type()) { _M_ht.insert_equal(__f, __l); } template - hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n, + /// @deprecated Use std::unordered_multimap + NCBI_DEPRECATED hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n, const hasher& __hf) : _M_ht(__n, __hf, key_equal(), allocator_type()) { _M_ht.insert_equal(__f, __l); } # ifdef _STLP_NEEDS_EXTRA_TEMPLATE_CONSTRUCTORS template - hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n, + /// @deprecated Use std::unordered_multimap + NCBI_DEPRECATED hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n, const hasher& __hf, const key_equal& __eql) : _M_ht(__n, __hf, __eql, allocator_type()) { _M_ht.insert_equal(__f, __l); } # endif template - hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n, + /// @deprecated Use std::unordered_multimap + NCBI_DEPRECATED hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a _STLP_ALLOCATOR_TYPE_DFL) : _M_ht(__n, __hf, __eql, __a) { _M_ht.insert_equal(__f, __l); } #else - hash_multimap(const value_type* __f, const value_type* __l) + /// @deprecated Use std::unordered_multimap + NCBI_DEPRECATED hash_multimap(const value_type* __f, const value_type* __l) : _M_ht(100, hasher(), key_equal(), allocator_type()) { _M_ht.insert_equal(__f, __l); } - hash_multimap(const value_type* __f, const value_type* __l, size_type __n) + /// @deprecated Use std::unordered_multimap + NCBI_DEPRECATED hash_multimap(const value_type* __f, const value_type* __l, size_type __n) : _M_ht(__n, hasher(), key_equal(), allocator_type()) { _M_ht.insert_equal(__f, __l); } - hash_multimap(const value_type* __f, const value_type* __l, size_type __n, + /// @deprecated Use std::unordered_multimap + NCBI_DEPRECATED hash_multimap(const value_type* __f, const value_type* __l, size_type __n, const hasher& __hf) : _M_ht(__n, __hf, key_equal(), allocator_type()) { _M_ht.insert_equal(__f, __l); } - hash_multimap(const value_type* __f, const value_type* __l, size_type __n, + /// @deprecated Use std::unordered_multimap + NCBI_DEPRECATED hash_multimap(const value_type* __f, const value_type* __l, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a = allocator_type()) : _M_ht(__n, __hf, __eql, __a) { _M_ht.insert_equal(__f, __l); } - hash_multimap(const_iterator __f, const_iterator __l) + /// @deprecated Use std::unordered_multimap + NCBI_DEPRECATED hash_multimap(const_iterator __f, const_iterator __l) : _M_ht(100, hasher(), key_equal(), allocator_type()) { _M_ht.insert_equal(__f, __l); } - hash_multimap(const_iterator __f, const_iterator __l, size_type __n) + /// @deprecated Use std::unordered_multimap + NCBI_DEPRECATED hash_multimap(const_iterator __f, const_iterator __l, size_type __n) : _M_ht(__n, hasher(), key_equal(), allocator_type()) { _M_ht.insert_equal(__f, __l); } - hash_multimap(const_iterator __f, const_iterator __l, size_type __n, + /// @deprecated Use std::unordered_multimap + NCBI_DEPRECATED hash_multimap(const_iterator __f, const_iterator __l, size_type __n, const hasher& __hf) : _M_ht(__n, __hf, key_equal(), allocator_type()) { _M_ht.insert_equal(__f, __l); } - hash_multimap(const_iterator __f, const_iterator __l, size_type __n, + /// @deprecated Use std::unordered_multimap + NCBI_DEPRECATED hash_multimap(const_iterator __f, const_iterator __l, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a = allocator_type()) : _M_ht(__n, __hf, __eql, __a) diff --git a/c++/include/corelib/hash_impl/_hash_set.h b/c++/include/corelib/hash_impl/_hash_set.h index 9b5629d7..6c46a8fa 100644 --- a/c++/include/corelib/hash_impl/_hash_set.h +++ b/c++/include/corelib/hash_impl/_hash_set.h @@ -79,72 +79,89 @@ private: _Ht _M_ht; public: - hash_set() + /// @deprecated Use std::unordered_set + NCBI_DEPRECATED hash_set() : _M_ht(100, hasher(), key_equal(), allocator_type()) {} - explicit hash_set(size_type __n) + /// @deprecated Use std::unordered_set + NCBI_DEPRECATED explicit hash_set(size_type __n) : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} - hash_set(size_type __n, const hasher& __hf) + /// @deprecated Use std::unordered_set + NCBI_DEPRECATED hash_set(size_type __n, const hasher& __hf) : _M_ht(__n, __hf, key_equal(), allocator_type()) {} - hash_set(size_type __n, const hasher& __hf, const key_equal& __eql, + /// @deprecated Use std::unordered_set + NCBI_DEPRECATED hash_set(size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a = allocator_type()) : _M_ht(__n, __hf, __eql, __a) {} #ifdef _STLP_MEMBER_TEMPLATES template - hash_set(_InputIterator __f, _InputIterator __l) + /// @deprecated Use std::unordered_set + NCBI_DEPRECATED hash_set(_InputIterator __f, _InputIterator __l) : _M_ht(100, hasher(), key_equal(), allocator_type()) { _M_ht.insert_unique(__f, __l); } template - hash_set(_InputIterator __f, _InputIterator __l, size_type __n) + /// @deprecated Use std::unordered_set + NCBI_DEPRECATED hash_set(_InputIterator __f, _InputIterator __l, size_type __n) : _M_ht(__n, hasher(), key_equal(), allocator_type()) { _M_ht.insert_unique(__f, __l); } template - hash_set(_InputIterator __f, _InputIterator __l, size_type __n, + /// @deprecated Use std::unordered_set + NCBI_DEPRECATED hash_set(_InputIterator __f, _InputIterator __l, size_type __n, const hasher& __hf) : _M_ht(__n, __hf, key_equal(), allocator_type()) { _M_ht.insert_unique(__f, __l); } # ifdef _STLP_NEEDS_EXTRA_TEMPLATE_CONSTRUCTORS template - hash_set(_InputIterator __f, _InputIterator __l, size_type __n, + /// @deprecated Use std::unordered_set + NCBI_DEPRECATED hash_set(_InputIterator __f, _InputIterator __l, size_type __n, const hasher& __hf, const key_equal& __eql) : _M_ht(__n, __hf, __eql, allocator_type()) { _M_ht.insert_unique(__f, __l); } # endif template - hash_set(_InputIterator __f, _InputIterator __l, size_type __n, + /// @deprecated Use std::unordered_set + NCBI_DEPRECATED hash_set(_InputIterator __f, _InputIterator __l, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a _STLP_ALLOCATOR_TYPE_DFL) : _M_ht(__n, __hf, __eql, __a) { _M_ht.insert_unique(__f, __l); } #else - hash_set(const value_type* __f, const value_type* __l) + /// @deprecated Use std::unordered_set + NCBI_DEPRECATED hash_set(const value_type* __f, const value_type* __l) : _M_ht(100, hasher(), key_equal(), allocator_type()) { _M_ht.insert_unique(__f, __l); } - hash_set(const value_type* __f, const value_type* __l, size_type __n) + /// @deprecated Use std::unordered_set + NCBI_DEPRECATED hash_set(const value_type* __f, const value_type* __l, size_type __n) : _M_ht(__n, hasher(), key_equal(), allocator_type()) { _M_ht.insert_unique(__f, __l); } - hash_set(const value_type* __f, const value_type* __l, size_type __n, + /// @deprecated Use std::unordered_set + NCBI_DEPRECATED hash_set(const value_type* __f, const value_type* __l, size_type __n, const hasher& __hf) : _M_ht(__n, __hf, key_equal(), allocator_type()) { _M_ht.insert_unique(__f, __l); } - hash_set(const value_type* __f, const value_type* __l, size_type __n, + /// @deprecated Use std::unordered_set + NCBI_DEPRECATED hash_set(const value_type* __f, const value_type* __l, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a = allocator_type()) : _M_ht(__n, __hf, __eql, __a) { _M_ht.insert_unique(__f, __l); } - hash_set(const_iterator __f, const_iterator __l) + /// @deprecated Use std::unordered_set + NCBI_DEPRECATED hash_set(const_iterator __f, const_iterator __l) : _M_ht(100, hasher(), key_equal(), allocator_type()) { _M_ht.insert_unique(__f, __l); } - hash_set(const_iterator __f, const_iterator __l, size_type __n) + /// @deprecated Use std::unordered_set + NCBI_DEPRECATED hash_set(const_iterator __f, const_iterator __l, size_type __n) : _M_ht(__n, hasher(), key_equal(), allocator_type()) { _M_ht.insert_unique(__f, __l); } - hash_set(const_iterator __f, const_iterator __l, size_type __n, + /// @deprecated Use std::unordered_set + NCBI_DEPRECATED hash_set(const_iterator __f, const_iterator __l, size_type __n, const hasher& __hf) : _M_ht(__n, __hf, key_equal(), allocator_type()) { _M_ht.insert_unique(__f, __l); } - hash_set(const_iterator __f, const_iterator __l, size_type __n, + /// @deprecated Use std::unordered_set + NCBI_DEPRECATED hash_set(const_iterator __f, const_iterator __l, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a = allocator_type()) : _M_ht(__n, __hf, __eql, __a) @@ -251,75 +268,93 @@ private: _Ht _M_ht; public: - hash_multiset() + /// @deprecated Use std::unordered_multiset + NCBI_DEPRECATED hash_multiset() : _M_ht(100, hasher(), key_equal(), allocator_type()) {} - explicit hash_multiset(size_type __n) + /// @deprecated Use std::unordered_multiset + NCBI_DEPRECATED explicit hash_multiset(size_type __n) : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} - hash_multiset(size_type __n, const hasher& __hf) + /// @deprecated Use std::unordered_multiset + NCBI_DEPRECATED hash_multiset(size_type __n, const hasher& __hf) : _M_ht(__n, __hf, key_equal(), allocator_type()) {} - hash_multiset(size_type __n, const hasher& __hf, const key_equal& __eql) + /// @deprecated Use std::unordered_multiset + NCBI_DEPRECATED hash_multiset(size_type __n, const hasher& __hf, const key_equal& __eql) : _M_ht(__n, __hf, __eql, allocator_type()) {} - hash_multiset(size_type __n, const hasher& __hf, const key_equal& __eql, + /// @deprecated Use std::unordered_multiset + NCBI_DEPRECATED hash_multiset(size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a) : _M_ht(__n, __hf, __eql, __a) {} #ifdef _STLP_MEMBER_TEMPLATES template - hash_multiset(_InputIterator __f, _InputIterator __l) + /// @deprecated Use std::unordered_multiset + NCBI_DEPRECATED hash_multiset(_InputIterator __f, _InputIterator __l) : _M_ht(100, hasher(), key_equal(), allocator_type()) { _M_ht.insert_equal(__f, __l); } template - hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n) + /// @deprecated Use std::unordered_multiset + NCBI_DEPRECATED hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n) : _M_ht(__n, hasher(), key_equal(), allocator_type()) { _M_ht.insert_equal(__f, __l); } template - hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n, + /// @deprecated Use std::unordered_multiset + NCBI_DEPRECATED hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n, const hasher& __hf) : _M_ht(__n, __hf, key_equal(), allocator_type()) { _M_ht.insert_equal(__f, __l); } # ifdef _STLP_NEEDS_EXTRA_TEMPLATE_CONSTRUCTORS template - hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n, + /// @deprecated Use std::unordered_multiset + NCBI_DEPRECATED hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n, const hasher& __hf, const key_equal& __eql) : _M_ht(__n, __hf, __eql, allocator_type()) { _M_ht.insert_equal(__f, __l); } # endif template - hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n, + /// @deprecated Use std::unordered_multiset + NCBI_DEPRECATED hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a _STLP_ALLOCATOR_TYPE_DFL) : _M_ht(__n, __hf, __eql, __a) { _M_ht.insert_equal(__f, __l); } #else - hash_multiset(const value_type* __f, const value_type* __l) + /// @deprecated Use std::unordered_multiset + NCBI_DEPRECATED hash_multiset(const value_type* __f, const value_type* __l) : _M_ht(100, hasher(), key_equal(), allocator_type()) { _M_ht.insert_equal(__f, __l); } - hash_multiset(const value_type* __f, const value_type* __l, size_type __n) + /// @deprecated Use std::unordered_multiset + NCBI_DEPRECATED hash_multiset(const value_type* __f, const value_type* __l, size_type __n) : _M_ht(__n, hasher(), key_equal(), allocator_type()) { _M_ht.insert_equal(__f, __l); } - hash_multiset(const value_type* __f, const value_type* __l, size_type __n, + /// @deprecated Use std::unordered_multiset + NCBI_DEPRECATED hash_multiset(const value_type* __f, const value_type* __l, size_type __n, const hasher& __hf) : _M_ht(__n, __hf, key_equal(), allocator_type()) { _M_ht.insert_equal(__f, __l); } - hash_multiset(const value_type* __f, const value_type* __l, size_type __n, + /// @deprecated Use std::unordered_multiset + NCBI_DEPRECATED hash_multiset(const value_type* __f, const value_type* __l, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a = allocator_type()) : _M_ht(__n, __hf, __eql, __a) { _M_ht.insert_equal(__f, __l); } - hash_multiset(const_iterator __f, const_iterator __l) + /// @deprecated Use std::unordered_multiset + NCBI_DEPRECATED hash_multiset(const_iterator __f, const_iterator __l) : _M_ht(100, hasher(), key_equal(), allocator_type()) { _M_ht.insert_equal(__f, __l); } - hash_multiset(const_iterator __f, const_iterator __l, size_type __n) + /// @deprecated Use std::unordered_multiset + NCBI_DEPRECATED hash_multiset(const_iterator __f, const_iterator __l, size_type __n) : _M_ht(__n, hasher(), key_equal(), allocator_type()) { _M_ht.insert_equal(__f, __l); } - hash_multiset(const_iterator __f, const_iterator __l, size_type __n, + /// @deprecated Use std::unordered_multiset + NCBI_DEPRECATED hash_multiset(const_iterator __f, const_iterator __l, size_type __n, const hasher& __hf) : _M_ht(__n, __hf, key_equal(), allocator_type()) { _M_ht.insert_equal(__f, __l); } - hash_multiset(const_iterator __f, const_iterator __l, size_type __n, + /// @deprecated Use std::unordered_multiset + NCBI_DEPRECATED hash_multiset(const_iterator __f, const_iterator __l, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a = allocator_type()) : _M_ht(__n, __hf, __eql, __a) diff --git a/c++/include/corelib/impl/ncbi_atomic_defs.h b/c++/include/corelib/impl/ncbi_atomic_defs.h index ae46601f..64b817aa 100644 --- a/c++/include/corelib/impl/ncbi_atomic_defs.h +++ b/c++/include/corelib/impl/ncbi_atomic_defs.h @@ -1,7 +1,7 @@ #ifndef CORELIB___NCBI_ATOMIC_DEFS__HPP #define CORELIB___NCBI_ATOMIC_DEFS__HPP -/* $Id: ncbi_atomic_defs.h 471651 2015-06-30 12:52:35Z vasilche $ +/* $Id: ncbi_atomic_defs.h 503972 2016-06-09 18:47:13Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -90,7 +90,7 @@ extern "C" { # define NCBI_SWAP_POINTERS_EXTERN 1 #endif -#if defined(NCBI_HAVE_CXX11) +#if defined(NCBI_HAVE_CXX11) && !defined(NCBI_COMPILER_MSVC) # include #endif @@ -130,7 +130,7 @@ extern "C" { # if defined(__sparc) && !defined(__sparcv9) # define NCBI_COUNTER_RESERVED_VALUE 0x3FFFFFFF # endif -#elif defined(NCBI_HAVE_CXX11) && !defined(NCBI_OS_MSWIN) +#elif defined(NCBI_HAVE_CXX11) && !defined(NCBI_COMPILER_MSVC) /* std::atomic<> in MSVC has non-default constructor so static CAtomicCounter couldn't be initialized in MT-safe manner */ typedef size_t TNCBIAtomicValue; diff --git a/c++/include/corelib/impl/ncbi_dbsvcmapper.hpp b/c++/include/corelib/impl/ncbi_dbsvcmapper.hpp index 0ecbbbd0..d4b0a2c9 100644 --- a/c++/include/corelib/impl/ncbi_dbsvcmapper.hpp +++ b/c++/include/corelib/impl/ncbi_dbsvcmapper.hpp @@ -1,7 +1,7 @@ #ifndef CORELIB___DB_SERVICE_MAPPER__HPP #define CORELIB___DB_SERVICE_MAPPER__HPP -/* $Id: ncbi_dbsvcmapper.hpp 414127 2013-09-20 16:02:32Z ucko $ +/* $Id: ncbi_dbsvcmapper.hpp 501812 2016-05-18 22:51:45Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -37,15 +37,53 @@ #include #include +#ifdef NCBI_OS_MSWIN +# include +#endif BEGIN_NCBI_SCOPE /////////////////////////////////////////////////////////////////////////////// -/// Forward declaration +/// Forward declarations /// +class CDBServer; +class IDBServiceMapper; class IRegistry; +/////////////////////////////////////////////////////////////////////////////// +/// I_ConnectionExtra +/// + +class I_ConnectionExtra +{ +public: + virtual ~I_ConnectionExtra(void) { } + +#ifdef NCBI_OS_MSWIN + typedef SOCKET TSockHandle; +#else + typedef int TSockHandle; +#endif + + /// Get OS handle of the socket represented by the connection + virtual TSockHandle GetLowLevelHandle(void) const = 0; + + virtual void SetUserData(CObject* data) = 0; + template T* GetUserData(void) + { return dynamic_cast(x_GetUserData()); } + template const T* GetUserData(void) const + { return dynamic_cast(x_GetUserData()); } + +protected: + virtual CObject* x_GetUserData(void) const = 0; + virtual void x_RecordServer(const CDBServer& server) { } + +private: + friend class IDBServiceMapper; +}; + + /////////////////////////////////////////////////////////////////////////////// /// IDBServiceMapper /// @@ -127,6 +165,18 @@ public: virtual void SetPreference(const string& service, const TSvrRef& preferred_server, double preference = 100) = 0; + + /// Given a connection that succeeded even though this service + /// mapper was unable to identify a good server beforehand, try to + /// determine which server it actually reached on the basis of its + /// low-level handle (if available); on success, pass the result + /// to its x_RecordServer method to inform subsequent logging. + /// @return true if successful, false otherwise. + virtual bool RecordServer(I_ConnectionExtra& extra) const { return false; } + +protected: + static void x_RecordServer(I_ConnectionExtra& extra, CDBServer& server) + { extra.x_RecordServer(server); } }; /////////////////////////////////////////////////////////////////////////////// diff --git a/c++/include/corelib/ncbi_base64.h b/c++/include/corelib/ncbi_base64.h index f0bbf956..7d0ef1b0 100644 --- a/c++/include/corelib/ncbi_base64.h +++ b/c++/include/corelib/ncbi_base64.h @@ -1,7 +1,7 @@ #ifndef CORELIB___NCBI_BASE64__H #define CORELIB___NCBI_BASE64__H -/* $Id: ncbi_base64.h 394628 2013-04-04 15:46:39Z kazimird $ +/* $Id: ncbi_base64.h 501322 2016-05-13 16:01:34Z vakatov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -90,9 +90,9 @@ extern NCBI_XNCBI_EXPORT int/*bool*/ BASE64_Decode * was successful. */ typedef enum { - eBase64_OK, /** Transcoded successfully. */ - eBase64_BufferTooSmall, /** The output buffer is too small. */ - eBase64_InvalidInput /** Input contains characters outside alphabet. */ + eBase64_OK, /**< Transcoded successfully. */ + eBase64_BufferTooSmall, /**< The output buffer is too small. */ + eBase64_InvalidInput /**< Input contains characters outside alphabet. */ } EBase64_Result; diff --git a/c++/include/corelib/ncbi_config.hpp b/c++/include/corelib/ncbi_config.hpp index 9260ffa3..a0366397 100644 --- a/c++/include/corelib/ncbi_config.hpp +++ b/c++/include/corelib/ncbi_config.hpp @@ -1,7 +1,7 @@ #ifndef CORELIB___NCBI_CONFIG__HPP #define CORELIB___NCBI_CONFIG__HPP -/* $Id: ncbi_config.hpp 492407 2016-02-17 15:08:33Z ivanov $ +/* $Id: ncbi_config.hpp 492280 2016-02-16 16:42:42Z sadyrovr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/corelib/ncbi_cookies.hpp b/c++/include/corelib/ncbi_cookies.hpp index e7b73fcc..e7039164 100644 --- a/c++/include/corelib/ncbi_cookies.hpp +++ b/c++/include/corelib/ncbi_cookies.hpp @@ -1,7 +1,7 @@ #ifndef CORELIB___NCBI_COOKIES__HPP #define CORELIB___NCBI_COOKIES__HPP -/* $Id: ncbi_cookies.hpp 458676 2015-02-09 12:35:49Z lavr $ +/* $Id: ncbi_cookies.hpp 517040 2016-10-20 11:22:39Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -107,9 +107,10 @@ public: /// encoded - the caller is responsible for providing a valid value. /// @sa AsString() void SetValue(const CTempString& value); - /// Set cookie's domain. No validation is performed immediately, but - /// if the value is invalid CHttpCookieExcepion will be thrown on - /// an attempt to get the cookie as a string. + /// Set cookie's domain. The value is converted to lower case and + /// the leading '.' is trimmed (if any). No other validation is performed + /// immediately, but if the value is invalid CHttpCookieExcepion will be + /// thrown on an attempt to get the cookie as a string. /// @sa AsString() void SetDomain(const CTempString& domain); /// Set host-only flag. If the flag is true, the domain must be identical @@ -472,6 +473,10 @@ inline void CHttpCookie::SetValue(const CTempString& value) inline void CHttpCookie::SetDomain(const CTempString& domain) { m_Domain = domain; + if (m_Domain.empty()) return; + // Ignore leading '.' + if (m_Domain[0] == '.') m_Domain = m_Domain.substr(1); + NStr::ToLower(m_Domain); } inline void CHttpCookie::SetPath(const CTempString& path) diff --git a/c++/include/corelib/ncbi_param.hpp b/c++/include/corelib/ncbi_param.hpp index 9ad97ac1..0759bd90 100644 --- a/c++/include/corelib/ncbi_param.hpp +++ b/c++/include/corelib/ncbi_param.hpp @@ -1,7 +1,7 @@ #ifndef CORELIB___NCBI_PARAM__HPP #define CORELIB___NCBI_PARAM__HPP -/* $Id: ncbi_param.hpp 445853 2014-09-09 13:27:06Z grichenk $ +/* $Id: ncbi_param.hpp 505730 2016-06-28 15:29:57Z elisovdn $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -235,7 +235,7 @@ double NCBI_XNCBI_EXPORT g_GetConfigDouble(const char* section, const TParamDesc& descr) \ { return CEnumParser< type, ptype >::EnumToString(val, descr); } -// Defenition of SNcbiParamDesc_XXXX static members common for normal +// Definition of SNcbiParamDesc_XXXX static members common for normal // and enum parameters. #define X_NCBI_PARAM_STATIC_DEF(descname, defval) \ descname::TStaticValue descname::sm_Default = defval; \ @@ -268,6 +268,11 @@ double NCBI_XNCBI_EXPORT g_GetConfigDouble(const char* section, /// Enum parameter declaration. In addition to NCBI_PARAM_DECL also /// specializes CParamParser to convert between strings and /// enum values. +/// @attention +/// Only use this macro in the global or "ncbi" namespace, otherwise you will +/// get compilation errors. Using this macro in the said namespaces will not +/// affect usability of a created CParamParser specialization +/// from other namespaces. /// @sa NCBI_PARAM_ENUM_ARRAY /// @sa NCBI_PARAM_ENUM_DEF #define NCBI_PARAM_ENUM_DECL(type, section, name) \ @@ -279,6 +284,11 @@ double NCBI_XNCBI_EXPORT g_GetConfigDouble(const char* section, /// Same as NCBI_PARAM_ENUM_DECL but with export specifier (e.g. NCBI_XNCBI_EXPORT) +/// @attention +/// Only use this macro in the global or "ncbi" namespace, otherwise you will +/// get compilation errors. Using this macro in the said namespaces will not +/// affect usability of a created CParamParser specialization +/// from other namespaces. /// @sa NCBI_PARAM_ENUM_DECL #define NCBI_PARAM_ENUM_DECL_EXPORT(expname, type, section, name) \ struct expname X_NCBI_PARAM_DECLNAME(section, name); \ diff --git a/c++/include/corelib/ncbi_stack.hpp b/c++/include/corelib/ncbi_stack.hpp index c5d73d46..b9ed26c9 100644 --- a/c++/include/corelib/ncbi_stack.hpp +++ b/c++/include/corelib/ncbi_stack.hpp @@ -1,7 +1,7 @@ #ifndef CORELIB___NCBI_STACK__HPP #define CORELIB___NCBI_STACK__HPP -/* $Id: ncbi_stack.hpp 379373 2012-10-31 15:06:17Z grichenk $ +/* $Id: ncbi_stack.hpp 500861 2016-05-09 16:32:20Z grichenk $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -52,17 +52,22 @@ public: string func; string file; string module; + const void* addr; size_t offs; size_t line; - SStackFrameInfo() - : offs(0), line(0) {} + SStackFrameInfo(void) + : addr(0), offs(0), line(0) {} + + SStackFrameInfo(const void* address) + : addr(address), offs(0), line(0) {} bool operator ==(const SStackFrameInfo& other) const { return func == other.func && file == other.file && module == other.module && + addr == other.addr && offs == other.offs && line == other.line; } diff --git a/c++/include/corelib/ncbi_xstr.hpp b/c++/include/corelib/ncbi_xstr.hpp index 25de3b26..a12deae9 100644 --- a/c++/include/corelib/ncbi_xstr.hpp +++ b/c++/include/corelib/ncbi_xstr.hpp @@ -1,7 +1,7 @@ #ifndef CORELIB___NCBI_XSTR__HPP #define CORELIB___NCBI_XSTR__HPP -/* $Id: ncbi_xstr.hpp 372736 2012-08-22 13:12:59Z gouriano $ +/* $Id: ncbi_xstr.hpp 500405 2016-05-04 15:18:35Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -76,18 +76,18 @@ public: : m_Data(str), m_Length(NPOS) { } - CTempXStr(const _TChar* str, size_t length) - : m_Data(str), m_Length(length) + CTempXStr(const _TChar* str, size_t len) + : m_Data(str), m_Length(len) { } - CTempXStr(const _TChar* str, size_t pos, size_t length) + CTempXStr(const _TChar* str, size_t pos, size_t len) { if (pos == x_npos()) { m_Data = str; m_Length = 0; } else { m_Data = str+pos; - m_Length = length; + m_Length = len; } } @@ -96,22 +96,22 @@ public: : m_Data(str.data()), m_Length(str.length()) { } - CTempXStr(const basic_string<_TChar>& str, size_t length) - : m_Data(str.data()), m_Length(length) + CTempXStr(const basic_string<_TChar>& str, size_t len) + : m_Data(str.data()), m_Length(len) { } - CTempXStr(const basic_string<_TChar>& str, size_t pos, size_t length) - : m_Data(str.data()+pos), m_Length(length) + CTempXStr(const basic_string<_TChar>& str, size_t pos, size_t len) + : m_Data(str.data()+pos), m_Length(len) { if (pos == x_npos()) { m_Data = str.data(); m_Length = 0; } else { m_Data = str.data()+pos; - if (length == x_npos()) { + if (len == x_npos()) { m_Length = str.length() - pos; } else { - m_Length = length; + m_Length = len; if (m_Length + pos > str.length()) { m_Length = str.length() - pos; } diff --git a/c++/include/corelib/ncbiapp.hpp b/c++/include/corelib/ncbiapp.hpp index 8d86fa4d..a7d49ac2 100644 --- a/c++/include/corelib/ncbiapp.hpp +++ b/c++/include/corelib/ncbiapp.hpp @@ -1,7 +1,7 @@ #ifndef CORELIB___NCBIAPP__HPP #define CORELIB___NCBIAPP__HPP -/* $Id: ncbiapp.hpp 497376 2016-04-06 13:21:22Z ivanov $ +/* $Id: ncbiapp.hpp 518670 2016-11-07 15:25:48Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -431,6 +431,7 @@ protected: /// @sa GetVersion void SetVersion(const CVersionInfo& version); void SetVersion(const CVersionInfo& version, const SBuildInfo& build_info); + void SetVersionByBuild(int major); /// Set version data for the program. /// @@ -559,6 +560,13 @@ private: /// Registry to read from. If NULL, use the current registry setting. void x_HonorStandardSettings(IRegistry* reg = 0); + /// Read switches that are stored in m_LogOptions from registry and + /// environment + void x_ReadLogOptions(); + + /// Log environment, registry, command arguments, path + void x_LogOptions(int event); + /// Setup C++ standard I/O streams' behaviour. /// /// Called from AppMain() to do compiler-specific optimization @@ -602,6 +610,7 @@ private: string m_DefaultConfig; ///< conf parameter to AppMain bool m_ConfigLoaded; ///< Finished loading config const char* m_LogFile; ///< Logfile if set in the command line + int m_LogOptions; ///< logging of env, reg, args, path }; diff --git a/c++/include/corelib/ncbiargs.hpp b/c++/include/corelib/ncbiargs.hpp index 144403f7..b21ea098 100644 --- a/c++/include/corelib/ncbiargs.hpp +++ b/c++/include/corelib/ncbiargs.hpp @@ -1,7 +1,7 @@ #ifndef CORELIB___NCBIARGS__HPP #define CORELIB___NCBIARGS__HPP -/* $Id: ncbiargs.hpp 491416 2016-02-04 17:55:07Z ivanov $ +/* $Id: ncbiargs.hpp 497224 2016-04-05 12:11:44Z gouriano $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -104,6 +104,7 @@ BEGIN_NCBI_SCOPE class CNcbiArguments; class CArgAllow; class CDir; +class CArgDependencyGroup; ///////////////////////////////////////////////////////////////////////////// @@ -874,6 +875,16 @@ public: const string& arg_name, const string& comment = kEmptyStr); + /// Add a dependency group. + /// The argument constraints specified by the dependency group(s) + /// will be processed only after all regular dependencies for arguments and + /// dependency groups have been processed. + /// @attention + /// The "dep_group" will be added by reference, and its lifetime will then + /// be managed according to the usual CObject/CRef rules. + /// @sa SetDependency() + void AddDependencyGroup(CArgDependencyGroup* dep_group); + /// Flag to invert constraint logically enum EConstraintNegate { eConstraintInvert, ///< Logical NOT @@ -1069,6 +1080,7 @@ private: EArgPositionalMode m_PositionalMode; ///< Processing of positional args TDependencies m_Dependencies; ///< Arguments' dependencies TMiscFlags m_MiscFlags; ///< Flags for USAGE, error handling etc. + set< CConstRef > m_DependencyGroups; // Extra USAGE info protected: @@ -1179,6 +1191,7 @@ protected: ~CPrintUsageXml(); void PrintArguments(const CArgDescriptions& desc) const; private: + const CArgDescriptions& m_desc; CNcbiOstream& m_out; }; @@ -1799,6 +1812,90 @@ private: string m_Comment; ///< Argument description }; +///////////////////////////////////////////////////////////////////////////// + +class NCBI_XNCBI_EXPORT CArgDependencyGroup : public CObject +{ +public: + /// Create new dependency group. + /// @param name + /// Name of the group + /// @param description + /// User-provided description of the dependency group (for Usage). + /// A generated description will be added to it. + static CRef Create( + const string& name, const string& description = kEmptyStr); + + virtual ~CArgDependencyGroup(void); + + /// @param min_members + /// Mark this group as "set" (in the context of + /// CArgDescriptions::EDependency) if at least "min_members" of its + /// members (args or groups listed in this group) are set. + /// @note This condition can be weakened by "eInstantSet" mechanism. + /// @sa EInstantSet + /// @return "*this" + CArgDependencyGroup& SetMinMembers(size_t min_members); + + /// @param max_members + /// No more than "max_members" of members (args or immediate groups + /// listed in this group) are allowed to be in the "set" state. + /// If this condition is not met, then this group will be marked + /// as "not set". + /// @return "*this" + CArgDependencyGroup& SetMaxMembers(size_t max_members); + + /// Control whether the "setting" of this particular member marks the + /// whole group as "set" regardless of the value passed to SetMinMembers() + /// @sa SetMinMembers(), Add() + enum EInstantSet { + eNoInstantSet, + eInstantSet + }; + + /// Make a regular argument a member of this dependency group. + /// An argument with this name will need to be added separately using + /// CArgDescriptions::AddXXX(). + /// @param arg_name + /// Name of the argument, as specified in CArgDescriptions::AddXXX() + /// @param instant_set + /// "eInstantSet" means that if the added argument ("arg_name") is + /// set, then the SetMinMembers() condition doesn't apply anymore. + /// @return "*this" + CArgDependencyGroup& Add(const string& arg_name, + EInstantSet instant_set = eNoInstantSet); + + /// Make another dependency group a member of this dependency group. + /// @attention + /// The "dep_group" will be added by reference, and its lifetime will + /// be managed according to the usual CObject/CRef rules. + /// @param instant_set + /// "eInstantSet" means that if the added group ("dep_group") is + /// set, then the SetMinMembers() condition doesn't apply anymore. + /// @return "*this" + CArgDependencyGroup& Add(CArgDependencyGroup* dep_group, + EInstantSet instant_set = eNoInstantSet); + +private: + bool x_Evaluate( const CArgs& args, string* arg_set, string* arg_unset) const; + + string m_Name; + string m_Description; + size_t m_MinMembers, m_MaxMembers; + map m_Arguments; + map, EInstantSet> m_Groups; + + // prohibit unwanted ctors and assignments + CArgDependencyGroup(void); + CArgDependencyGroup( const CArgDependencyGroup& dep_group); + CArgDependencyGroup& operator= (const CArgDependencyGroup&); + +public: + void PrintUsage(list& arr, size_t offset) const; + void PrintUsageXml(CNcbiOstream& out) const; + void Evaluate( const CArgs& args) const; +}; + END_NCBI_SCOPE diff --git a/c++/include/corelib/ncbiatomic.h b/c++/include/corelib/ncbiatomic.h index 2b6fd70d..24d82457 100644 --- a/c++/include/corelib/ncbiatomic.h +++ b/c++/include/corelib/ncbiatomic.h @@ -1,7 +1,7 @@ #ifndef NCBIATOMIC__H #define NCBIATOMIC__H -/* $Id: ncbiatomic.h 434180 2014-05-05 14:10:19Z ucko $ +/* $Id: ncbiatomic.h 503985 2016-06-09 20:21:58Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -68,7 +68,7 @@ void* NCBI_SwapPointers(void * volatile * location, void* new_value) #else { void** nv_loc = (void**) location; -# ifdef NCBI_HAVE_CXX11 +# if defined(NCBI_HAVE_CXX11) && !defined(NCBI_COMPILER_MSVC) if (sizeof(std::atomic) == sizeof(void*)) { std::atomic& a = *(std::atomic*)nv_loc; return a.exchange(new_value); diff --git a/c++/include/corelib/ncbictype.hpp b/c++/include/corelib/ncbictype.hpp index f93c447d..c0409cbc 100644 --- a/c++/include/corelib/ncbictype.hpp +++ b/c++/include/corelib/ncbictype.hpp @@ -1,7 +1,7 @@ #ifndef CORELIB___NCBICTYPE__HPP #define CORELIB___NCBICTYPE__HPP -/* $Id: ncbictype.hpp 453380 2014-12-03 14:39:19Z ucko $ +/* $Id: ncbictype.hpp 500405 2016-05-04 15:18:35Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -49,11 +49,14 @@ BEGIN_STD_NAMESPACE; -#define NCBI_DEFINE_CTYPE_FUNC(name) \ - inline int name(Uchar c) { return name(int(c)); } \ - inline int name(char c) { return name(Uchar(c)); } \ - template inline int name(C c) \ - { return See_the_standard_on_proper_argument_type_for_ctype_functions(c); } +#define NCBI_DEFINE_CTYPE_FUNC(name) \ + inline int name(Uchar c) { return name(int(c)); } \ + inline int name(char c) { return name(Uchar(c)); } \ + template inline int name(C c) \ + { \ + return See_the_standard_on_proper_argument_type_for_ctype_functions(c); \ + return 0; /* to avoid a compilation warning */ \ + } NCBI_DEFINE_CTYPE_FUNC(isalpha) NCBI_DEFINE_CTYPE_FUNC(isalnum) diff --git a/c++/include/corelib/ncbidbg.hpp b/c++/include/corelib/ncbidbg.hpp index d8f2920b..361ee9b1 100644 --- a/c++/include/corelib/ncbidbg.hpp +++ b/c++/include/corelib/ncbidbg.hpp @@ -1,7 +1,7 @@ #ifndef CORELIB___NCBIDBG__HPP #define CORELIB___NCBIDBG__HPP -/* $Id: ncbidbg.hpp 491449 2016-02-04 19:41:49Z ivanov $ +/* $Id: ncbidbg.hpp 491415 2016-02-04 17:54:53Z grichenk $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/corelib/ncbidiag.hpp b/c++/include/corelib/ncbidiag.hpp index 12ce5485..ec5fe112 100644 --- a/c++/include/corelib/ncbidiag.hpp +++ b/c++/include/corelib/ncbidiag.hpp @@ -1,7 +1,7 @@ #ifndef CORELIB___NCBIDIAG__HPP #define CORELIB___NCBIDIAG__HPP -/* $Id: ncbidiag.hpp 500364 2016-05-04 12:04:46Z ivanov $ +/* $Id: ncbidiag.hpp 514369 2016-09-21 15:22:25Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -36,7 +36,7 @@ /// Defines NCBI C++ diagnostic APIs, classes, and macros. /// /// More elaborate documentation could be found in: -/// http://www.ncbi.nlm.nih.gov/toolkit/doc/book/ch_core/#ch_core.diag +/// http://ncbi.github.io/cxx-toolkit/pages/ch_log.html #include @@ -189,6 +189,12 @@ NCBI_XNCBI_EXPORT const char* g_DiagUnknownFunction(void); // When printing a message in 'old' (human readable) format LOG_POST skips // all fields except the message. +/// This macro is deprecated and it's strongly recomended to move +/// in all projects (except tests) to macro LOG_POST_X to make possible more +/// flexible error statistics and logging. +/// +/// @sa +/// LOG_POST_EX, LOG_POST_X #define LOG_POST(message) \ ( NCBI_NS_NCBI::CNcbiDiag(DIAG_COMPILE_INFO, \ NCBI_NS_NCBI::eDiag_Error, \ @@ -274,7 +280,7 @@ NCBI_XNCBI_EXPORT const char* g_DiagUnknownFunction(void); }; \ }; \ } \ - extern void err_code_x__dummy_for_semicolon(void) + NCBI_EAT_SEMICOLON(err_code) /// Define maximum value of subcode for the error code currently in use. /// Currently used error code is defined by macro NCBI_USE_ERRCODE_X. This @@ -400,7 +406,7 @@ struct WRONG_USAGE_OF_DEFINE_ERR_SUBCODE_MACRO { NCBI_NS_NCBI::WRONG_USAGE_OF_DEFINE_ERR_SUBCODE_MACRO < \ NCBI_ERRCODE_X_NAME(name), \ NCBI_NS_NCBI::err_code_x::eErrCodeX_Max_##name != 0> \ - err_subcode) \ + /*err_subcode*/) \ {} @@ -505,10 +511,10 @@ struct WRONG_USAGE_OF_DEFINE_ERR_SUBCODE_MACRO { /// All calls to ERR_POST_X under the same default error code /// MUST be with deferent error subcodes to make possible more /// flexible error statistics and logging. -/// If using of macro leads to compile errors containing in message strings -/// like "err_code_x" or "ErrCodeX" then you didn't defined error code name -/// with NCBI_DEFINE_ERRCODE_X macro or didn't selected current default -/// error code with valid NCBI_USE_ERRCODE_X definition. +/// If using the macro leads to compile errors containing strings +/// like "err_code_x" or "ErrCodeX" in messages, it means you didn't define +/// error code name with NCBI_DEFINE_ERRCODE_X macro or didn't select current +/// default error code with valid NCBI_USE_ERRCODE_X definition. /// This macro allows the use of only constant error subcodes /// (integer literals or enum constants). If you need to make variable error /// subcode you need to use macro ERR_POST_EX as follows: @@ -1777,6 +1783,7 @@ enum EPostNumberIncrement { struct SRequestCtxWrapper; class CRequestContext; +class CSharedHitId; class CRequestRateControl; class CEncodedString; @@ -2221,7 +2228,7 @@ public: /// or Log.Http_Hit_Id/Log.Hit_Id values in the INI file. The Http-value /// has higher priority. If none of the values is set, the default hit id /// is generated automatically. - string GetDefaultHitID(void) const { return x_GetDefaultHitID(eHitID_Create); } + string GetDefaultHitID(void) const; /// Set new global default hit id. This value is used only if the per-request /// hit id is not set. @@ -2338,7 +2345,8 @@ private: // Check if current state is 'PB/P/PE'. bool x_DiagAtApplicationLevel(void) const; bool x_IsSetDefaultHitID(void) const; - string x_GetDefaultHitID(EDefaultHitIDFlags flag) const; + CSharedHitId x_GetDefaultHitID(EDefaultHitIDFlags flag) const; + string x_GetNextHitID(bool is_default) const; void x_LogHitID(void) const; void x_LogHitID_WithLock(void) const; // Same as above but with mutex lock. @@ -2349,21 +2357,21 @@ private: static TPID sm_PID; mutable TUID m_UID; - mutable unique_ptr m_Host; + mutable unique_ptr m_Host; string m_HostIP; - unique_ptr m_Username; - unique_ptr m_AppName; + unique_ptr m_Username; + unique_ptr m_AppName; mutable bool m_AppNameSet; - mutable unique_ptr m_DefaultSessionId; - mutable unique_ptr m_DefaultHitId; + mutable unique_ptr m_DefaultSessionId; + mutable unique_ptr m_DefaultHitId; mutable bool m_LoggedHitId; int m_ExitCode; bool m_ExitCodeSet; int m_ExitSig; EDiagAppState m_AppState; TProperties m_Properties; - unique_ptr m_StopWatch; - unique_ptr m_Messages; + unique_ptr m_StopWatch; + unique_ptr m_Messages; size_t m_MaxMessages; static CDiagContext* sm_Instance; @@ -2371,9 +2379,9 @@ private: static bool sm_ApplogSeverityLocked; // Rate control - unique_ptr m_AppLogRC; - unique_ptr m_ErrLogRC; - unique_ptr m_TraceLogRC; + unique_ptr m_AppLogRC; + unique_ptr m_ErrLogRC; + unique_ptr m_TraceLogRC; bool m_AppLogSuspended; bool m_ErrLogSuspended; bool m_TraceLogSuspended; @@ -2453,7 +2461,8 @@ extern void SetDiagHandler(CDiagHandler* handler, /// Get the currently set diagnostic handler class. NCBI_XNCBI_EXPORT -extern CDiagHandler* GetDiagHandler(bool take_ownership = false); +extern CDiagHandler* GetDiagHandler(bool take_ownership = false, + bool* current_ownership = 0); /// Set the diagnostic handler using the specified diagnostic handler /// and cleanup functions. diff --git a/c++/include/corelib/ncbidiag.inl b/c++/include/corelib/ncbidiag.inl index a8a781d3..a185e009 100644 --- a/c++/include/corelib/ncbidiag.inl +++ b/c++/include/corelib/ncbidiag.inl @@ -1,7 +1,7 @@ #if defined(CORELIB___NCBIDIAG__HPP) && !defined(CORELIB___NCBIDIAG__INL) #define CORELIB___NCBIDIAG__INL -/* $Id: ncbidiag.inl 461881 2015-03-13 13:39:13Z vasilche $ +/* $Id: ncbidiag.inl 503553 2016-06-06 15:54:54Z grichenk $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -100,7 +100,8 @@ class CDiagBuffer // Handler NCBI_XNCBI_EXPORT friend void SetDiagHandler(CDiagHandler* handler, bool can_delete); - NCBI_XNCBI_EXPORT friend CDiagHandler* GetDiagHandler(bool take_ownership); + NCBI_XNCBI_EXPORT friend CDiagHandler* GetDiagHandler(bool take_ownership, + bool* current_ownership); NCBI_XNCBI_EXPORT friend bool IsSetDiagHandler(void); // Error code information diff --git a/c++/include/corelib/ncbierror.hpp b/c++/include/corelib/ncbierror.hpp index b780f4b2..45313c9b 100644 --- a/c++/include/corelib/ncbierror.hpp +++ b/c++/include/corelib/ncbierror.hpp @@ -1,7 +1,7 @@ #ifndef CORELIB___NCBIERROR__HPP #define CORELIB___NCBIERROR__HPP -/* $Id: ncbierror.hpp 458676 2015-02-09 12:35:49Z lavr $ +/* $Id: ncbierror.hpp 511430 2016-08-22 15:25:37Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -169,17 +169,20 @@ public: /// Copy constructor CNcbiError(const CNcbiError& err) - : m_Code(err.m_Code), m_Category(err.m_Category) - , m_Native(err.m_Native), m_Extra(err.m_Extra) {} + : m_Code(err.m_Code), + m_Category(err.m_Category), + m_Native(err.m_Native), + m_Extra(err.m_Extra) + {} - ~CNcbiError(void){} + ~CNcbiError(void) {} /// Assignment. CNcbiError& operator= (const CNcbiError& err) { - m_Code = err.m_Code; - m_Category= err.m_Category; - m_Native = err.m_Native; - m_Extra = err.m_Extra; + m_Code = err.m_Code; + m_Category = err.m_Category; + m_Native = err.m_Native; + m_Extra = err.m_Extra; return *this; } @@ -202,7 +205,15 @@ public: /// Error code /// @param extra /// Additional information - static void Set(ECode code, const CTempString& extra = CTempString()); + static void Set(ECode code); + /// @copydoc CNcbiError::Set(ECode) + static void Set(ECode code, const CTempString extra); + /// @copydoc CNcbiError::Set(ECode) + static void Set(ECode code, const char* extra); + /// @copydoc CNcbiError::Set(ECode) + static void Set(ECode code, const string& extra); + /// @copydoc CNcbiError::Set(ECode) + static void Set(ECode code, string&& extra); /// Set last error using errno code /// @@ -210,14 +221,29 @@ public: /// "errno" code /// @param extra /// Additional information - static void SetErrno(int errno_code, - const CTempString& extra = CTempString()); + static void SetErrno(int errno_code); + /// @copydoc CNcbiError::SetErrno(int) + static void SetErrno(int errno_code, const CTempString extra); + /// @copydoc CNcbiError::SetErrno(int) + static void SetErrno(int errno_code, const string& extra); + /// @copydoc CNcbiError::SetErrno(int) + static void SetErrno(int errno_code, const char* extra); + /// @copydoc CNcbiError::SetErrno(int) + static void SetErrno(int errno_code, string&& extra); /// Set last error using current "errno" code /// /// @param extra /// Additional information - static void SetFromErrno(const CTempString& extra = CTempString()); + static void SetFromErrno(void); + /// @copydoc CNcbiError::SetFromErrno(void) + static void SetFromErrno(const CTempString extra); + /// @copydoc CNcbiError::SetFromErrno(void) + static void SetFromErrno(const string& extra); + /// @copydoc CNcbiError::SetFromErrno(void) + static void SetFromErrno(const char* extra); + /// @copydoc CNcbiError::SetFromErrno(void) + static void SetFromErrno(string&& extra); #if defined(NCBI_OS_MSWIN) /// Set last error using Windows-specific error code @@ -229,8 +255,15 @@ public: /// @note /// Not all Windows errors can be translated into ECode enum. /// In this case, Code() will return 'eUnknown' - static void SetWindowsError(int native_err_code, - const CTempString& extra = CTempString()); + static void SetWindowsError(int native_err_code); + /// @copydoc CNcbiError::SetWindowsError(int) + static void SetWindowsError(int native_err_code, const CTempString extra); + /// @copydoc CNcbiError::SetWindowsError(int) + static void SetWindowsError(int native_err_code, const string& extra); + /// @copydoc CNcbiError::SetWindowsError(int) + static void SetWindowsError(int native_err_code, const char* extra); + /// @copydoc CNcbiError::SetWindowsError(int) + static void SetWindowsError(int native_err_code, string&& extra); /// Set last error on MS Windows using GetLastError() /// @@ -239,13 +272,29 @@ public: /// @note /// Not all Windows errors can be translated into ECode enum. /// In this case, Code() will return 'eUnknown' - static void SetFromWindowsError(const CTempString& extra = CTempString()); + static void SetFromWindowsError(void); + /// @copydoc CNcbiError::SetFromWindowsError(void) + static void SetFromWindowsError(const CTempString extra); + /// @copydoc CNcbiError::SetFromWindowsError(void) + static void SetFromWindowsError(const string& extra); + /// @copydoc CNcbiError::SetFromWindowsError(void) + static void SetFromWindowsError(const char* extra); + /// @copydoc CNcbiError::SetFromWindowsError(void) + static void SetFromWindowsError(string&& extra); #endif /* NCBI_OS_MSWIN */ protected: // Prohibit creation of 'empty' error object CNcbiError(void); +private: + static CNcbiError* x_Init(int err_code); + template + static CNcbiError* x_Init(int err_code, Ty extra); +#ifdef NCBI_OS_MSWIN + static void x_SetWindowsCodeCategory(CNcbiError* e); +#endif + private: mutable ECode m_Code; ECategory m_Category; diff --git a/c++/include/corelib/ncbifile.hpp b/c++/include/corelib/ncbifile.hpp index b3207494..bc218b5d 100644 --- a/c++/include/corelib/ncbifile.hpp +++ b/c++/include/corelib/ncbifile.hpp @@ -1,7 +1,7 @@ #ifndef CORELIB___NCBIFILE__HPP #define CORELIB___NCBIFILE__HPP -/* $Id: ncbifile.hpp 497376 2016-04-06 13:21:22Z ivanov $ +/* $Id: ncbifile.hpp 515654 2016-10-04 18:38:59Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -391,7 +391,8 @@ public: /// How to interpret relative paths. /// @sa CreateAbsolutePath enum ERelativeToWhat { - eRelativeToCwd, ///< Relative to the current working directory + /// Relative to the current working directory. + eRelativeToCwd, /// Relative to the executable's location. If the executable was /// invoked via a symlink, search the directory containing the symlink /// before the directory (if different) containing the actual binary. @@ -409,10 +410,24 @@ public: /// Corresponding absolute path. May be the original string (if already /// absolute) or the starting point indicated by rtw (if the input was /// empty or "."). - /// @sa ERelativeToWhat + /// @sa ERelativeToWhat, CreateAbsolutePath static string CreateAbsolutePath(const string& path, ERelativeToWhat rtw = eRelativeToCwd); + /// Get an absolute path from some, possibly relative, path. + /// + /// @param path + /// Path to resolve, in native syntax; returned as is if absolute. + /// @param rtw + /// Starting point for relative path resolution. Used as base path + /// for "path" if the latter have an relative form. + /// Must be an absolute. + /// @return + /// Corresponding absolute path. May be the original string (if already + /// absolute) or concatenation of rtw and path. + /// @sa CreateAbsolutePath + static string CreateAbsolutePath(const string& path, const string& rtw); + /// Concatenate two parts of the path for the current OS. /// /// Note that the arguments must be OS-specific. @@ -1619,8 +1634,24 @@ public: static string GetHome(void); /// Get temporary directory. + /// + /// Return temporary directory name specified by OS via environment variables. + /// @sa GetAppTmpDir static string GetTmpDir(void); + /// Get temporary directory name for application. + /// + /// Return temporary directory name specified in the application's registry file or via environment. + /// Registry file: + /// [NCBI] + /// TmpDir = ... + /// Environment variable: + /// NCBI_CONFIG__NCBI__TmpDir + /// + /// If not specified, return GetTmpDir(). + /// @sa GetTmpDir + static string GetAppTmpDir(void); + /// Get the current working directory. static string GetCwd(void); @@ -2118,12 +2149,8 @@ public: /// /// Define a list of dir entries for deletion. /// -/// Each Object of this class maintains a list of names of dir entries -/// that will be deleted from the file system when the object -/// goes out of scope. -/// -/// Note: Directories will be removed recursively, symbolic links -- -/// without dir entries which they points to. +/// Each object of this class maintains a list of paths that will be deleted +/// from the file system when the object goes out of scope. class NCBI_XNCBI_EXPORT CFileDeleteList : public CObject { @@ -2131,17 +2158,25 @@ public: /// Destructor removes all dir entries on list. ~CFileDeleteList(); - typedef list TNames; + typedef list TList; + + /// Add a path for later deletion. + /// @param path + /// String that specifies the file system entry to delete. + /// It will be stored as the absolute normalized path, so relative names + /// are safe to use. + /// @note + /// Directories will be removed recursively. + /// Symbolic links -- without dir entries which they points to. + void Add(const string& path); - /// Add a dir entry for later deletion. - void Add(const string& entryname); /// Get the underlying list. - const TNames& GetNames() const; + const TList& GetList() const; /// Set the underlying list. - void SetNames(TNames& names); + void SetList(TList& list); private: - TNames m_Names; ///< List of dir entries for deletion + TList m_Paths; ///< List of dir entries for deletion }; @@ -2156,7 +2191,7 @@ class NCBI_XNCBI_EXPORT CFileDeleteAtExit { public: /// Add the name of a dir entry; it will be deleted on (normal) exit - static void Add(const string& entryname); + static void Add(const string& path); /// Get underlying static CFileDeleteList object static const CFileDeleteList& GetDeleteList(); @@ -2259,6 +2294,8 @@ struct SMemoryFileAttrs; class NCBI_XNCBI_EXPORT CMemoryFile_Base { public: + typedef Int8 TOffsetType; // signed for POSIX compatibility + /// Which operations are permitted in memory map file. typedef enum { eMMP_Read, ///< Data can be read @@ -2360,7 +2397,7 @@ public: /// EMemMapProtect, EMemMapShare, GetPtr, GetSize, GetOffset CMemoryFileSegment(SMemoryFileHandle& handle, SMemoryFileAttrs& attrs, - off_t offset, + TOffsetType offset, size_t length); /// Destructor. @@ -2381,7 +2418,7 @@ public: /// Offset in bytes of mapped area from beginning of the file. /// Always return value passed in constructor even if data /// was not successfully mapped. - off_t GetOffset(void) const; + TOffsetType GetOffset(void) const; /// Get length of the mapped area. /// @@ -2412,7 +2449,7 @@ public: /// Always return adjusted value even if data was not successfully mapped. /// @sa /// GetRealPtr, GetRealSize, GetOffset - off_t GetRealOffset(void) const; + TOffsetType GetRealOffset(void) const; /// Get real length of the mapped area. /// @@ -2460,14 +2497,14 @@ private: // Values for user void* m_DataPtr; ///< Pointer to the beginning of the mapped area. ///> The user seen this one. - off_t m_Offset; ///< Requested starting offset of the + TOffsetType m_Offset; ///< Requested starting offset of the ///< mapped area from beginning of file. size_t m_Length; ///< Requested length of the mapped area. // Internal real values void* m_DataPtrReal; ///< Real pointer to the beginning of the mapped ///< area which should be fried later. - off_t m_OffsetReal; ///< Corrected starting offset of the + TOffsetType m_OffsetReal; ///< Corrected starting offset of the ///< mapped area from beginning of file. size_t m_LengthReal; ///< Corrected length of the mapped area. @@ -2555,7 +2592,7 @@ public: /// MS Windows: If file is open in eMMP_Read mode with eMMS_Private /// protection, that memory pages will be mapped in exclusive mode, /// and any other process cannot access the same file for writing. - void* Map(off_t offset, size_t length); + void* Map(TOffsetType offset, size_t length); /// Unmap file segment. /// @@ -2582,7 +2619,7 @@ public: /// Offset in bytes of mapped segment from beginning of the file. /// Returned value is a value of "offset" parameter passed /// to Map() method for specified "ptr". - off_t GetOffset(void* ptr) const; + TOffsetType GetOffset(void* ptr) const; /// Get length of the mapped segment. /// @@ -2714,7 +2751,7 @@ public: CMemoryFile(const string& file_name, EMemMapProtect protect_attr = eMMP_Read, EMemMapShare share_attr = eMMS_Shared, - off_t offset = 0, + TOffsetType offset = 0, size_t lendth = 0, EOpenMode mode = eDefault, Uint8 max_file_len = 0); @@ -2739,7 +2776,7 @@ public: /// - NULL if mapped to a file of zero length, or if not mapped. /// @sa /// Unmap, GetPtr, GetOffset, GetSize, Extend - void* Map(off_t offset = 0, size_t length = 0); + void* Map(TOffsetType offset = 0, size_t length = 0); /// Unmap file if mapped. /// @@ -2777,7 +2814,7 @@ public: /// /// @return /// Offset in bytes of mapped area from beginning of the file. - off_t GetOffset(void) const; + TOffsetType GetOffset(void) const; /// Get length of the mapped region. /// @@ -3540,6 +3577,8 @@ private: class NCBI_XNCBI_EXPORT CFileLock { public: + typedef Int8 TOffsetType; // signed for POSIX compatibility + /// Type of file lock. /// /// Shared lock allows all processes to read from the locked portion @@ -3578,12 +3617,12 @@ public: CFileLock(const string& filename, TFlags flags = fDefault, EType type = eShared, - off_t offset = 0, + TOffsetType offset = 0, size_t length = 0); CFileLock(const char* filename, TFlags flags = fDefault, EType type = eShared, - off_t offset = 0, + TOffsetType offset = 0, size_t length = 0); /// Construct CFileLock for locking file by system file handle 'handle'. @@ -3593,7 +3632,7 @@ public: CFileLock(TFileHandle handle, TFlags flags = fDefault, EType type = eShared, - off_t offset = 0, + TOffsetType offset = 0, size_t length = 0); /// Destruct the CFileLock, close file and remove all locks if necessary. @@ -3614,7 +3653,7 @@ public: /// Number of bytes to lock. /// The value 0 means that whole file will be locked. /// @sa Unlock - void Lock(EType type, off_t offset = 0, size_t length = 0); + void Lock(EType type, TOffsetType offset = 0, size_t length = 0); /// Unlock file. /// @@ -3636,7 +3675,7 @@ public: protected: /// Auxiliary method for constructors. - void x_Init(const char* filename, EType type, off_t offset, size_t length); + void x_Init(const char* filename, EType type, TOffsetType offset, size_t length); private: TFileHandle m_Handle; ///< System file handle. @@ -3906,21 +3945,22 @@ bool CSymLink::Exists(void) const // CFileDelete* inline -void CFileDeleteList::Add(const string& entryname) +void CFileDeleteList::Add(const string& path) { - m_Names.push_back(entryname); + string p = CDirEntry::NormalizePath(CDirEntry::CreateAbsolutePath(path)); + m_Paths.push_back(p); } inline -const CFileDeleteList::TNames& CFileDeleteList::GetNames(void) const +const CFileDeleteList::TList& CFileDeleteList::GetList(void) const { - return m_Names; + return m_Paths; } inline -void CFileDeleteList::SetNames(CFileDeleteList::TNames& names) +void CFileDeleteList::SetList(CFileDeleteList::TList& list) { - m_Names = names; + m_Paths = list; } @@ -3950,7 +3990,7 @@ size_t CMemoryFileSegment::GetSize(void) const inline -off_t CMemoryFileSegment::GetOffset(void) const +CMemoryFileSegment::TOffsetType CMemoryFileSegment::GetOffset(void) const { return m_Offset; } @@ -3969,7 +4009,7 @@ size_t CMemoryFileSegment::GetRealSize(void) const inline -off_t CMemoryFileSegment::GetRealOffset(void) const +CMemoryFileSegment::TOffsetType CMemoryFileSegment::GetRealOffset(void) const { return m_OffsetReal; } @@ -3993,7 +4033,7 @@ CMemoryFileMap::GetMemoryFileSegment(void* ptr) const } inline -off_t CMemoryFileMap::GetOffset(void* ptr) const +CMemoryFileMap::TOffsetType CMemoryFileMap::GetOffset(void* ptr) const { return GetMemoryFileSegment(ptr)->GetOffset(); } @@ -4038,7 +4078,7 @@ size_t CMemoryFile::GetSize(void) const } inline -off_t CMemoryFile::GetOffset(void) const +CMemoryFile::TOffsetType CMemoryFile::GetOffset(void) const { x_Verify(); return CMemoryFileMap::GetOffset(m_Ptr); diff --git a/c++/include/corelib/ncbimisc.hpp b/c++/include/corelib/ncbimisc.hpp index c7a48cf6..7aa31678 100644 --- a/c++/include/corelib/ncbimisc.hpp +++ b/c++/include/corelib/ncbimisc.hpp @@ -1,7 +1,7 @@ #ifndef CORELIB___NCBIMISC__HPP #define CORELIB___NCBIMISC__HPP -/* $Id: ncbimisc.hpp 494187 2016-03-04 12:23:11Z ivanov $ +/* $Id: ncbimisc.hpp 500279 2016-05-03 17:12:04Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -973,6 +973,7 @@ typedef int TTaxId; //#define NCBI_STRICT_GI //#define NCBI_INT8_GI +//#define NCBI_STRICT_ENTREZ_ID #ifdef NCBI_STRICT_GI # define NCBI_INT8_GI @@ -988,41 +989,41 @@ typedef Uint8 TUintId; // Strict mode can be enabled only for Int8 GIs. -class CStrictGi +class CStrictId64 { public: - CStrictGi(void) : m_Gi(0) {} + CStrictId64(void) : m_Gi(0) {} - bool operator==(const CStrictGi& gi) const { return m_Gi == gi.m_Gi; } - bool operator!=(const CStrictGi& gi) const { return m_Gi != gi.m_Gi; } - bool operator<(const CStrictGi& gi) const { return m_Gi < gi.m_Gi; } - bool operator<=(const CStrictGi& gi) const { return m_Gi <= gi.m_Gi; } - bool operator>(const CStrictGi& gi) const { return m_Gi > gi.m_Gi; } - bool operator>=(const CStrictGi& gi) const { return m_Gi >= gi.m_Gi; } + bool operator==(const CStrictId64& gi) const { return m_Gi == gi.m_Gi; } + bool operator!=(const CStrictId64& gi) const { return m_Gi != gi.m_Gi; } + bool operator<(const CStrictId64& gi) const { return m_Gi < gi.m_Gi; } + bool operator<=(const CStrictId64& gi) const { return m_Gi <= gi.m_Gi; } + bool operator>(const CStrictId64& gi) const { return m_Gi > gi.m_Gi; } + bool operator>=(const CStrictId64& gi) const { return m_Gi >= gi.m_Gi; } - CStrictGi& operator++(void) { m_Gi++; return *this; } - CStrictGi operator++(int) { CStrictGi tmp = *this; m_Gi++; return tmp; } - CStrictGi& operator--(void) { m_Gi--; return *this; } - CStrictGi operator--(int) { CStrictGi tmp = *this; m_Gi--; return tmp; } + CStrictId64& operator++(void) { m_Gi++; return *this; } + CStrictId64 operator++(int) { CStrictId64 tmp = *this; m_Gi++; return tmp; } + CStrictId64& operator--(void) { m_Gi--; return *this; } + CStrictId64 operator--(int) { CStrictId64 tmp = *this; m_Gi--; return tmp; } - TIntId operator+(const CStrictGi& gi) const { return m_Gi + gi.m_Gi; } - TIntId operator-(const CStrictGi& gi) const { return m_Gi - gi.m_Gi; } + TIntId operator+(const CStrictId64& gi) const { return m_Gi + gi.m_Gi; } + TIntId operator-(const CStrictId64& gi) const { return m_Gi - gi.m_Gi; } - CStrictGi operator+(TIntId offset) const { return m_Gi + offset; } - CStrictGi operator-(TIntId offset) const { return m_Gi - offset; } + CStrictId64 operator+(TIntId offset) const { return m_Gi + offset; } + CStrictId64 operator-(TIntId offset) const { return m_Gi - offset; } #if defined(NCBI_INT8_GI) - CStrictGi operator+(Int4 offset) const { return m_Gi + offset; } - CStrictGi operator-(Int4 offset) const { return m_Gi - offset; } + CStrictId64 operator+(Int4 offset) const { return m_Gi + offset; } + CStrictId64 operator-(Int4 offset) const { return m_Gi - offset; } #endif - CStrictGi(TIntId value) : m_Gi(value) {} - CStrictGi& operator=(TIntId value) { m_Gi = value; return *this; } + CStrictId64(TIntId value) : m_Gi(value) {} + CStrictId64& operator=(TIntId value) { m_Gi = value; return *this; } operator TIntId(void) const { return m_Gi; } bool operator==(TIntId value) const { return m_Gi == value; } #if defined(NCBI_INT8_GI) && defined(NCBI_TEST_APPLICATION) - CStrictGi(Int4 value) : m_Gi(value) {} - CStrictGi& operator=(Int4 value) { m_Gi = value; return *this; } + CStrictId64(Int4 value) : m_Gi(value) {} + CStrictId64& operator=(Int4 value) { m_Gi = value; return *this; } bool operator==(Int4 value) const { return m_Gi == value; } #endif @@ -1030,26 +1031,26 @@ public: private: #if defined(NCBI_INT8_GI) && !defined(NCBI_TEST_APPLICATION) - CStrictGi(Int4); - CStrictGi& operator=(Int4); + CStrictId64(Int4); + CStrictId64& operator=(Int4); operator Int4(void) const; #endif - CStrictGi(Int1); - CStrictGi(Uint1); - CStrictGi(Int2); - CStrictGi(Uint2); - CStrictGi(Uint4); - CStrictGi(Uint8); - CStrictGi(float); - CStrictGi(double); - CStrictGi& operator=(Int1); - CStrictGi& operator=(Uint1); - CStrictGi& operator=(Int2); - CStrictGi& operator=(Uint2); - CStrictGi& operator=(Uint4); - CStrictGi& operator=(Uint8); - CStrictGi& operator=(float); - CStrictGi& operator=(double); + CStrictId64(Int1); + CStrictId64(Uint1); + CStrictId64(Int2); + CStrictId64(Uint2); + CStrictId64(Uint4); + CStrictId64(Uint8); + CStrictId64(float); + CStrictId64(double); + CStrictId64& operator=(Int1); + CStrictId64& operator=(Uint1); + CStrictId64& operator=(Int2); + CStrictId64& operator=(Uint2); + CStrictId64& operator=(Uint4); + CStrictId64& operator=(Uint8); + CStrictId64& operator=(float); + CStrictId64& operator=(double); operator Int1(void) const; operator Uint1(void) const; operator Int2(void) const; @@ -1063,14 +1064,26 @@ private: TIntId m_Gi; }; +/// @deprecated: Use CStrictId64 instead of CStrictGi, or TGi/TEntrezId typedefs. +NCBI_DEPRECATED typedef CStrictId64 CStrictGi; + inline -CNcbiOstream& operator<<(CNcbiOstream& out, const CStrictGi& gi) +CNcbiOstream& operator<<(CNcbiOstream& out, const CStrictId64& gi) { return out << TIntId(gi); } -typedef CStrictGi TGi; +inline +CNcbiIstream& operator>>(CNcbiIstream& in, CStrictId64& gi) +{ + TIntId id; + in >> id; + gi = id; + return in; +} + +typedef CStrictId64 TGi; #else // NCBI_STRICT_GI @@ -1086,6 +1099,16 @@ typedef Uint4 TUintId; #endif +/// TEntrezId type for entrez ids which require the same strictness as TGi. +#ifdef NCBI_STRICT_ENTREZ_ID +# ifndef NCBI_STRICT_GI +# undef NCBI_STRICT_ENTREZ_ID +# endif +typedef TGi TEntrezId; +#else +typedef TIntId TEntrezId; +#endif + /// a helper template to enforce constness of argument to GI_CONST macro template class CConstGIChecker { @@ -1149,9 +1172,9 @@ template class CFastBuffer { public: - CFastBuffer(size_t size) - : m_Size(size), - m_Buffer(size <= KEmbeddedSize ? m_EmbeddedBuffer : new TType[size]) + CFastBuffer(size_t buf_size) + : m_Size(buf_size), + m_Buffer(buf_size <= KEmbeddedSize ? m_EmbeddedBuffer : new TType[buf_size]) {} ~CFastBuffer() { if (m_Buffer != m_EmbeddedBuffer) delete[] m_Buffer; } @@ -1234,9 +1257,9 @@ size_t ArraySize(const Element (&)[Size]) } #ifdef NCBI_STRICT_GI -template <> struct hash +template <> struct hash { - size_t operator()(const ncbi::CStrictGi & x) const + size_t operator()(const ncbi::CStrictId64 & x) const { return hash()((ncbi::TIntId)x); } diff --git a/c++/include/corelib/ncbiobj.hpp b/c++/include/corelib/ncbiobj.hpp index d4e6feab..480f8211 100644 --- a/c++/include/corelib/ncbiobj.hpp +++ b/c++/include/corelib/ncbiobj.hpp @@ -1,7 +1,7 @@ #ifndef CORELIB___NCBIOBJ__HPP #define CORELIB___NCBIOBJ__HPP -/* $Id: ncbiobj.hpp 463582 2015-03-30 18:03:40Z vasilche $ +/* $Id: ncbiobj.hpp 502479 2016-05-24 22:41:09Z vasilche $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -662,6 +662,16 @@ public: } } + /// Copy constructor from an existing CRef object, + CRef(TThisType&& ref) + : m_Data(ref.m_Data) + { + if ( TObjectType* ptr = ref.m_Data.second() ) { + m_Data.first().TransferLock(ptr, ref.m_Data.first()); + ref.m_Data.second() = 0; + } + } + /// Destructor. ~CRef(void) { @@ -879,6 +889,29 @@ public: return *this; } + /// Assignment operator for references. + TThisType& operator=(TThisType&& ref) + { +#ifdef NCBI_COMPILER_MSVC + // extra check on MSVC + if (this == &ref) { + // no-op + return *this; + } +#endif + TObjectType* oldPtr = m_Data.second(); + TObjectType* newPtr = ref.m_Data.second(); + if ( newPtr ) { + m_Data.first().TransferLock(newPtr, ref.m_Data.first()); + ref.m_Data.second() = 0; + } + m_Data.second() = newPtr; + if ( oldPtr ) { + m_Data.first().Unlock(oldPtr); + } + return *this; + } + /// Assignment operator for references with right hand side set to /// a pointer. TThisType& operator=(TObjectType* ptr) @@ -1205,6 +1238,16 @@ public: } } + /// Constructor from an existing CConstRef object, + CConstRef(TThisType&& ref) + : m_Data(ref.m_Data) + { + if ( TObjectType* ptr = ref.m_Data.second() ) { + m_Data.first().TransferLock(ptr, ref.m_Data.first()); + ref.m_Data.second() = 0; + } + } + /// Constructor from an existing CRef object, CConstRef(const CRef& ref) : m_Data(ref.GetLocker(), 0) @@ -1433,6 +1476,29 @@ public: return *this; } + /// Assignment operator for const references. + TThisType& operator=(TThisType&& ref) + { +#ifdef NCBI_COMPILER_MSVC + // extra check on MSVC + if (this == &ref) { + // no-op + return *this; + } +#endif + TObjectType* oldPtr = m_Data.second(); + TObjectType* newPtr = ref.m_Data.second(); + if ( newPtr ) { + m_Data.first().TransferLock(newPtr, ref.m_Data.first()); + ref.m_Data.second() = 0; + } + m_Data.second() = newPtr; + if ( oldPtr ) { + m_Data.first().Unlock(oldPtr); + } + return *this; + } + /// Assignment operator for assigning a reference to a const reference. TThisType& operator=(const CRef& ref) { diff --git a/c++/include/corelib/ncbireg.hpp b/c++/include/corelib/ncbireg.hpp index 88786fdd..dae0a6d7 100644 --- a/c++/include/corelib/ncbireg.hpp +++ b/c++/include/corelib/ncbireg.hpp @@ -1,7 +1,7 @@ #ifndef CORELIB___NCBIREG__HPP #define CORELIB___NCBIREG__HPP -/* $Id: ncbireg.hpp 495404 2016-03-17 13:28:04Z ivanov $ +/* $Id: ncbireg.hpp 506965 2016-07-13 16:55:04Z elisovdn $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -297,6 +297,14 @@ public: void WriteLock(void); void Unlock (void); + /// Check if "str" consists of alphanumeric and '_' only + /// Treat the case of set fSectionlessEntries separately + static bool IsNameSection(const string& str, TFlags flags); + + // Check if "str" consists of alphanumeric and '_' only + static bool IsNameEntry(const string& str, TFlags flags); + + /// Entry name for an in-section comment static const char* sm_InSectionCommentName; diff --git a/c++/include/corelib/ncbistl.hpp b/c++/include/corelib/ncbistl.hpp index c3916ed5..b1d6b222 100644 --- a/c++/include/corelib/ncbistl.hpp +++ b/c++/include/corelib/ncbistl.hpp @@ -1,7 +1,7 @@ #ifndef CORELIB___NCBISTL__HPP #define CORELIB___NCBISTL__HPP -/* $Id: ncbistl.hpp 442488 2014-08-04 17:50:17Z vasilche $ +/* $Id: ncbistl.hpp 504449 2016-06-15 15:52:43Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -217,6 +217,7 @@ END_NCBI_SCOPE # include # ifdef _GLIBCXX_THROW_OR_ABORT /* using libstdc++ from GCC 4.8 or later */ # include +# include # include # include # endif diff --git a/c++/include/corelib/ncbistr.hpp b/c++/include/corelib/ncbistr.hpp index 5cc1cc52..5cc04312 100644 --- a/c++/include/corelib/ncbistr.hpp +++ b/c++/include/corelib/ncbistr.hpp @@ -1,7 +1,7 @@ #ifndef CORELIB___NCBISTR__HPP #define CORELIB___NCBISTR__HPP -/* $Id: ncbistr.hpp 497430 2016-04-06 17:39:32Z ivanov $ +/* $Id: ncbistr.hpp 511434 2016-08-22 15:26:41Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -232,23 +232,32 @@ enum class EEncoding { class NCBI_XNCBI_EXPORT NStr { public: - /// Convert string to non-negative integer value. - /// - /// @param str - /// String containing only digits, representing non-negative - /// decimal value in the int range: [0..kMax_Int]. - /// @return - /// - If conversion succeeds, set errno to zero and return the - /// converted value. - /// - Otherwise, set errno to non-zero and return -1. - static int StringToNonNegativeInt(const string& str); - - /// @deprecated - /// Use template-based StringToNumeric<> or StringToNonNegativeInt() instead. - NCBI_DEPRECATED - static int StringToNumeric(const string& str) { - return StringToNonNegativeInt(str); - } + /// Common conversion flags. + enum EConvErrFlags { + /// Do not throw an exception on error. + /// Could be used with methods throwing an exception by default, ignored otherwise. + /// Just return zero and set errno to non-zero instead of throwing an exception. + /// We recommend the following technique to check against errors + /// with minimum overhead when this flag is used: + /// @code + /// if (!retval && errno != 0) + /// ERROR; + /// @endcode + /// And for StringToDouble*() variants: + /// @code + /// if (retval == HUGE_VAL || retval == -HUGE_VAL || + /// !retval && errno != 0) + /// ERROR; + /// @endcode + fConvErr_NoThrow = (1 << 0), + /* + fConvErr_NoErrno = (1 << 1), ///< Do not set errno at all. + ///< If used together with fConvErr_NoThrow flag + ///< returns 0 on error (-1 for StringToNonNegativeInt). + */ + fConvErr_NoErrMessage = (1 << 2) ///< Set errno, but do not set CNcbiError message on error + }; + typedef int TConvErrFlags; ///< Bitwise OR of "EConvErrFlags" /// Number to string conversion flags. /// @@ -256,12 +265,13 @@ public: /// If specified base in the *ToString() methods is not default 10, /// that some flags like fWithSign and fWithCommas will be ignored. enum ENumToStringFlags { - fWithSign = (1 << 6), ///< Prefix the output value with a sign - fWithCommas = (1 << 7), ///< Use commas as thousands separator - fDoubleFixed = (1 << 8), ///< Use n.nnnn format for double - fDoubleScientific= (1 << 9), ///< Use scientific format for double - fDoublePosix = (1 << 10), ///< Use C locale - fDoubleGeneral = fDoubleFixed | fDoubleScientific, + fWithSign = (1 << 6), ///< Prefix the output value with a sign + fWithCommas = (1 << 7), ///< Use commas as thousands separator + fDoubleFixed = (1 << 8), ///< Use n.nnnn format for double + fDoubleScientific = (1 << 9), ///< Use scientific format for double + fDoublePosix = (1 << 10), ///< Use C locale + fDoubleGeneral = fDoubleFixed | fDoubleScientific, + // Additional flags to convert "software" qualifiers (see UInt8ToString_DataSize) fDS_Binary = (1 << 11), fDS_NoDecimalPoint = (1 << 12), fDS_PutSpaceBeforeSuffix = (1 << 13), @@ -272,39 +282,26 @@ public: /// String to number conversion flags. enum EStringToNumFlags { - fConvErr_NoThrow = (1 << 16), ///< On error, return zero and set - /// errno to non-zero instead of throwing an exception (the default). - /// We recommend the following technique to check against errors - /// with minimum overhead when this flag is used: - /// if (!retval && errno != 0) - /// ERROR; - /// And for StringToDouble*() variants: - /// if (retval == HUGE_VAL || retval == -HUGE_VAL || - /// !retval && errno != 0) - /// ERROR; - - fMandatorySign = (1 << 17), ///< See 'fWithSign' - fAllowCommas = (1 << 18), ///< See 'fWithCommas' - fAllowLeadingSpaces = (1 << 19), ///< Can have leading spaces - fAllowLeadingSymbols = (1 << 20) | fAllowLeadingSpaces, - ///< Can have leading non-nums - fAllowTrailingSpaces = (1 << 21), ///< Can have trailing spaces - fAllowTrailingSymbols = (1 << 22) | fAllowTrailingSpaces, - ///< Can have trailing non-nums - fDecimalPosix = (1 << 23), ///< For decimal point, use C locale - fDecimalPosixOrLocal = (1 << 24), ///< For decimal point, try both C and current locale - fDecimalPosixFinite = (1 << 25), ///< keep result finite and normalized - /// if DBL_MAX < result < INF, result becomes DBL_MAX - /// if 0 < result < DBL_MIN, result becomes DBL_MIN - - fDS_ForceBinary = (1 << 26), - fDS_ProhibitFractions = (1 << 27), + fMandatorySign = (1 << 17), ///< See 'ENumToStringFlags::fWithSign' + fAllowCommas = (1 << 18), ///< See 'ENumToStringFlags::fWithCommas' + fAllowLeadingSpaces = (1 << 19), ///< Can have leading spaces + fAllowLeadingSymbols = (1 << 20) | fAllowLeadingSpaces, + ///< Can have leading non-nums + fAllowTrailingSpaces = (1 << 21), ///< Can have trailing spaces + fAllowTrailingSymbols = (1 << 22) | fAllowTrailingSpaces, + ///< Can have trailing non-nums + fDecimalPosix = (1 << 23), ///< For decimal point, use C locale + fDecimalPosixOrLocal = (1 << 24), ///< For decimal point, try both C and current locale + fDecimalPosixFinite = (1 << 25), ///< Keep result finite and normalized: + ///< if DBL_MAX < result < INF, result becomes DBL_MAX + ///< if 0 < result < DBL_MIN, result becomes DBL_MIN + // Additional flags to convert "software" qualifiers (see StringToUInt8_DataSize) + fDS_ForceBinary = (1 << 26), + fDS_ProhibitFractions = (1 << 27), fDS_ProhibitSpaceBeforeSuffix = (1 << 28) - }; typedef int TStringToNumFlags; ///< Bitwise OR of "EStringToNumFlags" - /// Convert string to a numeric value. /// /// @param str @@ -349,6 +346,27 @@ public: TStringToNumFlags flags = 0, int base = 10); + /// Convert string to non-negative integer value. + /// + /// @param str + /// String containing only digits, representing non-negative + /// decimal value in the int range: [0..kMax_Int]. + /// @param flags + /// How to convert string to value. + /// Only fConvErr_NoErrMessage flag is supported here. + /// @return + /// - If conversion succeeds, set errno to zero and return the converted value. + /// - Otherwise, set errno to non-zero and return -1. + static int StringToNonNegativeInt(const CTempString str, TConvErrFlags flags = 0); + + /// @deprecated + /// Use template-based StringToNumeric<> or StringToNonNegativeInt() instead. + NCBI_DEPRECATED + static int StringToNumeric(const string& str) + { + return StringToNonNegativeInt(str); + } + /// Convert string to int. /// /// @param str @@ -572,7 +590,7 @@ public: /// converted value. /// - Otherwise, if fConvErr_NoThrow is not set, throw an exception. /// - Otherwise, set errno to non-zero and return zero. - /// @deprecated Use StringToUInt8_DataSize(str,flags) instead. + /// @deprecated Use StringToUInt8_DataSize(str, flags) instead. NCBI_DEPRECATED static Uint8 StringToUInt8_DataSize(const CTempString str, TStringToNumFlags flags, @@ -601,12 +619,15 @@ public: /// /// @param str /// String to be converted. + /// @param flags + /// How to convert string to value. + /// Only fConvErr_NoErrMessage flag is supported here. /// @return /// Pointer value corresponding to its string representation. /// - If conversion succeeds, set errno to zero and return the /// converted value. /// - Otherwise, set errno to non-zero and return NULL. - static const void* StringToPtr(const CTempStringEx str); + static const void* StringToPtr(const CTempStringEx str, TConvErrFlags flags = 0); /// Convert character to integer. /// @@ -677,29 +698,6 @@ public: static string IntToString(unsigned int value, TNumToStringFlags flags = 0, int base = 10); -// +++ will be deleted soon -//private: - /// @deprecated Use NumericToString instead - NCBI_DEPRECATED - static string IntToString(long value, TNumToStringFlags flags = 0, - int base = 10); - /// @deprecated Use NumericToString instead - NCBI_DEPRECATED - static string IntToString(unsigned long value, TNumToStringFlags flags = 0, - int base = 10); -#if !NCBI_INT8_IS_LONG - /// @deprecated Use NumericToString instead - NCBI_DEPRECATED - static string IntToString(Int8 value, TNumToStringFlags flags = 0, - int base = 10); - /// @deprecated Use NumericToString instead - NCBI_DEPRECATED - static string IntToString(Uint8 value, TNumToStringFlags flags = 0, - int base = 10); -#endif -// --- will be deleted soon -public: - /// Convert int to string. /// /// @param out_str @@ -724,33 +722,6 @@ public: TNumToStringFlags flags = 0, int base = 10); -// +++ will be deleted soon -//private: - /// @deprecated Use NumericToString instead - NCBI_DEPRECATED - static void IntToString(string& out_str, long value, - TNumToStringFlags flags = 0, - int base = 10); - /// @deprecated Use NumericToString instead - NCBI_DEPRECATED - static void IntToString(string& out_str, unsigned long value, - TNumToStringFlags flags = 0, - int base = 10); -#if !NCBI_INT8_IS_LONG - /// @deprecated Use NumericToString instead - NCBI_DEPRECATED - static void IntToString(string& out_str, Int8 value, - TNumToStringFlags flags = 0, - int base = 10); - /// @deprecated Use NumericToString instead - NCBI_DEPRECATED - static void IntToString(string& out_str, Uint8 value, - TNumToStringFlags flags = 0, - int base = 10); -#endif -// --- will be deleted soon -public: - /// Convert UInt to string. /// /// @param value @@ -773,33 +744,6 @@ public: TNumToStringFlags flags = 0, int base = 10); -// +++ will be deleted soon -//private: - /// @deprecated Use NumericToString instead - NCBI_DEPRECATED - static string UIntToString(unsigned long value, - TNumToStringFlags flags = 0, - int base = 10); - /// @deprecated Use NumericToString instead - NCBI_DEPRECATED - static string UIntToString(long value, - TNumToStringFlags flags = 0, - int base = 10); -#if !NCBI_INT8_IS_LONG - /// @deprecated Use NumericToString instead - NCBI_DEPRECATED - static string UIntToString(Int8 value, - TNumToStringFlags flags = 0, - int base = 10); - /// @deprecated Use NumericToString instead - NCBI_DEPRECATED - static string UIntToString(Uint8 value, - TNumToStringFlags flags = 0, - int base = 10); -#endif -// --- will be deleted soon -public: - /// Convert UInt to string. /// /// @param out_str @@ -824,33 +768,6 @@ public: TNumToStringFlags flags = 0, int base = 10); -// +++ will be deleted soon -//private: - /// @deprecated Use NumericToString instead - NCBI_DEPRECATED - static void UIntToString(string& out_str, unsigned long value, - TNumToStringFlags flags = 0, - int base = 10); - /// @deprecated Use NumericToString instead - NCBI_DEPRECATED - static void UIntToString(string& out_str, long value, - TNumToStringFlags flags = 0, - int base = 10); -#if !NCBI_INT8_IS_LONG - /// @deprecated Use NumericToString instead - NCBI_DEPRECATED - static void UIntToString(string& out_str, Int8 value, - TNumToStringFlags flags = 0, - int base = 10); - /// @deprecated Use NumericToString instead - NCBI_DEPRECATED - static void UIntToString(string& out_str, Uint8 value, - TNumToStringFlags flags = 0, - int base = 10); -#endif -// --- will be deleted soon -public: - /// Convert Int to string. /// /// @param value @@ -1983,8 +1900,8 @@ public: /// NOTE: When an occurrence is found the next occurrence will be /// searched for starting right *after* the found pattern. /// @return - /// - Start of the found pattern in the string. - /// - NPOS if there is no occurrence of the pattern in the string. + /// Start of the found pattern in the string. + /// Or NPOS if there is no occurrence of the pattern in the string. static SIZE_TYPE Find(const CTempString str, const CTempString pattern, ECase use_case = eCase, @@ -1998,11 +1915,11 @@ public: /// @param pattern /// Pattern to search for in "str". /// @param start - /// Position in "str" to start search from -- default of 0 means start - /// the search from the beginning of the string. + /// Position in "str" to start search from. + /// 0 means start the search from the beginning of the string. /// @param end - /// Position in "str" to perform search up to -- default of NPOS means - /// to search to the end of the string. + /// Position in "str" to perform search up to. + /// NPOS means to search to the end of the string. /// @param which /// When set to eFirst, this means to find the first occurrence of /// "pattern" in "str". When set to eLast, this means to find the last @@ -2012,12 +1929,32 @@ public: /// case-insensitive compare (eNocase) while searching for the pattern. /// @return /// - The start of the first or last (depending on "which" parameter) - /// occurrence of "pattern" in "str", within the string interval - /// ["start", "end"], or + /// occurrence of "pattern" in "str", within the string interval + /// ["start", "end"], or /// - NPOS if there is no occurrence of the pattern. /// @sa FindCase, FindNoCase, FindWord + /// /// @deprecated - /// Use Find() method without [start:end] range. + /// Use + /// @code + /// Find(str, pattern, [use_case], [direction], [occurrence]) + /// @endcode + /// method instead. + /// For example: + /// @code + /// Find(str, pattern, 0, NPOS, eLast, eCase) + /// @endcode + /// can be replaced by + /// @code + /// Find(str, pattern, eCase, eReverseSearch, /* 0 */) + /// @endcode + /// If you doing a search on a substring of the 'str' and ["start", "end"] search + /// interval is not a default [0, NPOS], that mean a whole 'str' string, you may + /// need to pass a substring instead of 'str', like + /// @code + /// Find(CTempString(str, start, len), pattern, ....) + /// @endcode + /// and after checking search result on NPOS, adjust it by 'start' yourself. NCBI_DEPRECATED static SIZE_TYPE Find(const CTempString str, const CTempString pattern, @@ -2027,8 +1964,7 @@ public: /// Wrapper for backward-compatibility inline - static SIZE_TYPE Find(const CTempString str, const CTempString pattern, - SIZE_TYPE start) + static SIZE_TYPE Find(const CTempString str, const CTempString pattern, SIZE_TYPE start) { return FindCase(str, pattern, start); } @@ -2051,12 +1987,38 @@ public: /// occurrence of "pattern" in "str". /// @return /// - The start of the first or last (depending on "which" parameter) - /// occurrence of "pattern" in "str", within the string interval - /// ["start", "end"], or + /// occurrence of "pattern" in "str", within the string interval + /// ["start", "end"], or /// - NPOS if there is no occurrence of the pattern. /// @sa Find + /// /// @deprecated /// Use Find() method without [start:end] range. + /// @deprecated + /// Use one of the next methods instead: + /// @code + /// Find(str, pattern, [use_case], [direction], [occurrence]) + /// FindCase(str, pattern, [start]) + /// @endcode + /// For example: + /// @code + /// FindCase(str, pattern, 0, NPOS, eLast) + /// @endcode + /// can be replaced by + /// @code + /// Find(str, pattern, eCase, eReverseSearch, /* 0 */) + /// @endcode + /// For simpler cases without range, or with default [0, NPOS] please use + /// @code + /// FindCase(str, pattern, [start]) + /// @endcode + /// But if you doing a search on a substring of the 'str' and ["start", "end"] search + /// interval is not a default [0, NPOS], that mean a whole 'str' string, you may + /// need to pass a substring instead of 'str', like + /// @code + /// FindCase(CTempString(str, start, len), pattern, ....) + /// @endcode + /// and after checking search result on NPOS, adjust it by 'start' yourself. NCBI_DEPRECATED static SIZE_TYPE FindCase(const CTempString str, const CTempString pattern, @@ -2086,12 +2048,36 @@ public: /// occurrence of "pattern" in "str". /// @return /// - The start of the first or last (depending on "which" parameter) - /// occurrence of "pattern" in "str", within the string interval - /// ["start", "end"], or + /// occurrence of "pattern" in "str", within the string interval + /// ["start", "end"], or /// - NPOS if there is no occurrence of the pattern. /// @sa Find + /// /// @deprecated - /// Use Find() method without [start:end] range. + /// Use one of the next methods instead: + /// @code + /// Find(str, pattern, [use_case], [direction], [occurrence]) + /// FindNoCase(str, pattern, [start]) + /// @endcode + /// For example: + /// @code + /// FindNoCase(str, pattern, 0, NPOS, eLast) + /// @endcode + /// can be replaced by + /// @code + /// Find(str, pattern, eNocase, eReverseSearch, /* 0 */) + /// @endcode + /// For simpler cases without range, or with default [0, NPOS] please use + /// @code + /// FindNoCase(str, pattern, [start]) + /// @endcode + /// But if you doing a search on a substring of the 'str' and ["start", "end"] search + /// interval is not a default [0, NPOS], that mean a whole 'str' string, you may + /// need to pass a substring instead of 'str', like + /// @code + /// FindNoCase(CTempString(str, start, len), pattern, ....) + /// @endcode + /// and after checking search result on NPOS, adjust it by 'start' yourself. NCBI_DEPRECATED static SIZE_TYPE FindNoCase(const CTempString str, const CTempString pattern, @@ -2170,7 +2156,10 @@ public: /// - NPOS if there is no occurrence of the word. /// @sa Find /// @deprecated - /// Use FindWord() variant with EDirection parameter. + /// Use FindWord() variant with EDirection parameter: + /// @code + /// FindWord(str, word, [use_case], [direction]) + /// @endcode inline NCBI_DEPRECATED static SIZE_TYPE FindWord(const CTempString str, @@ -2390,7 +2379,7 @@ public: fSplit_Truncate_End = 1 << 2, ///< Truncate trailing delimiters fSplit_Truncate = fSplit_Truncate_Begin | fSplit_Truncate_End, fSplit_ByPattern = 1 << 3, ///< Require full delimiter strings - fSplit_CanEscape = 1 << 4, ///< Allow \... escaping + fSplit_CanEscape = 1 << 4, ///< Allow \\... escaping fSplit_CanSingleQuote = 1 << 5, ///< Allow '...' quoting fSplit_CanDoubleQuote = 1 << 6, ///< Allow "..." quoting fSplit_CanQuote = fSplit_CanSingleQuote | fSplit_CanDoubleQuote, @@ -2404,7 +2393,7 @@ public: /// Note that it truncates leading and trailing delimiters as well. /// Please use ESplitFlags instead. fSplit_MergeDelims = fSplit_MergeDelimiters | fSplit_Truncate, - /// Mo merge the delimiters. + /// Do not merge the delimiters. /// fSplit_NoMergeDelims can be temporary used for semantics /// purposes only, because we still have legacy Split() version /// without flags, that use fSplit_MergeDelims by default. @@ -2488,19 +2477,19 @@ public: /// Variation of Split() wihout flags -- for backward compatibility only. /// @attention - /// Automatically use flags: fSplit_MergeDelimiters | fSplit_Truncate + /// Automatically use flags: fSplit_Tokenize /// @deprecated Use Split() with TSplitFlags instead inline NCBI_DEPRECATED static list& Split(const CTempString str, const CTempString delim, list& arr) { - return Split(str, delim, arr, fSplit_MergeDelimiters | fSplit_Truncate); + return Split(str, delim, arr, fSplit_Tokenize); } /// Variation of Split() wihout flags -- for backward compatibility only. /// @attention - /// Automatically use flags: fSplit_MergeDelimiters | fSplit_Truncate + /// Automatically use flags: fSplit_Tokenize /// @deprecated Use Split() with TSplitFlags instead inline NCBI_DEPRECATED @@ -2508,7 +2497,7 @@ public: const CTempString str, const CTempString delim, list& arr) { - return Split(str, delim, arr, fSplit_MergeDelimiters | fSplit_Truncate); + return Split(str, delim, arr, fSplit_Tokenize); } /// @deprecated Use Split() with TSplitFlags instead @@ -2754,7 +2743,7 @@ public: /// Get a printable version of the specified string. /// /// All non-printable characters will be represented as "\r", "\n", "\v", - /// "\t", "\"", "\\", etc, or "\ooo" where 'ooo' is an octal code of the + /// "\t", "\"", "\\\\", etc, or "\\ooo" where 'ooo' is an octal code of the /// character. The resultant string is a well-formed C string literal, /// which, without alterations, can be compiled by a C/C++ compiler. /// In many instances, octal representations of non-printable characters @@ -3078,42 +3067,43 @@ public: /// first line. /// @return /// Return "arr", the list of wrapped lines. - template - static void WrapIt(const string& str, SIZE_TYPE width, - _D& dest, TWrapFlags flags = 0, - const string* prefix = 0, - const string* prefix1 = 0); - - class IWrapDest - { - public: - virtual void Append(const string& s) = 0; - virtual void Append(const CTempString& s) = 0; - }; - - class CWrapDestStringList : public IWrapDest - { - protected: - list& m_list; - public: - CWrapDestStringList(list& l) : m_list(l) {}; - virtual void Append(const string& s) - { - m_list.push_back(s); - } - virtual void Append(const CTempString& s) - { + template + static void WrapIt(const string& str, SIZE_TYPE width, + _D& dest, TWrapFlags flags = 0, + const string* prefix = 0, + const string* prefix1 = 0); + + class IWrapDest + { + public: + virtual ~IWrapDest() {} + virtual void Append(const string& s) = 0; + virtual void Append(const CTempString& s) = 0; + }; + + class CWrapDestStringList : public IWrapDest + { + protected: + list& m_list; + public: + CWrapDestStringList(list& l) : m_list(l) {}; + virtual void Append(const string& s) + { + m_list.push_back(s); + } + virtual void Append(const CTempString& s) + { m_list.push_back(NcbiEmptyString); m_list.back().assign(s.data(), s.length()); - } - }; + } + }; - static void Wrap(const string& str, SIZE_TYPE width, - IWrapDest& dest, TWrapFlags flags, - const string* prefix, - const string* prefix1); + static void Wrap(const string& str, SIZE_TYPE width, + IWrapDest& dest, TWrapFlags flags, + const string* prefix, + const string* prefix1); - static list& Wrap(const string& str, SIZE_TYPE width, + static list& Wrap(const string& str, SIZE_TYPE width, list& arr, TWrapFlags flags = 0, const string* prefix = 0, const string* prefix1 = 0); @@ -4441,7 +4431,13 @@ char NStr::StringToNumeric(const CTempString str, int n = StringToInt(str, flags, base); if (n < numeric_limits::min() || n > numeric_limits::max()) { if (flags & NStr::fConvErr_NoThrow) { - CNcbiError::SetErrno(errno = ERANGE, str); +// if ((flags & fConvErr_NoErrno) == 0) { + if (flags & fConvErr_NoErrMessage) { + CNcbiError::SetErrno(errno = ERANGE); + } else { + CNcbiError::SetErrno(errno = ERANGE, str); + } +// } return 0; } else { NCBI_THROW2(CStringException, eConvert, @@ -4458,7 +4454,13 @@ unsigned char NStr::StringToNumeric(const CTempString str, unsigned int n = StringToUInt(str, flags, base); if (n > numeric_limits::max()) { if (flags & NStr::fConvErr_NoThrow) { - CNcbiError::SetErrno(errno = ERANGE,str); +// if ((flags & fConvErr_NoErrno) == 0) { + if (flags & fConvErr_NoErrMessage) { + CNcbiError::SetErrno(errno = ERANGE); + } else { + CNcbiError::SetErrno(errno = ERANGE, str); + } +// } return 0; } else { NCBI_THROW2(CStringException, eConvert, @@ -4479,7 +4481,13 @@ bool NStr::StringToNumeric(const CTempString str, } if (n < numeric_limits::min() || n > numeric_limits::max()) { if (flags & NStr::fConvErr_NoThrow) { - CNcbiError::SetErrno(errno = ERANGE, str); +// if ((flags & fConvErr_NoErrno) == 0) { + if (flags & fConvErr_NoErrMessage) { + CNcbiError::SetErrno(errno = ERANGE); + } else { + CNcbiError::SetErrno(errno = ERANGE, str); + } +// } return false; } else { NCBI_THROW2(CStringException, eConvert, @@ -4501,7 +4509,13 @@ bool NStr::StringToNumeric(const CTempString str, } if (n > numeric_limits::max()) { if (flags & NStr::fConvErr_NoThrow) { - CNcbiError::SetErrno(errno = ERANGE,str); +// if ((flags & fConvErr_NoErrno) == 0) { + if (flags & fConvErr_NoErrMessage) { + CNcbiError::SetErrno(errno = ERANGE); + } else { + CNcbiError::SetErrno(errno = ERANGE, str); + } +// } return false; } else { NCBI_THROW2(CStringException, eConvert, @@ -4535,7 +4549,13 @@ wchar_t NStr::StringToNumeric(const CTempString str, int n = StringToInt(str, flags, base); if (n < numeric_limits::min() || n > numeric_limits::max()) { if (flags & NStr::fConvErr_NoThrow) { - CNcbiError::SetErrno(errno = ERANGE, str);; +// if ((flags & fConvErr_NoErrno) == 0) { + if (flags & fConvErr_NoErrMessage) { + CNcbiError::SetErrno(errno = ERANGE); + } else { + CNcbiError::SetErrno(errno = ERANGE, str); + } +// } return 0; } else { NCBI_THROW2(CStringException, eConvert, @@ -4556,7 +4576,13 @@ bool NStr::StringToNumeric(const CTempString str, } if (n < numeric_limits::min() || n > numeric_limits::max()) { if (flags & NStr::fConvErr_NoThrow) { - CNcbiError::SetErrno(errno = ERANGE, str); +// if ((flags & fConvErr_NoErrno) == 0) { + if (flags & fConvErr_NoErrMessage) { + CNcbiError::SetErrno(errno = ERANGE); + } else { + CNcbiError::SetErrno(errno = ERANGE, str); + } +// } return false; } else { NCBI_THROW2(CStringException, eConvert, @@ -4604,7 +4630,13 @@ short NStr::StringToNumeric(const CTempString str, int n = StringToInt(str, flags, base); if (n < numeric_limits::min() || n > numeric_limits::max()) { if (flags & NStr::fConvErr_NoThrow) { - CNcbiError::SetErrno(errno = ERANGE, str); +// if ((flags & fConvErr_NoErrno) == 0) { + if (flags & fConvErr_NoErrMessage) { + CNcbiError::SetErrno(errno = ERANGE); + } else { + CNcbiError::SetErrno(errno = ERANGE, str); + } +// } return 0; } else { NCBI_THROW2(CStringException, eConvert, @@ -4621,7 +4653,13 @@ unsigned short NStr::StringToNumeric(const CTempString str, unsigned int n = StringToUInt(str, flags, base); if (n > numeric_limits::max()) { if (flags & NStr::fConvErr_NoThrow) { - CNcbiError::SetErrno(errno = ERANGE, str); +// if ((flags & fConvErr_NoErrno) == 0) { + if (flags & fConvErr_NoErrMessage) { + CNcbiError::SetErrno(errno = ERANGE); + } else { + CNcbiError::SetErrno(errno = ERANGE, str); + } +// } return 0; } else { NCBI_THROW2(CStringException, eConvert, @@ -4642,7 +4680,13 @@ bool NStr::StringToNumeric(const CTempString str, } if (n < numeric_limits::min() || n > numeric_limits::max()) { if (flags & NStr::fConvErr_NoThrow) { - CNcbiError::SetErrno(errno = ERANGE, str); +// if ((flags & fConvErr_NoErrno) == 0) { + if (flags & fConvErr_NoErrMessage) { + CNcbiError::SetErrno(errno = ERANGE); + } else { + CNcbiError::SetErrno(errno = ERANGE, str); + } +// } return false; } else { NCBI_THROW2(CStringException, eConvert, @@ -4664,7 +4708,13 @@ bool NStr::StringToNumeric(const CTempString str, } if (n > numeric_limits::max()) { if (flags & NStr::fConvErr_NoThrow) { - CNcbiError::SetErrno(errno = ERANGE, str); +// if ((flags & fConvErr_NoErrno) == 0) { + if (flags & fConvErr_NoErrMessage) { + CNcbiError::SetErrno(errno = ERANGE); + } else { + CNcbiError::SetErrno(errno = ERANGE, str); + } +// } return false; } else { NCBI_THROW2(CStringException, eConvert, @@ -4941,7 +4991,13 @@ float NStr::StringToNumeric(const CTempString str, // dont use ::min() for float types, it returns positive value if (n < -numeric_limits::max() || n > numeric_limits::max()) { if (flags & NStr::fConvErr_NoThrow) { - CNcbiError::SetErrno(errno = ERANGE, str); +// if ((flags & fConvErr_NoErrno) == 0) { + if (flags & fConvErr_NoErrMessage) { + CNcbiError::SetErrno(errno = ERANGE); + } else { + CNcbiError::SetErrno(errno = ERANGE, str); + } +// } return 0; } else { NCBI_THROW2(CStringException, eConvert, @@ -4963,7 +5019,13 @@ bool NStr::StringToNumeric(const CTempString str, // dont use ::min() for float types, it returns positive value if (n < -numeric_limits::max() || n > numeric_limits::max()) { if (flags & NStr::fConvErr_NoThrow) { - CNcbiError::SetErrno(errno = ERANGE, str); +// if ((flags & fConvErr_NoErrno) == 0) { + if (flags & fConvErr_NoErrMessage) { + CNcbiError::SetErrno(errno = ERANGE); + } else { + CNcbiError::SetErrno(errno = ERANGE, str); + } +// } return false; } else { NCBI_THROW2(CStringException, eConvert, @@ -5059,44 +5121,6 @@ string NStr::IntToString(unsigned int value, return ret; } -inline -string NStr::IntToString(long value, - TNumToStringFlags flags, int base) -{ - string ret; - LongToString(ret, value, flags, base); - return ret; -} - -inline -string NStr::IntToString(unsigned long value, - TNumToStringFlags flags, int base) -{ - string ret; - LongToString(ret, value, flags, base); - return ret; -} - -#if !NCBI_INT8_IS_LONG -inline -string NStr::IntToString(Int8 value, - TNumToStringFlags flags, int base) -{ - string ret; - Int8ToString(ret, value, flags, base); - return ret; -} - -inline -string NStr::IntToString(Uint8 value, - TNumToStringFlags flags, int base) -{ - string ret; - Int8ToString(ret, (Int8)value, flags, base); - return ret; -} -#endif - inline void NStr::IntToString(string& out_str, unsigned int value, TNumToStringFlags flags, int base) @@ -5104,36 +5128,6 @@ void NStr::IntToString(string& out_str, unsigned int value, IntToString(out_str, (int)value, flags, base); } -inline -void NStr::IntToString(string& out_str, long value, - TNumToStringFlags flags, int base) -{ - LongToString(out_str, value, flags, base); -} - -inline -void NStr::IntToString(string& out_str, unsigned long value, - TNumToStringFlags flags, int base) -{ - LongToString(out_str, value, flags, base); -} - -#if !NCBI_INT8_IS_LONG -inline -void NStr::IntToString(string& out_str, Int8 value, - TNumToStringFlags flags, int base) -{ - Int8ToString(out_str, value, flags, base); -} - -inline -void NStr::IntToString(string& out_str, Uint8 value, - TNumToStringFlags flags, int base) -{ - Int8ToString(out_str, (Int8)value, flags, base); -} -#endif - inline string NStr::UIntToString(unsigned int value, TNumToStringFlags flags, int base) @@ -5152,44 +5146,6 @@ string NStr::UIntToString(int value, return ret; } -inline -string NStr::UIntToString(unsigned long value, - TNumToStringFlags flags, int base) -{ - string ret; - ULongToString(ret, value, flags, base); - return ret; -} - -inline -string NStr::UIntToString(long value, - TNumToStringFlags flags, int base) -{ - string ret; - ULongToString(ret, (unsigned long)value, flags, base); - return ret; -} - -#if !NCBI_INT8_IS_LONG -inline -string NStr::UIntToString(Int8 value, - TNumToStringFlags flags, int base) -{ - string ret; - UInt8ToString(ret, (Uint8)value, flags, base); - return ret; -} - -inline -string NStr::UIntToString(Uint8 value, - TNumToStringFlags flags, int base) -{ - string ret; - UInt8ToString(ret, value, flags, base); - return ret; -} -#endif - inline void NStr::UIntToString(string& out_str, unsigned int value, TNumToStringFlags flags, int base) @@ -5204,36 +5160,6 @@ void NStr::UIntToString(string& out_str, int value, UIntToString(out_str, (unsigned int)value, flags, base); } -inline -void NStr::UIntToString(string& out_str, unsigned long value, - TNumToStringFlags flags, int base) -{ - ULongToString(out_str, value, flags, base); -} - -inline -void NStr::UIntToString(string& out_str, long value, - TNumToStringFlags flags, int base) -{ - ULongToString(out_str, (unsigned long)value, flags, base); -} - -#if !NCBI_INT8_IS_LONG -inline -void NStr::UIntToString(string& out_str, Int8 value, - TNumToStringFlags flags, int base) -{ - UInt8ToString(out_str, (Uint8)value, flags, base); -} - -inline -void NStr::UIntToString(string& out_str, Uint8 value, - TNumToStringFlags flags, int base) -{ - UInt8ToString(out_str, value, flags, base); -} -#endif - inline string NStr::LongToString(long value, TNumToStringFlags flags, int base) @@ -6065,7 +5991,6 @@ bool PNocase_Conditional_Generic::operator()(const T& s1, const T& s2) const } - END_NCBI_NAMESPACE; #endif /* CORELIB___NCBISTR__HPP */ diff --git a/c++/include/corelib/request_ctx.hpp b/c++/include/corelib/request_ctx.hpp index 999efb9e..29fc93fa 100644 --- a/c++/include/corelib/request_ctx.hpp +++ b/c++/include/corelib/request_ctx.hpp @@ -1,7 +1,7 @@ #ifndef CORELIB___REQUEST_CTX__HPP #define CORELIB___REQUEST_CTX__HPP -/* $Id: request_ctx.hpp 489237 2016-01-11 17:27:20Z grichenk $ +/* $Id: request_ctx.hpp 508071 2016-07-25 16:13:27Z grichenk $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -58,6 +58,63 @@ BEGIN_NCBI_SCOPE // Forward declarations class CRequestContext_PassThrough; + +/// Helper class to hold hit id and sub-hit counter which can be shared +/// between multiple request contexts. +class NCBI_XNCBI_EXPORT CSharedHitId +{ +public: + explicit CSharedHitId(const string& hit) : m_HitId(hit), m_SubHitId(0) {} + CSharedHitId(void) : m_SubHitId(0) {} + ~CSharedHitId(void) {} + + bool Empty(void) const { return m_HitId.empty(); } + + /// Mark this hit id as a shared one and start using shared counter. + void SetShared(void) const + { + if ( IsShared() ) return; // Already shared. + m_SharedSubHitId.Reset(new TSharedCounter()); + m_SharedSubHitId->GetData().Set(m_SubHitId); + } + + /// Check if shared counter is used. + bool IsShared(void) const { return m_SharedSubHitId; } + + /// Get hit id value. + const string& GetHitId(void) const { return m_HitId; } + + /// Set new hit id value. This resets sub-hit counter and makes it non-shared. + void SetHitId(const string& hit_id) + { + m_SharedSubHitId.Reset(); + m_SubHitId = 0; + m_HitId = hit_id; + } + + typedef unsigned int TSubHitId; + + /// Get current sub-hit id value. + TSubHitId GetCurrentSubHitId(void) const + { + return IsShared() ? (TSubHitId)m_SharedSubHitId->GetData().Get() : m_SubHitId; + } + + /// Get next sub-hit id value. + TSubHitId GetNextSubHitId(void) + { + return IsShared() ? (TSubHitId)m_SharedSubHitId->GetData().Add(1) : ++m_SubHitId; + } + +private: + typedef CObjectFor TSharedCounter; + + string m_HitId; + TSubHitId m_SubHitId; + mutable CRef m_SharedSubHitId; +}; + + class NCBI_XNCBI_EXPORT CRequestContext : public CObject { public: @@ -150,10 +207,9 @@ public: /// the hit id value. const string& SetHitID(void); /// Get current hit id appended with auto-incremented sub-hit id. - /// If hit id is not set, return empty string. - const string& GetNextSubHitID(void); + const string& GetNextSubHitID(CTempString prefix = CTempString()); /// Get the last generated sub-hit id. - const string& GetCurrentSubHitID(void); + const string& GetCurrentSubHitID(CTempString prefix = CTempString()); /// Dtab bool IsSetDtab(void) const; @@ -299,9 +355,10 @@ private: // If 'ignore_app_state' is set, log any available hit id anyway. void x_LogHitID(bool ignore_app_state = false) const; + void x_SetHitID(const CSharedHitId& hit_id); string x_GetHitID(CDiagContext::EDefaultHitIDFlags flag) const; - void x_UpdateSubHitID(bool increment); + void x_UpdateSubHitID(bool increment, CTempString prefix); static bool& sx_GetDefaultAutoIncRequestIDOnPost(void); @@ -319,10 +376,9 @@ private: EDiagAppState m_AppState; string m_ClientIP; CEncodedString m_SessionID; - string m_HitID; + CSharedHitId m_HitID; string m_Dtab; mutable bool m_LoggedHitID; - int m_SubHitID; int m_ReqStatus; CStopWatch m_ReqTimer; Int8 m_BytesRd; @@ -533,25 +589,24 @@ inline void CRequestContext::UnsetHitID(void) { x_UnsetProp(eProp_HitID); - m_HitID.clear(); + m_HitID.SetHitId(kEmptyStr); m_LoggedHitID = false; - m_SubHitID = 0; m_SubHitIDCache.clear(); } inline -const string& CRequestContext::GetNextSubHitID(void) +const string& CRequestContext::GetNextSubHitID(CTempString prefix) { - x_UpdateSubHitID(true); + x_UpdateSubHitID(true, prefix); return m_SubHitIDCache; } inline -const string& CRequestContext::GetCurrentSubHitID(void) +const string& CRequestContext::GetCurrentSubHitID(CTempString prefix) { - x_UpdateSubHitID(false); + x_UpdateSubHitID(false, prefix); return m_SubHitIDCache; } diff --git a/c++/include/corelib/rwstream.hpp b/c++/include/corelib/rwstream.hpp index 3e879677..fb49dd51 100644 --- a/c++/include/corelib/rwstream.hpp +++ b/c++/include/corelib/rwstream.hpp @@ -1,7 +1,7 @@ #ifndef CORELIB___RWSTREAM__HPP #define CORELIB___RWSTREAM__HPP -/* $Id: rwstream.hpp 426324 2014-02-07 17:28:45Z lavr $ +/* $Id: rwstream.hpp 500279 2016-05-03 17:12:04Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -94,7 +94,7 @@ BEGIN_NCBI_SCOPE /// may specify the buffer location (if 0, an internal storage gets /// allocated and later freed upon stream destruction). /// -/// @param flags +/// @param stm_flags /// controls whether IReader is destroyed upon stream destruction, /// whether exceptions get logged (or leaked, or caught silently), etc. /// @@ -106,10 +106,10 @@ class NCBI_XNCBI_EXPORT CRStream : public CNcbiIstream { public: CRStream(IReader* r, - streamsize buf_size = 0, - CT_CHAR_TYPE* buf = 0, - CRWStreambuf::TFlags flags = 0) - : CNcbiIstream(0), m_Sb(r, 0, buf_size, buf, flags) + streamsize buf_size = 0, + CT_CHAR_TYPE* buf = 0, + CRWStreambuf::TFlags stm_flags = 0) + : CNcbiIstream(0), m_Sb(r, 0, buf_size, buf, stm_flags) { init(r ? &m_Sb : 0); } @@ -131,7 +131,7 @@ private: /// may specify the buffer location (if 0, an internal storage gets /// allocated and later freed upon stream destruction). /// -/// @param flags +/// @param stm_flags /// controls whether IWriter is destroyed upon stream destruction, /// whether exceptions get logged (or leaked, or caught silently), etc. /// @@ -143,10 +143,10 @@ class NCBI_XNCBI_EXPORT CWStream : public CNcbiOstream { public: CWStream(IWriter* w, - streamsize buf_size = 0, - CT_CHAR_TYPE* buf = 0, - CRWStreambuf::TFlags flags = 0) - : CNcbiOstream(0), m_Sb(0, w, buf_size, buf, flags) + streamsize buf_size = 0, + CT_CHAR_TYPE* buf = 0, + CRWStreambuf::TFlags stm_flags = 0) + : CNcbiOstream(0), m_Sb(0, w, buf_size, buf, stm_flags) { init(w ? &m_Sb : 0); } @@ -169,7 +169,7 @@ private: /// may specify the buffer location (if 0, an internal storage gets /// allocated and later freed upon stream destruction). /// -/// @param flags +/// @param stm_flags /// controls whether IReaderWriter is destroyed upon stream destruction, /// whether exceptions get logged (or leaked, or caught silently), etc. /// @@ -181,20 +181,20 @@ class NCBI_XNCBI_EXPORT CRWStream : public CNcbiIostream { public: CRWStream(IReaderWriter* rw, - streamsize buf_size = 0, - CT_CHAR_TYPE* buf = 0, - CRWStreambuf::TFlags flags = 0) - : CNcbiIostream(0), m_Sb(rw, buf_size, buf, flags) + streamsize buf_size = 0, + CT_CHAR_TYPE* buf = 0, + CRWStreambuf::TFlags stm_flags = 0) + : CNcbiIostream(0), m_Sb(rw, buf_size, buf, stm_flags) { init(rw ? &m_Sb : 0); } CRWStream(IReader* r, IWriter* w, - streamsize buf_size = 0, - CT_CHAR_TYPE* buf = 0, - CRWStreambuf::TFlags flags = 0) - : CNcbiIostream(0), m_Sb(r, w, buf_size, buf, flags) + streamsize buf_size = 0, + CT_CHAR_TYPE* buf = 0, + CRWStreambuf::TFlags stm_flags = 0) + : CNcbiIostream(0), m_Sb(r, w, buf_size, buf, stm_flags) { init(r || w ? &m_Sb : 0); } diff --git a/c++/include/corelib/version.hpp b/c++/include/corelib/version.hpp index 18ee5c2a..eaaf9461 100644 --- a/c++/include/corelib/version.hpp +++ b/c++/include/corelib/version.hpp @@ -1,7 +1,7 @@ #ifndef CORELIB___VERSION__HPP #define CORELIB___VERSION__HPP -/* $Id: version.hpp 492326 2016-02-16 19:38:11Z ivanov $ +/* $Id: version.hpp 508153 2016-07-26 15:24:18Z elisovdn $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -286,6 +286,7 @@ public: fPackageFull = 0x08, ///< Print package info, if available fBuildInfo = 0x10, ///< Print build info (date and tag) fBuildSignature = 0x20, ///< Print build signature, if available + fTCBuildNumber = 0x40, ///< Print TeamCity build number, if available fPrintAll = 0xFF ///< Print all version data }; typedef int TPrintFlags; ///< Binary OR of EPrintFlags diff --git a/c++/include/dbapi/dbapi.hpp b/c++/include/dbapi/dbapi.hpp index 62649cd6..b66c713f 100644 --- a/c++/include/dbapi/dbapi.hpp +++ b/c++/include/dbapi/dbapi.hpp @@ -1,7 +1,7 @@ #ifndef DBAPI___DBAPI__HPP #define DBAPI___DBAPI__HPP -/* $Id: dbapi.hpp 498367 2016-04-15 17:18:04Z ivanov $ +/* $Id: dbapi.hpp 501456 2016-05-16 15:12:46Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -906,7 +906,7 @@ public: virtual void SetTimeout(size_t nof_secs) = 0; /// Set timeout for command cancellation and connection closing - virtual void SetCancelTimeout(size_t nof_secs) {} + virtual void SetCancelTimeout(size_t /*nof_secs*/) {} /// Get connection timeout. virtual size_t GetTimeout(void) const; diff --git a/c++/include/dbapi/driver/dbapi_driver_conn_mgr.hpp b/c++/include/dbapi/driver/dbapi_driver_conn_mgr.hpp index 4a1854ae..ef54d133 100644 --- a/c++/include/dbapi/driver/dbapi_driver_conn_mgr.hpp +++ b/c++/include/dbapi/driver/dbapi_driver_conn_mgr.hpp @@ -2,7 +2,7 @@ #define DBAPI_DRIVER_CONN_MGR_HPP -/* $Id: dbapi_driver_conn_mgr.hpp 494592 2016-03-08 17:55:58Z ivanov $ +/* $Id: dbapi_driver_conn_mgr.hpp 494417 2016-03-07 15:06:35Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/dbapi/driver/dbapi_driver_convert.hpp b/c++/include/dbapi/driver/dbapi_driver_convert.hpp index 1d7b7d22..d152b0b0 100644 --- a/c++/include/dbapi/driver/dbapi_driver_convert.hpp +++ b/c++/include/dbapi/driver/dbapi_driver_convert.hpp @@ -1,7 +1,7 @@ #ifndef DBAPI_DRIVER___DBAPI_DRIVER_CONVERT__HPP #define DBAPI_DRIVER___DBAPI_DRIVER_CONVERT__HPP -/* $Id: dbapi_driver_convert.hpp 498375 2016-04-15 17:20:50Z ivanov $ +/* $Id: dbapi_driver_convert.hpp 498292 2016-04-14 19:07:55Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NTOICE diff --git a/c++/include/dbapi/driver/dbapi_object_convert.hpp b/c++/include/dbapi/driver/dbapi_object_convert.hpp index 0ecbb712..2afb24b4 100644 --- a/c++/include/dbapi/driver/dbapi_object_convert.hpp +++ b/c++/include/dbapi/driver/dbapi_object_convert.hpp @@ -1,7 +1,7 @@ #ifndef DBAPI_DRIVER___DBAPI_OBJECT_CONVERT__HPP #define DBAPI_DRIVER___DBAPI_OBJECT_CONVERT__HPP -/* $Id: dbapi_object_convert.hpp 498375 2016-04-15 17:20:50Z ivanov $ +/* $Id: dbapi_object_convert.hpp 498292 2016-04-14 19:07:55Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NTOICE diff --git a/c++/include/dbapi/driver/dbapi_svc_mapper.hpp b/c++/include/dbapi/driver/dbapi_svc_mapper.hpp index 5e9a6891..628c1f38 100644 --- a/c++/include/dbapi/driver/dbapi_svc_mapper.hpp +++ b/c++/include/dbapi/driver/dbapi_svc_mapper.hpp @@ -1,7 +1,7 @@ #ifndef DBAPI_SVC_MAPPER_HPP #define DBAPI_SVC_MAPPER_HPP -/* $Id: dbapi_svc_mapper.hpp 494592 2016-03-08 17:55:58Z ivanov $ +/* $Id: dbapi_svc_mapper.hpp 506715 2016-07-11 16:01:42Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -98,6 +98,7 @@ public: double preference = 100.0); virtual void GetServersList(const string& service, list* serv_list) const; + virtual bool RecordServer(I_ConnectionExtra& extra) const; void Push(const CRef& mapper); void Pop(void); @@ -203,6 +204,7 @@ private: TLBNameMap m_LBNameMap; TServiceMap m_ServerMap; TServiceUsageMap m_ServiceUsageMap; + TServiceUsageMap m_OrigServiceUsageMap; }; class NCBI_DBAPIDRIVER_EXPORT CDBUniversalMapper : public CDBServiceMapperCoR diff --git a/c++/include/dbapi/driver/exception.hpp b/c++/include/dbapi/driver/exception.hpp index c7e3bdb7..27b6cc0c 100644 --- a/c++/include/dbapi/driver/exception.hpp +++ b/c++/include/dbapi/driver/exception.hpp @@ -1,7 +1,7 @@ #ifndef DBAPI_DRIVER___EXCEPTION__HPP #define DBAPI_DRIVER___EXCEPTION__HPP -/* $Id: exception.hpp 440575 2014-07-15 13:59:14Z ivanov $ +/* $Id: exception.hpp 501456 2016-05-16 15:12:46Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -156,8 +156,8 @@ public: }; struct NCBI_DBAPIDRIVER_EXPORT SMessageInContext { - SMessageInContext(const string& msg, const SContext& context) - : message(msg), context(&context) + SMessageInContext(const string& msg, const SContext& ctx) + : message(msg), context(&ctx) { } SMessageInContext(const string& msg = kEmptyStr) : message(msg) @@ -166,7 +166,7 @@ public: : message(msg) { } - SMessageInContext operator+(const SContext& context) const; + SMessageInContext operator+(const SContext& ctx) const; string message; CConstRef context; @@ -210,8 +210,8 @@ public: { return m_Context->database_name; } const SContext& GetContext(void) const { return *m_Context; } - void ApplyContext(const SContext& context) - { x_SetContext().UpdateFrom(context); } + void ApplyContext(const SContext& ctx) + { x_SetContext().UpdateFrom(ctx); } void SetFromConnection(const impl::CConnection& connection); void SetExtraMsg(const string& msg) { x_SetContext().extra_msg = msg; } diff --git a/c++/include/dbapi/driver/impl/dbapi_driver_utils.hpp b/c++/include/dbapi/driver/impl/dbapi_driver_utils.hpp index 2f7474ee..dd498083 100644 --- a/c++/include/dbapi/driver/impl/dbapi_driver_utils.hpp +++ b/c++/include/dbapi/driver/impl/dbapi_driver_utils.hpp @@ -1,7 +1,7 @@ #ifndef DBAPI_DRIVER_IMPL___DBAPI_DRIVER_UTILS__HPP #define DBAPI_DRIVER_IMPL___DBAPI_DRIVER_UTILS__HPP -/* $Id: dbapi_driver_utils.hpp 450609 2014-10-28 18:46:14Z ucko $ +/* $Id: dbapi_driver_utils.hpp 503691 2016-06-07 15:44:43Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -259,6 +259,19 @@ string ConvertN2A(Uint4 host); NCBI_DBAPIDRIVER_EXPORT SIZE_TYPE GetValidUTF8Len(const CTempString& ts); +enum EBinaryToHexFlags +{ + fB2H_NoFinalNul = 0x1, + fB2H_NoPrefix = 0x2 +}; +typedef int TBinaryToHexFlags; +// Returns the number of bytes used in buffer, NOT counting the final +// NUL (if it wasn't suppressed). +NCBI_DBAPIDRIVER_EXPORT +size_t binary_to_hex_string(char* buffer, size_t buffer_size, + const void* value, size_t value_size, + TBinaryToHexFlags flags = 0); + ///////////////////////////////////////////////////////////////////////////// inline void diff --git a/c++/include/dbapi/driver/impl/dbapi_impl_cmd.hpp b/c++/include/dbapi/driver/impl/dbapi_impl_cmd.hpp index d136f9f5..6d1b6a6e 100644 --- a/c++/include/dbapi/driver/impl/dbapi_impl_cmd.hpp +++ b/c++/include/dbapi/driver/impl/dbapi_impl_cmd.hpp @@ -1,7 +1,7 @@ #ifndef DBAPI_DRIVER_IMPL___DBAPI_IMPL_CMD__HPP #define DBAPI_DRIVER_IMPL___DBAPI_IMPL_CMD__HPP -/* $Id: dbapi_impl_cmd.hpp 498367 2016-04-15 17:18:04Z ivanov $ +/* $Id: dbapi_impl_cmd.hpp 497635 2016-04-08 13:52:30Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/dbapi/driver/impl/dbapi_impl_connection.hpp b/c++/include/dbapi/driver/impl/dbapi_impl_connection.hpp index 293bb012..bd8f1315 100644 --- a/c++/include/dbapi/driver/impl/dbapi_impl_connection.hpp +++ b/c++/include/dbapi/driver/impl/dbapi_impl_connection.hpp @@ -2,7 +2,7 @@ #define DBAPI_DRIVER_IMPL___DBAPI_IMPL_CONNECTION__HPP -/* $Id: dbapi_impl_connection.hpp 498367 2016-04-15 17:18:04Z ivanov $ +/* $Id: dbapi_impl_connection.hpp 510689 2016-08-15 15:29:39Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -120,6 +120,11 @@ public: return *m_ExceptionContext; } + const string& GetRequestedServer(void) const + { + return m_RequestedServer; + } + public: /// Check out if connection is alive (this function doesn't ping the server, /// it just checks the status of connection which was set by the last @@ -312,6 +317,8 @@ protected: return const_cast(m_UserData.GetPointerOrNull()); } + void x_RecordServer(const CDBServer& server); + private: typedef deque TCommandList; @@ -326,8 +333,9 @@ private: CDBConnParams::EServerType m_ServerType; bool m_ServerTypeIsKnown; - const Uint4 m_Host; - const Uint2 m_Port; + const string m_RequestedServer; + Uint4 m_Host; + Uint2 m_Port; const string m_Passwd; const string m_Pool; unsigned int m_PoolMinSize; diff --git a/c++/include/dbapi/driver/impl/dbapi_impl_context.hpp b/c++/include/dbapi/driver/impl/dbapi_impl_context.hpp index 7db2608e..a80db1cf 100644 --- a/c++/include/dbapi/driver/impl/dbapi_impl_context.hpp +++ b/c++/include/dbapi/driver/impl/dbapi_impl_context.hpp @@ -1,7 +1,7 @@ #ifndef DBAPI_DRIVER_IMPL___DBAPI_IMPL_CONTEXT__HPP #define DBAPI_DRIVER_IMPL___DBAPI_IMPL_CONTEXT__HPP -/* $Id: dbapi_impl_context.hpp 498367 2016-04-15 17:18:04Z ivanov $ +/* $Id: dbapi_impl_context.hpp 516380 2016-10-13 11:32:10Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -76,7 +76,8 @@ struct NCBI_DBAPIDRIVER_EXPORT SDBConfParams fPasswordKeySet = 0x4000, fPoolIdleTimeSet = 0x8000, fPoolWaitTimeSet = 0x10000, - fPoolAllowTempSet= 0x20000 + fPoolAllowTempSet= 0x20000, + fContRaiserrorSet= 0x40000 }; typedef unsigned int TFlags; @@ -99,6 +100,7 @@ struct NCBI_DBAPIDRIVER_EXPORT SDBConfParams string pool_idle_time; string pool_wait_time; string pool_allow_temp_overflow; + string continue_after_raiserror; string args; @@ -122,6 +124,8 @@ struct NCBI_DBAPIDRIVER_EXPORT SDBConfParams bool IsPoolWaitTimeSet(void) { return IsFlagSet(fPoolWaitTimeSet); } bool IsPoolAllowTempOverflowSet(void) { return IsFlagSet(fPoolAllowTempSet); } + bool IsContinueAfterRaiserrorSet(void) + { return IsFlagSet(fContRaiserrorSet); } bool IsArgsSet(void) { return IsFlagSet(fArgsSet); } void Clear(void); @@ -267,11 +271,10 @@ protected: private: mutable CMutex m_DefaultCtxMtx; -#ifdef NCBI_THREADS + mutable CMutex m_PoolMutex; //< for m_PoolSem* and m_(Not)InUse CSemaphore m_PoolSem; string m_PoolSemSubject; CConnection* m_PoolSemConn; -#endif unsigned int m_LoginTimeout; //< Login timeout. unsigned int m_Timeout; //< Connection timeout. diff --git a/c++/include/dbapi/driver/impl/dbapi_impl_result.hpp b/c++/include/dbapi/driver/impl/dbapi_impl_result.hpp index a1fefb68..07d31c97 100644 --- a/c++/include/dbapi/driver/impl/dbapi_impl_result.hpp +++ b/c++/include/dbapi/driver/impl/dbapi_impl_result.hpp @@ -1,7 +1,7 @@ #ifndef DBAPI_DRIVER_IMPL___DBAPI_IMPL_RESULT__HPP #define DBAPI_DRIVER_IMPL___DBAPI_IMPL_RESULT__HPP -/* $Id: dbapi_impl_result.hpp 498367 2016-04-15 17:18:04Z ivanov $ +/* $Id: dbapi_impl_result.hpp 497635 2016-04-08 13:52:30Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/dbapi/driver/interfaces.hpp b/c++/include/dbapi/driver/interfaces.hpp index ee04b3c6..a39cafad 100644 --- a/c++/include/dbapi/driver/interfaces.hpp +++ b/c++/include/dbapi/driver/interfaces.hpp @@ -1,7 +1,7 @@ #ifndef DBAPI_DRIVER___INTERFACES__HPP #define DBAPI_DRIVER___INTERFACES__HPP -/* $Id: interfaces.hpp 498375 2016-04-15 17:20:50Z ivanov $ +/* $Id: interfaces.hpp 501812 2016-05-18 22:51:45Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -38,9 +38,7 @@ #include #include -#ifdef NCBI_OS_MSWIN -# include -#else // NCBI_OS_UNIX +#ifdef NCBI_OS_UNIX # include #endif @@ -1128,8 +1126,6 @@ private: -class I_ConnectionExtra; - ///////////////////////////////////////////////////////////////////////////// /// /// I_Connection:: @@ -1385,31 +1381,6 @@ public: }; -class NCBI_DBAPIDRIVER_EXPORT I_ConnectionExtra -{ -public: - virtual ~I_ConnectionExtra(void); - -#ifdef NCBI_OS_MSWIN - typedef SOCKET TSockHandle; -#else - typedef int TSockHandle; -#endif - - /// Get OS handle of the socket represented by the connection - virtual TSockHandle GetLowLevelHandle(void) const = 0; - - virtual void SetUserData(CObject* data) = 0; - template T* GetUserData(void) - { return dynamic_cast(x_GetUserData()); } - template const T* GetUserData(void) const - { return dynamic_cast(x_GetUserData()); } - -protected: - virtual CObject* x_GetUserData(void) const = 0; -}; - - END_NCBI_SCOPE diff --git a/c++/include/dbapi/driver/odbc/interfaces.hpp b/c++/include/dbapi/driver/odbc/interfaces.hpp index 90e15f36..bcd65f5a 100644 --- a/c++/include/dbapi/driver/odbc/interfaces.hpp +++ b/c++/include/dbapi/driver/odbc/interfaces.hpp @@ -1,7 +1,7 @@ #ifndef DBAPI_DRIVER_ODBC___INTERFACES__HPP #define DBAPI_DRIVER_ODBC___INTERFACES__HPP -/* $Id: interfaces.hpp 498367 2016-04-15 17:18:04Z ivanov $ +/* $Id: interfaces.hpp 497635 2016-04-08 13:52:30Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/dbapi/driver/public.hpp b/c++/include/dbapi/driver/public.hpp index a3ef0a98..6eb1c52a 100644 --- a/c++/include/dbapi/driver/public.hpp +++ b/c++/include/dbapi/driver/public.hpp @@ -1,7 +1,7 @@ #ifndef DBAPI_DRIVER___PUBLIC__HPP #define DBAPI_DRIVER___PUBLIC__HPP -/* $Id: public.hpp 498375 2016-04-15 17:20:50Z ivanov $ +/* $Id: public.hpp 498292 2016-04-14 19:07:55Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/dbapi/driver/types.hpp b/c++/include/dbapi/driver/types.hpp index 8f2a9c7e..939d7a3f 100644 --- a/c++/include/dbapi/driver/types.hpp +++ b/c++/include/dbapi/driver/types.hpp @@ -1,7 +1,7 @@ #ifndef DBAPI_DRIVER___TYPES__HPP #define DBAPI_DRIVER___TYPES__HPP -/* $Id: types.hpp 498375 2016-04-15 17:20:50Z ivanov $ +/* $Id: types.hpp 498292 2016-04-14 19:07:55Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/dbapi/driver/util/blobstore.hpp b/c++/include/dbapi/driver/util/blobstore.hpp index 91f7bd4d..2bd6aebd 100644 --- a/c++/include/dbapi/driver/util/blobstore.hpp +++ b/c++/include/dbapi/driver/util/blobstore.hpp @@ -1,7 +1,7 @@ #ifndef DBAPI_UTILS___BLOBSTORE__HPP #define DBAPI_UTILS___BLOBSTORE__HPP -/* $Id: blobstore.hpp 498367 2016-04-15 17:18:04Z ivanov $ +/* $Id: blobstore.hpp 497635 2016-04-08 13:52:30Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/dbapi/error_codes.hpp b/c++/include/dbapi/error_codes.hpp index f51400b4..745ae4bb 100644 --- a/c++/include/dbapi/error_codes.hpp +++ b/c++/include/dbapi/error_codes.hpp @@ -1,7 +1,7 @@ #ifndef DBAPI___ERROR_CODES__HPP #define DBAPI___ERROR_CODES__HPP -/* $Id: error_codes.hpp 495422 2016-03-17 13:33:23Z ivanov $ +/* $Id: error_codes.hpp 516380 2016-10-13 11:32:10Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/dbapi/variant.hpp b/c++/include/dbapi/variant.hpp index 8b4de103..13eae804 100644 --- a/c++/include/dbapi/variant.hpp +++ b/c++/include/dbapi/variant.hpp @@ -1,7 +1,7 @@ #ifndef DBAPI___VARIANT__HPP #define DBAPI___VARIANT__HPP -/* $Id: variant.hpp 498375 2016-04-15 17:20:50Z ivanov $ +/* $Id: variant.hpp 498292 2016-04-14 19:07:55Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/html/htmlhelper.hpp b/c++/include/html/htmlhelper.hpp index 7fdcc3cb..03fa5ebd 100644 --- a/c++/include/html/htmlhelper.hpp +++ b/c++/include/html/htmlhelper.hpp @@ -1,7 +1,7 @@ #ifndef HTML___HTMLHELPER__HPP #define HTML___HTMLHELPER__HPP -/* $Id: htmlhelper.hpp 460167 2015-02-25 15:39:05Z ivanov $ +/* $Id: htmlhelper.hpp 501456 2016-05-16 15:12:46Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -212,11 +212,11 @@ void CIDs::Decode(const string& str) pos = 1; // start of number } - SIZE_TYPE end; // end of number - while ( (end = str.find_first_of(" +_,", pos)) != NPOS ) { - id = AddID(cmd, id, GetNumber(str.substr(pos, end - pos))); - cmd = str[end]; - pos = end + 1; + SIZE_TYPE end_pos; // end of number + while ( (end_pos = str.find_first_of(" +_,", pos)) != NPOS ) { + id = AddID(cmd, id, GetNumber(str.substr(pos, end_pos - pos))); + cmd = str[end_pos]; + pos = end_pos + 1; } AddID(cmd, id, GetNumber(str.substr(pos))); } diff --git a/c++/include/html/nodemap.hpp b/c++/include/html/nodemap.hpp index fc3e75a6..ed8446b1 100644 --- a/c++/include/html/nodemap.hpp +++ b/c++/include/html/nodemap.hpp @@ -1,7 +1,7 @@ #ifndef HTML___NODEMAP__HPP #define HTML___NODEMAP__HPP -/* $Id: nodemap.hpp 103491 2007-05-04 17:18:18Z kazimird $ +/* $Id: nodemap.hpp 501456 2016-05-16 15:12:46Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -186,7 +186,7 @@ struct TagMapper : public BaseTagMapper TagMapper(CNCBINode* (C::*method)(void)) : m_Method(method) { return; } - virtual CNCBINode* MapTag(CNCBINode* _this, const string& name) const + virtual CNCBINode* MapTag(CNCBINode* _this, const string& /*name*/) const { return (dynamic_cast(_this)->*m_Method)(); } private: CNCBINode* (C::*m_Method)(void); diff --git a/c++/include/misc/error_codes.hpp b/c++/include/misc/error_codes.hpp new file mode 100644 index 00000000..10b42c38 --- /dev/null +++ b/c++/include/misc/error_codes.hpp @@ -0,0 +1,52 @@ +#ifndef MISC___ERROR_CODES__HPP +#define MISC___ERROR_CODES__HPP + +/* $Id: error_codes.hpp 467460 2015-05-13 18:25:03Z grichenk $ + * =========================================================================== + * + * PUBLIC DOMAIN NOTICE + * National Center for Biotechnology Information + * + * This software/database is a "United States Government Work" under the + * terms of the United States Copyright Act. It was written as part of + * the author's official duties as a United States Government employee and + * thus cannot be copyrighted. This software/database is freely available + * to the public for use. The National Library of Medicine and the U.S. + * Government have not placed any restriction on its use or reproduction. + * + * Although all reasonable efforts have been taken to ensure the accuracy + * and reliability of the software and data, the NLM and the U.S. + * Government do not and cannot warrant the performance or results that + * may be obtained by using this software or data. The NLM and the U.S. + * Government disclaim all warranties, express or implied, including + * warranties of performance, merchantability or fitness for any particular + * purpose. + * + * Please cite the author in any work or product based on this material. + * + * =========================================================================== + * + * Authors: Pavel Ivanov + * + */ + +/// @file error_codes.hpp +/// Definition of all error codes used in misc libraries +/// (xcgi_redirect.lib, xgridcgi.lib). +/// + + +#include + + +BEGIN_NCBI_SCOPE + + +NCBI_DEFINE_ERRCODE_X(Misc_CgiRedirect, 701, 2); +NCBI_DEFINE_ERRCODE_X(Misc_GridCgi, 702, 3); +NCBI_DEFINE_ERRCODE_X(Misc_EutilsClient, 703, 6); + +END_NCBI_SCOPE + + +#endif /* MISC___ERROR_CODES__HPP */ diff --git a/c++/include/ncbi_pch.hpp b/c++/include/ncbi_pch.hpp index d7b2df27..5f36f13b 100644 --- a/c++/include/ncbi_pch.hpp +++ b/c++/include/ncbi_pch.hpp @@ -1,5 +1,5 @@ #if defined(NCBI_USE_PCH) && !defined(NCBI_PCH__HPP) -/* $Id: ncbi_pch.hpp 500618 2016-05-05 19:15:27Z blastadm $ +/* $Id: ncbi_pch.hpp 521318 2016-12-07 19:37:59Z blastadm $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/ncbi_source_ver.h b/c++/include/ncbi_source_ver.h index 53cda902..291450b4 100644 --- a/c++/include/ncbi_source_ver.h +++ b/c++/include/ncbi_source_ver.h @@ -1,4 +1,4 @@ -/* $Id: ncbi_source_ver.h 500618 2016-05-05 19:15:27Z blastadm $ +/* $Id: ncbi_source_ver.h 521318 2016-12-07 19:37:59Z blastadm $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/ncbiconf.h b/c++/include/ncbiconf.h index 8434a4c6..87a6e18e 100644 --- a/c++/include/ncbiconf.h +++ b/c++/include/ncbiconf.h @@ -1,7 +1,7 @@ #ifndef FORWARDING_NCBICONF_H #define FORWARDING_NCBICONF_H -/* $Id: ncbiconf.h 500618 2016-05-05 19:15:27Z blastadm $ +/* $Id: ncbiconf.h 521318 2016-12-07 19:37:59Z blastadm $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/objects/biblio/MedlineUID.hpp b/c++/include/objects/biblio/MedlineUID.hpp new file mode 100644 index 00000000..2e67f4a2 --- /dev/null +++ b/c++/include/objects/biblio/MedlineUID.hpp @@ -0,0 +1,76 @@ +/* $Id: MedlineUID.hpp 498065 2016-04-12 22:14:52Z vasilche $ + * =========================================================================== + * + * PUBLIC DOMAIN NOTICE + * National Center for Biotechnology Information + * + * This software/database is a "United States Government Work" under the + * terms of the United States Copyright Act. It was written as part of + * the author's official duties as a United States Government employee and + * thus cannot be copyrighted. This software/database is freely available + * to the public for use. The National Library of Medicine and the U.S. + * Government have not placed any restriction on its use or reproduction. + * + * Although all reasonable efforts have been taken to ensure the accuracy + * and reliability of the software and data, the NLM and the U.S. + * Government do not and cannot warrant the performance or results that + * may be obtained by using this software or data. The NLM and the U.S. + * Government disclaim all warranties, express or implied, including + * warranties of performance, merchantability or fitness for any particular + * purpose. + * + * Please cite the author in any work or product based on this material. + * + * =========================================================================== + * + */ + +/// @file MedlineUID.hpp +/// User-defined methods of the data storage class. +/// +/// This file was originally generated by application DATATOOL +/// using the following specifications: +/// 'biblio.asn'. +/// +/// New methods or data members can be added to it if needed. +/// See also: MedlineUID_.hpp + + +#ifndef OBJECTS_BIBLIO_MEDLINEUID_HPP +#define OBJECTS_BIBLIO_MEDLINEUID_HPP + + +// generated includes +#include + +// generated classes + +BEGIN_NCBI_SCOPE + +BEGIN_objects_SCOPE // namespace ncbi::objects:: + +///////////////////////////////////////////////////////////////////////////// +class NCBI_BIBLIO_EXPORT CMedlineUID : public CMedlineUID_Base +{ + typedef CMedlineUID_Base Tparent; +public: + CMedlineUID(void) {} + + /// Explicit constructor from the primitive type. + explicit CMedlineUID(const ncbi::TEntrezId& data) + : Tparent(data) {} + +#ifdef NCBI_STRICT_ENTREZ_ID + /// Explicit constructor from zero. + explicit CMedlineUID(std::nullptr_t zero) + : Tparent((TIntId)0) {} +#endif +}; + +END_objects_SCOPE // namespace ncbi::objects:: + +END_NCBI_SCOPE + + +#endif // OBJECTS_BIBLIO_MEDLINEUID_HPP +/* Original file checksum: lines: 70, chars: 2190, CRC32: 8a1e1a16 */ diff --git a/c++/include/objects/biblio/PmcID.hpp b/c++/include/objects/biblio/PmcID.hpp new file mode 100644 index 00000000..e5330288 --- /dev/null +++ b/c++/include/objects/biblio/PmcID.hpp @@ -0,0 +1,76 @@ +/* $Id: PmcID.hpp 498065 2016-04-12 22:14:52Z vasilche $ + * =========================================================================== + * + * PUBLIC DOMAIN NOTICE + * National Center for Biotechnology Information + * + * This software/database is a "United States Government Work" under the + * terms of the United States Copyright Act. It was written as part of + * the author's official duties as a United States Government employee and + * thus cannot be copyrighted. This software/database is freely available + * to the public for use. The National Library of Medicine and the U.S. + * Government have not placed any restriction on its use or reproduction. + * + * Although all reasonable efforts have been taken to ensure the accuracy + * and reliability of the software and data, the NLM and the U.S. + * Government do not and cannot warrant the performance or results that + * may be obtained by using this software or data. The NLM and the U.S. + * Government disclaim all warranties, express or implied, including + * warranties of performance, merchantability or fitness for any particular + * purpose. + * + * Please cite the author in any work or product based on this material. + * + * =========================================================================== + * + */ + +/// @file PmcID.hpp +/// User-defined methods of the data storage class. +/// +/// This file was originally generated by application DATATOOL +/// using the following specifications: +/// 'biblio.asn'. +/// +/// New methods or data members can be added to it if needed. +/// See also: PmcID_.hpp + + +#ifndef OBJECTS_BIBLIO_PMCID_HPP +#define OBJECTS_BIBLIO_PMCID_HPP + + +// generated includes +#include + +// generated classes + +BEGIN_NCBI_SCOPE + +BEGIN_objects_SCOPE // namespace ncbi::objects:: + +///////////////////////////////////////////////////////////////////////////// +class NCBI_BIBLIO_EXPORT CPmcID : public CPmcID_Base +{ + typedef CPmcID_Base Tparent; +public: + CPmcID(void) {} + + /// Explicit constructor from the primitive type. + explicit CPmcID(const ncbi::TEntrezId& data) + : Tparent(data) {} + +#ifdef NCBI_STRICT_ENTREZ_ID + /// Explicit constructor from zero. + explicit CPmcID(std::nullptr_t zero) + : Tparent((TIntId)0) {} +#endif +}; + +END_objects_SCOPE // namespace ncbi::objects:: + +END_NCBI_SCOPE + + +#endif // OBJECTS_BIBLIO_PMCID_HPP +/* Original file checksum: lines: 70, chars: 2135, CRC32: dbe555d8 */ diff --git a/c++/include/objects/biblio/PubMedId.hpp b/c++/include/objects/biblio/PubMedId.hpp new file mode 100644 index 00000000..3108b5c6 --- /dev/null +++ b/c++/include/objects/biblio/PubMedId.hpp @@ -0,0 +1,76 @@ +/* $Id: PubMedId.hpp 498065 2016-04-12 22:14:52Z vasilche $ + * =========================================================================== + * + * PUBLIC DOMAIN NOTICE + * National Center for Biotechnology Information + * + * This software/database is a "United States Government Work" under the + * terms of the United States Copyright Act. It was written as part of + * the author's official duties as a United States Government employee and + * thus cannot be copyrighted. This software/database is freely available + * to the public for use. The National Library of Medicine and the U.S. + * Government have not placed any restriction on its use or reproduction. + * + * Although all reasonable efforts have been taken to ensure the accuracy + * and reliability of the software and data, the NLM and the U.S. + * Government do not and cannot warrant the performance or results that + * may be obtained by using this software or data. The NLM and the U.S. + * Government disclaim all warranties, express or implied, including + * warranties of performance, merchantability or fitness for any particular + * purpose. + * + * Please cite the author in any work or product based on this material. + * + * =========================================================================== + * + */ + +/// @file PubMedId.hpp +/// User-defined methods of the data storage class. +/// +/// This file was originally generated by application DATATOOL +/// using the following specifications: +/// 'biblio.asn'. +/// +/// New methods or data members can be added to it if needed. +/// See also: PubMedId_.hpp + + +#ifndef OBJECTS_BIBLIO_PUBMEDID_HPP +#define OBJECTS_BIBLIO_PUBMEDID_HPP + + +// generated includes +#include + +// generated classes + +BEGIN_NCBI_SCOPE + +BEGIN_objects_SCOPE // namespace ncbi::objects:: + +///////////////////////////////////////////////////////////////////////////// +class NCBI_BIBLIO_EXPORT CPubMedId : public CPubMedId_Base +{ + typedef CPubMedId_Base Tparent; +public: + CPubMedId(void) {} + + /// Explicit constructor from the primitive type. + explicit CPubMedId(const ncbi::TEntrezId& data) + : Tparent(data) {} + +#ifdef NCBI_STRICT_ENTREZ_ID + /// Explicit constructor from zero. + explicit CPubMedId(std::nullptr_t zero) + : Tparent((TIntId)0) {} +#endif +}; + +END_objects_SCOPE // namespace ncbi::objects:: + +END_NCBI_SCOPE + + +#endif // OBJECTS_BIBLIO_PUBMEDID_HPP +/* Original file checksum: lines: 70, chars: 2168, CRC32: 981284c0 */ diff --git a/c++/include/objects/general/Dbtag.hpp b/c++/include/objects/general/Dbtag.hpp index 456af1fb..7140c1b9 100644 --- a/c++/include/objects/general/Dbtag.hpp +++ b/c++/include/objects/general/Dbtag.hpp @@ -1,4 +1,4 @@ -/* $Id: Dbtag.hpp 496201 2016-03-24 15:11:44Z ivanov $ +/* $Id: Dbtag.hpp 509625 2016-08-08 14:26:35Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -212,7 +212,9 @@ public: eDbtagType_ERIC, eDbtagType_I5KNAL, eDbtagType_VISTA, - eDbtagType_BEI + eDbtagType_BEI, + eDbtagType_Araport, + eDbtagType_VGNC }; enum EDbtagGroup { diff --git a/c++/include/objects/general/Name_std.hpp b/c++/include/objects/general/Name_std.hpp index be5e199b..36757ec7 100644 --- a/c++/include/objects/general/Name_std.hpp +++ b/c++/include/objects/general/Name_std.hpp @@ -1,4 +1,4 @@ -/* $Id: Name_std.hpp 103491 2007-05-04 17:18:18Z kazimird $ +/* $Id: Name_std.hpp 509242 2016-08-04 14:12:34Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -66,6 +66,9 @@ public: /// Get a list of NCBI's standard suffixes. static const TSuffixes& GetStandardSuffixes(void); + static void FixSuffix(string& suffix); + + bool ExtractSuffixFromLastName(); private: // Prohibit copy constructor and assignment operator diff --git a/c++/include/objects/general/User_object.hpp b/c++/include/objects/general/User_object.hpp index 7e78bf91..06e68b1c 100644 --- a/c++/include/objects/general/User_object.hpp +++ b/c++/include/objects/general/User_object.hpp @@ -1,4 +1,4 @@ -/* $Id: User_object.hpp 490266 2016-01-22 16:40:57Z kornbluh $ +/* $Id: User_object.hpp 501123 2016-05-11 17:29:51Z bollin $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -166,7 +166,8 @@ public: eObjectType_Unverified, eObjectType_ValidationSuppression, eObjectType_Cleanup, - eObjectType_AutodefOptions + eObjectType_AutodefOptions, + eObjectType_FileTrack }; EObjectType GetObjectType() const; @@ -185,6 +186,10 @@ public: void UpdateNcbiCleanup(int version); + // Set FileTrack URL + void SetFileTrackURL(const string& url); + void SetFileTrackUploadId(const string& upload_id); + private: /// Prohibit copy constructor and assignment operator CUser_object(const CUser_object& value); diff --git a/c++/include/objects/genomecoll/GCClient_GetAssemblyBySequ.hpp b/c++/include/objects/genomecoll/GCClient_GetAssemblyBySequ.hpp new file mode 100644 index 00000000..fc7dcb6b --- /dev/null +++ b/c++/include/objects/genomecoll/GCClient_GetAssemblyBySequ.hpp @@ -0,0 +1,89 @@ +/* $Id: GCClient_GetAssemblyBySequ.hpp 500855 2016-05-09 16:12:34Z zherikov $ + * =========================================================================== + * + * PUBLIC DOMAIN NOTICE + * National Center for Biotechnology Information + * + * This software/database is a "United States Government Work" under the + * terms of the United States Copyright Act. It was written as part of + * the author's official duties as a United States Government employee and + * thus cannot be copyrighted. This software/database is freely available + * to the public for use. The National Library of Medicine and the U.S. + * Government have not placed any restriction on its use or reproduction. + * + * Although all reasonable efforts have been taken to ensure the accuracy + * and reliability of the software and data, the NLM and the U.S. + * Government do not and cannot warrant the performance or results that + * may be obtained by using this software or data. The NLM and the U.S. + * Government disclaim all warranties, express or implied, including + * warranties of performance, merchantability or fitness for any particular + * purpose. + * + * Please cite the author in any work or product based on this material. + * + * =========================================================================== + * + */ + +/// @file GCClient_GetAssemblyBySequ.hpp +/// User-defined methods of the data storage class. +/// +/// This file was originally generated by application DATATOOL +/// using the following specifications: +/// 'gencoll_client.asn'. +/// +/// New methods or data members can be added to it if needed. +/// See also: GCClient_GetAssemblyBySequ_.hpp + + +#ifndef OBJECTS_GENOMECOLL_GCCLIENT_GETASSEMBLYBYSEQU_HPP +#define OBJECTS_GENOMECOLL_GCCLIENT_GETASSEMBLYBYSEQU_HPP + + +// generated includes +#include + +// generated classes + +BEGIN_NCBI_SCOPE + +BEGIN_objects_SCOPE // namespace ncbi::objects:: + +///////////////////////////////////////////////////////////////////////////// +class CGCClient_GetAssemblyBySequenceRequest : public CGCClient_GetAssemblyBySequenceRequest_Base +{ + typedef CGCClient_GetAssemblyBySequenceRequest_Base Tparent; +public: + // constructor + CGCClient_GetAssemblyBySequenceRequest(void); + // destructor + ~CGCClient_GetAssemblyBySequenceRequest(void); + + static string GetFilterDisplayName(int filter); + +private: + // Prohibit copy constructor and assignment operator + CGCClient_GetAssemblyBySequenceRequest(const CGCClient_GetAssemblyBySequenceRequest& value); + CGCClient_GetAssemblyBySequenceRequest& operator=(const CGCClient_GetAssemblyBySequenceRequest& value); + +}; + +/////////////////// CGCClient_GetAssemblyBySequenceRequest inline methods + +// constructor +inline +CGCClient_GetAssemblyBySequenceRequest::CGCClient_GetAssemblyBySequenceRequest(void) +{ +} + + +/////////////////// end of CGCClient_GetAssemblyBySequenceRequest inline methods + + +END_objects_SCOPE // namespace ncbi::objects:: + +END_NCBI_SCOPE + + +#endif // OBJECTS_GENOMECOLL_GCCLIENT_GETASSEMBLYBYSEQU_HPP +/* Original file checksum: lines: 86, chars: 2881, CRC32: 175ce2d7 */ diff --git a/c++/include/objects/genomecoll/GC_Assembly.hpp b/c++/include/objects/genomecoll/GC_Assembly.hpp index 00ac70b4..7066c75b 100644 --- a/c++/include/objects/genomecoll/GC_Assembly.hpp +++ b/c++/include/objects/genomecoll/GC_Assembly.hpp @@ -1,4 +1,4 @@ -/* $Id: GC_Assembly.hpp 467805 2015-05-18 12:53:53Z zherikov $ +/* $Id: GC_Assembly.hpp 504372 2016-06-14 18:01:03Z shchekot $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -79,6 +79,9 @@ public: /// Retrieve the accession for this assembly string GetAccession() const; + /// Either accession or submitter-provided id + string GetBestIdentifier() const; + /// Retrieve the full set of assembly descriptors const CGC_AssemblyDesc& GetDesc() const; @@ -159,6 +162,9 @@ private: CGC_TaggedSequences::TState relation); void x_Index(CGC_Assembly& root); + + const list< CRef< CDbtag > >& x_GetId() const; + string x_GetSubmitterId() const; }; /////////////////// CGC_Assembly inline methods diff --git a/c++/include/objects/genomecoll/cached_assembly.hpp b/c++/include/objects/genomecoll/cached_assembly.hpp index dbec4438..e6d81103 100644 --- a/c++/include/objects/genomecoll/cached_assembly.hpp +++ b/c++/include/objects/genomecoll/cached_assembly.hpp @@ -41,10 +41,14 @@ public: CCachedAssembly(const vector& blob); CRef Assembly(); + //@deprecated, Blob() will be used in the next release(SC18). This one will be removed in SC19. const string& Blob(CCompressStream::EMethod neededCompression); + //New assemblies are compressed with CCompressStream::eZip, existing returned as is. + const string& Blob(); public: static bool ValidBlob(int blobSize); + static CCompressStream::EMethod Compression(const string& blob); private: CRef m_assembly; diff --git a/c++/include/objects/genomecoll/genomic_collections_cli.hpp b/c++/include/objects/genomecoll/genomic_collections_cli.hpp index 8ce6e052..557746fe 100644 --- a/c++/include/objects/genomecoll/genomic_collections_cli.hpp +++ b/c++/include/objects/genomecoll/genomic_collections_cli.hpp @@ -1,4 +1,4 @@ -/* $Id: genomic_collections_cli.hpp 499302 2016-04-25 15:35:38Z ivanov $ +/* $Id: genomic_collections_cli.hpp 517367 2016-10-24 17:52:09Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -45,6 +45,7 @@ #include #include #include +#include #include // generated classes @@ -118,6 +119,11 @@ public: // pseudo scaffolds are reported as unlocalized/unplaced, as needed for analysis static string kScaffoldsWithAlignments() {return "ScaffoldsWithAlignments";}; + // Scaffolds + // No alignment data + // pseudo scaffolds reported as submitted. + static string kEntrezIndexing() {return "EntrezIndexing";}; + // Almost maximum contents: // all sequences down to contigs // No statistics @@ -135,22 +141,119 @@ public: string ValidateChrType(const string& chrType, const string& chrLoc); + NCBI_DEPRECATED // Use FindOneAssemblyBySequences CRef FindBestAssembly (const string& seq_id, int filter_type, int sort_type = eGCClient_FindBestAssemblySort_default); + NCBI_DEPRECATED // Use FindOneAssemblyBySequences CRef FindBestAssembly (const list& seq_id, int filter_type, int sort_type = eGCClient_FindBestAssemblySort_default); + NCBI_DEPRECATED // Use FindAssembliesBySequences CRef FindAllAssemblies (const list& seq_id, int filter_type, int sort_type = eGCClient_FindBestAssemblySort_default); + /// Find assembly by sequence accession + /// + /// @param sequence_acc + /// Sequence accession in ACC.VER format + /// @param filter + /// Bitfield, OR-ed combination of eGCClient_GetAssemblyBySequenceFilter_* values: + /// eGCClient_GetAssemblyBySequenceFilter_all - do not filter out anything + /// eGCClient_GetAssemblyBySequenceFilter_latest - look up for latest releases only + /// eGCClient_GetAssemblyBySequenceFilter_major - look up for major releases only + /// eGCClient_GetAssemblyBySequenceFilter_genbank - look up for GenBank releases only + /// eGCClient_GetAssemblyBySequenceFilter_refseq - look up for RefSeq releases only + /// If none of genbank of refseq filters are specified then both GenBank and RefSeq releases will be returned + /// @param sort + /// Assembly ordering: + /// CGCClient_GetAssemblyBySequenceRequest::eSort_default - sort by number of sequences found in assembly, then by reference/representative/other, then by modification date + /// CGCClient_GetAssemblyBySequenceRequest::eSort_latest - sort by number of sequences found in assembly, then latest first, then by reference/representative/other, then by modification date + /// CGCClient_GetAssemblyBySequenceRequest::eSort_major - sort by number of sequences found in assembly, then major first, then by reference/representative/other, then by modification date + /// @return Assembly if found, NULL otherwise. + CRef FindOneAssemblyBySequences + (const string& sequence_acc, + int filter, + CGCClient_GetAssemblyBySequenceRequest::ESort sort = CGCClient_GetAssemblyBySequenceRequest::eSort_default); + + /// Find assembly by sequence accessions + /// + /// @param sequence_acc + /// Sequence accessions in ACC.VER format + /// @param filter + /// Bitfield, OR-ed combination of eGCClient_GetAssemblyBySequenceFilter_* values: + /// eGCClient_GetAssemblyBySequenceFilter_all - do not filter out anything + /// eGCClient_GetAssemblyBySequenceFilter_latest - look up for latest releases only + /// eGCClient_GetAssemblyBySequenceFilter_major - look up for major releases only + /// eGCClient_GetAssemblyBySequenceFilter_genbank - look up for GenBank releases only + /// eGCClient_GetAssemblyBySequenceFilter_refseq - look up for RefSeq releases only + /// If none of genbank of refseq filters are specified then both GenBank and RefSeq releases will be returned + /// @param sort + /// Assembly ordering: + /// CGCClient_GetAssemblyBySequenceRequest::eSort_default - sort by number of sequences found in assembly, then by reference/representative/other, then by modification date + /// CGCClient_GetAssemblyBySequenceRequest::eSort_latest - sort by number of sequences found in assembly, then latest first, then by reference/representative/other, then by modification date + /// CGCClient_GetAssemblyBySequenceRequest::eSort_major - sort by number of sequences found in assembly, then major first, then by reference/representative/other, then by modification date + /// @return If assembly is found then return it with list of related sequences. NULL otherwise. + CRef FindOneAssemblyBySequences + (const list& sequence_acc, + int filter, + CGCClient_GetAssemblyBySequenceRequest::ESort sort = CGCClient_GetAssemblyBySequenceRequest::eSort_default); + + /// Find assemblies by sequence accession + /// + /// @param sequence_acc + /// Sequence accession in ACC.VER format + /// @param filter + /// Bitfield, OR-ed combination of eGCClient_GetAssemblyBySequenceFilter_* values: + /// eGCClient_GetAssemblyBySequenceFilter_all - do not filter out anything + /// eGCClient_GetAssemblyBySequenceFilter_latest - look up for latest releases only + /// eGCClient_GetAssemblyBySequenceFilter_major - look up for major releases only + /// eGCClient_GetAssemblyBySequenceFilter_genbank - look up for GenBank releases only + /// eGCClient_GetAssemblyBySequenceFilter_refseq - look up for RefSeq releases only + /// If none of genbank of refseq filters are specified then both GenBank and RefSeq releases will be returned + /// @param sort + /// Assembly ordering: + /// CGCClient_GetAssemblyBySequenceRequest::eSort_default - sort by number of sequences found in assembly, then by reference/representative/other, then by modification date + /// CGCClient_GetAssemblyBySequenceRequest::eSort_latest - sort by number of sequences found in assembly, then latest first, then by reference/representative/other, then by modification date + /// CGCClient_GetAssemblyBySequenceRequest::eSort_major - sort by number of sequences found in assembly, then major first, then by reference/representative/other, then by modification date + /// @return List of found assemblies with related sequences. + CRef FindAssembliesBySequences + (const string& sequence_acc, + int filter, + CGCClient_GetAssemblyBySequenceRequest::ESort sort = CGCClient_GetAssemblyBySequenceRequest::eSort_default); + + /// Find assemblies by sequence accessions + /// + /// @param sequence_acc + /// Sequence accessions in ACC.VER format + /// @param filter + /// Bitfield, OR-ed combination of eGCClient_GetAssemblyBySequenceFilter_* values: + /// eGCClient_GetAssemblyBySequenceFilter_all - do not filter out anything + /// eGCClient_GetAssemblyBySequenceFilter_latest - look up for latest releases only + /// eGCClient_GetAssemblyBySequenceFilter_major - look up for major releases only + /// eGCClient_GetAssemblyBySequenceFilter_genbank - look up for GenBank releases only + /// eGCClient_GetAssemblyBySequenceFilter_refseq - look up for RefSeq releases only + /// If none of genbank of refseq filters are specified then both GenBank and RefSeq releases will be returned + /// @param sort + /// Assembly ordering: + /// CGCClient_GetAssemblyBySequenceRequest::eSort_default - sort by number of sequences found in assembly, then by reference/representative/other, then by modification date + /// CGCClient_GetAssemblyBySequenceRequest::eSort_latest - sort by number of sequences found in assembly, then latest first, then by reference/representative/other, then by modification date + /// CGCClient_GetAssemblyBySequenceRequest::eSort_major - sort by number of sequences found in assembly, then major first, then by reference/representative/other, then by modification date + /// @return List of found assemblies with related sequences. + CRef FindAssembliesBySequences + (const list& sequence_acc, + int filter, + CGCClient_GetAssemblyBySequenceRequest::ESort sort = CGCClient_GetAssemblyBySequenceRequest::eSort_default); + + + CRef GetEquivalentAssemblies(const string& acc, int equivalency); // see CGCClient_GetEquivalentAssembliesRequest_::EEquivalency @@ -159,6 +262,7 @@ private: CGenomicCollectionsService(const CGenomicCollectionsService& value); CGenomicCollectionsService& operator=(const CGenomicCollectionsService& value); + CRef FindAssembliesBySequences(const list& sequence_acc, int filter, CGCClient_GetAssemblyBySequenceRequest::ESort sort, bool top_only); }; END_objects_SCOPE diff --git a/c++/include/objects/id2/id2processor.hpp b/c++/include/objects/id2/id2processor.hpp index fc9177ec..c01d990e 100644 --- a/c++/include/objects/id2/id2processor.hpp +++ b/c++/include/objects/id2/id2processor.hpp @@ -1,6 +1,6 @@ #ifndef OBJECTS_ID2_ID2PROCESSOR_HPP #define OBJECTS_ID2_ID2PROCESSOR_HPP -/* $Id: id2processor.hpp 486265 2015-12-02 19:22:44Z vasilche $ +/* $Id: id2processor.hpp 504899 2016-06-20 17:49:29Z vasilche $ * =========================================================================== * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information @@ -50,8 +50,12 @@ public: virtual ~CID2ProcessorResolver(void); typedef vector > TIds; + typedef vector > TReplies; virtual TIds GetIds(const CSeq_id& id) = 0; + + virtual void ProcessPacket(TReplies& replies, + CID2_Request_Packet& packet) = 0; }; diff --git a/c++/include/objects/macro/String_constraint.hpp b/c++/include/objects/macro/String_constraint.hpp index 414e0f6d..c16c7241 100644 --- a/c++/include/objects/macro/String_constraint.hpp +++ b/c++/include/objects/macro/String_constraint.hpp @@ -1,4 +1,4 @@ -/* $Id: String_constraint.hpp 494819 2016-03-10 18:53:49Z ivanov $ +/* $Id: String_constraint.hpp 494536 2016-03-08 14:06:47Z bollin $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/objects/macro/Suspect_rule.hpp b/c++/include/objects/macro/Suspect_rule.hpp index c419cbc2..5baa8ccf 100644 --- a/c++/include/objects/macro/Suspect_rule.hpp +++ b/c++/include/objects/macro/Suspect_rule.hpp @@ -1,4 +1,4 @@ -/* $Id: Suspect_rule.hpp 436428 2014-05-28 13:28:28Z chenj $ +/* $Id: Suspect_rule.hpp 514101 2016-09-19 15:56:13Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -48,9 +48,20 @@ // generated classes BEGIN_NCBI_SCOPE - BEGIN_objects_SCOPE // namespace ncbi::objects:: +// forward declarations +class CConstraint_choice; +class CConstraint_choice_set; +class CField_constraint; +class CField_type; +class CLocation_constraint; +class CLocation_pos_constraint; +class CReplace_rule; +class CSearch_func; +class CSource_constraint; +class CString_constraint; + ///////////////////////////////////////////////////////////////////////////// class CSuspect_rule : public CSuspect_rule_Base { @@ -66,10 +77,25 @@ public: bool ApplyToString(string& val) const; + string GetRuleTypeName(void) const; + string SummarizeRule(void) const; + bool IsFatal(void) const { return GetFatal() || GetRule_type() == eFix_type_remove_organism_name || GetRule_type() == eFix_type_inappropriate_symbol;} + private: // Prohibit copy constructor and assignment operator CSuspect_rule(const CSuspect_rule& value); CSuspect_rule& operator=(const CSuspect_rule& value); + + string SummarizeSearchFunc(const CSearch_func&) const; + string SummarizeReplaceRule(const CReplace_rule&) const; + string SummarizeStringConstraint(const CString_constraint&) const; + string SummarizeConstraintSet(const CConstraint_choice_set&) const; + string SummarizeConstraint(const CConstraint_choice&) const; + string SummarizeLocationConstraint(const CLocation_constraint&) const; + string SummarizeEndDistance(const CLocation_pos_constraint&) const; + string SummarizeSourceConstraint(const CSource_constraint&) const; + string SummarizeFieldConstraint(const CField_constraint&) const; + string SummarizeFieldType(const CField_type&) const; }; /////////////////// CSuspect_rule inline methods diff --git a/c++/include/objects/seq/Seq_gap.hpp b/c++/include/objects/seq/Seq_gap.hpp index de9b2dfa..86a69e27 100644 --- a/c++/include/objects/seq/Seq_gap.hpp +++ b/c++/include/objects/seq/Seq_gap.hpp @@ -1,4 +1,4 @@ -/* $Id: Seq_gap.hpp 499433 2016-04-26 14:13:30Z ivanov $ +/* $Id: Seq_gap.hpp 494120 2016-03-03 18:29:40Z gotvyans $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/objects/seq/Seq_inst.hpp b/c++/include/objects/seq/Seq_inst.hpp index 49f2191f..d10cc3e1 100644 --- a/c++/include/objects/seq/Seq_inst.hpp +++ b/c++/include/objects/seq/Seq_inst.hpp @@ -1,4 +1,4 @@ -/* $Id: Seq_inst.hpp 488736 2016-01-05 15:02:56Z choi $ +/* $Id: Seq_inst.hpp 518949 2016-11-09 16:44:19Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -66,6 +66,8 @@ public: // translate EMol to string static string GetMoleculeClass(EMol mol); + bool ConvertDeltaToRaw(); + private: // Prohibit copy constructor and assignment operator CSeq_inst(const CSeq_inst& value); diff --git a/c++/include/objects/seq/Seq_literal.hpp b/c++/include/objects/seq/Seq_literal.hpp index 7df80f8c..8eee459e 100644 --- a/c++/include/objects/seq/Seq_literal.hpp +++ b/c++/include/objects/seq/Seq_literal.hpp @@ -1,4 +1,4 @@ -/* $Id: Seq_literal.hpp 429786 2014-03-19 15:22:12Z mozese2 $ +/* $Id: Seq_literal.hpp 497282 2016-04-05 18:01:48Z kiryutin $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -62,7 +62,10 @@ public: enum EBridgeableStatus { e_NotAGap, e_Bridgeable, e_NotBridgeable, e_MaybeBridgeable }; - EBridgeableStatus IsBridgeable() const; + EBridgeableStatus GetBridgeability() const; + + // change the method name to GetBridgeability to make it clear + NCBI_DEPRECATED EBridgeableStatus IsBridgeable() const { return GetBridgeability(); } private: // Prohibit copy constructor and assignment operator diff --git a/c++/include/objects/seq/seq_loc_mapper_base.hpp b/c++/include/objects/seq/seq_loc_mapper_base.hpp index 058f4c38..73c0be7d 100644 --- a/c++/include/objects/seq/seq_loc_mapper_base.hpp +++ b/c++/include/objects/seq/seq_loc_mapper_base.hpp @@ -1,7 +1,7 @@ #ifndef SEQ_LOC_MAPPER_BASE__HPP #define SEQ_LOC_MAPPER_BASE__HPP -/* $Id: seq_loc_mapper_base.hpp 493266 2016-02-25 16:13:50Z ivanov $ +/* $Id: seq_loc_mapper_base.hpp 505917 2016-06-29 20:22:14Z grichenk $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -82,9 +82,8 @@ public: ENa_strand dst_strand, bool ext_to = false, int frame = 0, - TSeqPos dst_total_len = kInvalidSeqPos, TSeqPos src_bioseq_len = kInvalidSeqPos, - TSeqPos dst_len = kInvalidSeqPos ); + TSeqPos dst_len = kInvalidSeqPos); /// Check if the id is on the source sequence. bool GoodSrcId(const CSeq_id& id) const; @@ -145,9 +144,6 @@ private: bool m_ExtTo; // Holds the frame shift (0 if none) of the underlying CDS (if any). int m_Frame; - // Holds the complete length of the destination. This is needed - // to detect whether or not fuzzy edges should be extended to the end. - TSeqPos m_Dst_total_len; // This holds the complete length of the original source bioseq. // Needed to detect whether or not fuzzy edges should be extended to the end. TSeqPos m_Src_bioseq_len; @@ -276,6 +272,65 @@ private: }; +///////////////////////////////////////////////////////////////////////////// +/// +/// CSeq_loc_Mapper_Options -- +/// +/// Options passed to CSeq_loc_Mapper[_Base] constructor. +/// + +class NCBI_SEQ_EXPORT CSeq_loc_Mapper_Options +{ +public: + typedef int TMapOptions; + + CSeq_loc_Mapper_Options(void); + CSeq_loc_Mapper_Options(IMapper_Sequence_Info* seq_info, + TMapOptions opts = 0); + CSeq_loc_Mapper_Options(TMapOptions opts); + + /// Sequence type, length etc. provider. If any ids from the mapping + /// ranges are not available through this object, they should be + /// registered using CSeq_loc_Mapper_Base::SetSeqTypeById(). + IMapper_Sequence_Info* GetMapperSequenceInfo(void) const; + CSeq_loc_Mapper_Options& SetMapperSequenceInfo(IMapper_Sequence_Info* seq_info); + + /// Dense-seg mapping option. + /// @sa CSeq_loc_Mapper_Base::fAlign_Dense_seg_TotalRange + bool GetAlign_Dense_seg_TotalRange(void) const; + CSeq_loc_Mapper_Options& SetAlign_Dense_seg_TotalRange(bool value = true); + + /// Mapping direction when mapping through a sparse-seg. + /// @sa CSeq_loc_Mapper_Base::fAlign_Sparse_ToFirst + /// @sa CSeq_loc_Mapper_Base::fAlign_Sparse_ToSecond + bool GetAlign_Sparse_ToFirst(void) const; + bool GetAlign_Sparse_ToSecond(void) const; + CSeq_loc_Mapper_Options& SetAlign_Sparse_ToFirst(bool value = true); + CSeq_loc_Mapper_Options& SetAlign_Sparse_ToSecond(bool value = true); + + /// Mapping depth when using a seq-map, a bioseq or a GC-assembly. + /// @sa CSeq_loc_Mapper_Base::fMapSingleLevel + bool GetMapSingleLevel(void) const; + CSeq_loc_Mapper_Options& SetMapSingleLevel(bool value = true); + + /// Mapped location trimming at sequence end. Off by default. + /// @sa CSeq_loc_Mapper_Base::fTrimMappedLocation + bool GetTrimMappedLocation(void) const; + CSeq_loc_Mapper_Options& SetTrimMappedLocation(bool value = true); + +private: + friend class CSeq_loc_Mapper_Base; + + IMapper_Sequence_Info& GetSeqInfo(void) const; + + bool x_IsSetOption(int opt) const; + void x_SetOption(int opt, bool enable); + + mutable CRef m_SeqInfo; + TMapOptions m_Options; +}; + + ///////////////////////////////////////////////////////////////////////////// /// /// CSeq_loc_Mapper_Base -- @@ -296,12 +351,12 @@ public: enum EMapOptions { /// Ignore internal dense-seg structure - map each /// dense-seg according to the total ranges involved - fAlign_Dense_seg_TotalRange = 0x01, + fAlign_Dense_seg_TotalRange = 1 << 0, /// Flags used to indicate mapping direction when mapping /// through a sparse-seg. - fAlign_Sparse_ToFirst = 0x00, ///< Map to first-id - fAlign_Sparse_ToSecond = 0x02, ///< Map to second-id + fAlign_Sparse_ToFirst = 0, ///< Map to first-id + fAlign_Sparse_ToSecond = 1 << 1, ///< Map to second-id /// Flag used when mapping through a seq-map (this includes /// mapping through a bioseq or a GC-assembly). If set, each @@ -309,7 +364,12 @@ public: /// mode which maps from any level as far up/down as possible. /// The result of mapping can be mapped further by making another /// call to Map(). - fMapSingleLevel = 0x04 + fMapSingleLevel = 1 << 2, + + /// Enable trimming of source/destination ranges at sequence end. + /// By default locations can stretch beyond sequence end. With trimming + /// enabled the mapper will truncate ranges to fit sequence lengths. + fTrimMappedLocation = 1 << 3 }; typedef int TMapOptions; @@ -337,40 +397,48 @@ public: /// NOTE: If the mapper is used with mixed sequence types, the /// ranges must use genomic coordinates (for ranges on proteins /// multiply all coordinates by 3). - /// @param seq_info - /// Sequence type, length etc. provider. If any ids from the mapping - /// ranges are not available through this object, they must be - /// registered using SetSeqTypeById. - /// @sa IMapper_Sequence_Info - /// @sa SetSeqTypeById - CSeq_loc_Mapper_Base(CMappingRanges* mapping_ranges, - IMapper_Sequence_Info* seq_info = 0); + /// @param options + /// Mapping options which need to be set during mapper initialization. + /// @sa CSeq_loc_Mapper_Options + CSeq_loc_Mapper_Base(CMappingRanges* mapping_ranges, + CSeq_loc_Mapper_Options options = CSeq_loc_Mapper_Options()); /// Mapping through a feature, both location and product must be set. - CSeq_loc_Mapper_Base(const CSeq_feat& map_feat, - EFeatMapDirection dir, - IMapper_Sequence_Info* seq_info = 0); + CSeq_loc_Mapper_Base(const CSeq_feat& map_feat, + EFeatMapDirection dir, + CSeq_loc_Mapper_Options options = CSeq_loc_Mapper_Options()); /// Mapping between two seq_locs. - CSeq_loc_Mapper_Base(const CSeq_loc& source, - const CSeq_loc& target, - IMapper_Sequence_Info* seq_info = 0); + CSeq_loc_Mapper_Base(const CSeq_loc& source, + const CSeq_loc& target, + CSeq_loc_Mapper_Options options = CSeq_loc_Mapper_Options()); /// Mapping through an alignment. Need to specify target ID or /// target row of the alignment. Any other ID is mapped to the /// target one. Only the first row matching target ID is used, /// all other rows are considered source. + CSeq_loc_Mapper_Base(const CSeq_align& map_align, + const CSeq_id& to_id, + CSeq_loc_Mapper_Options options = CSeq_loc_Mapper_Options()); + /// @deprecated Use the version with CSeq_loc_Mapper_Options instead. + NCBI_DEPRECATED CSeq_loc_Mapper_Base(const CSeq_align& map_align, const CSeq_id& to_id, - TMapOptions opts = 0, - IMapper_Sequence_Info* seq_info = 0); + TMapOptions opts, + IMapper_Sequence_Info* seq_info); + /// Sparse alignments require special row indexing since each /// row contains two seq-ids. Use options to specify mapping /// direction. + CSeq_loc_Mapper_Base(const CSeq_align& map_align, + size_t to_row, + CSeq_loc_Mapper_Options options = CSeq_loc_Mapper_Options()); + /// @deprecated Use the version with CSeq_loc_Mapper_Options instead. + NCBI_DEPRECATED CSeq_loc_Mapper_Base(const CSeq_align& map_align, size_t to_row, - TMapOptions opts = 0, - IMapper_Sequence_Info* seq_info = 0); + TMapOptions opts, + IMapper_Sequence_Info* seq_info); ~CSeq_loc_Mapper_Base(void); @@ -568,7 +636,6 @@ protected: const CInt_fuzz* fuzz_from = 0, const CInt_fuzz* fuzz_to = 0, int frame = 0, - TSeqPos dst_total_len = kInvalidSeqPos, TSeqPos src_bioseq_len = kInvalidSeqPos); // Add new CMappingRange. This includes collecting all synonyms for the id, @@ -583,7 +650,6 @@ protected: TSeqPos length, bool ext_right, int frame, - TSeqPos dst_total_len, TSeqPos src_bioseq_len, TSeqPos dst_length ); @@ -882,14 +948,11 @@ protected: // Control how fuzz is generated and propagated TFuzzOption m_FuzzOption; // Misc mapping options - TMapOptions m_MapOptions; - - // Sequence info provider - mutable CRef m_SeqInfo; + CSeq_loc_Mapper_Options m_MapOptions; public: // Initialize the mapper with default values - CSeq_loc_Mapper_Base(IMapper_Sequence_Info* seqinfo = 0); + CSeq_loc_Mapper_Base(CSeq_loc_Mapper_Options options = CSeq_loc_Mapper_Options()); /// Methods for getting sequence types, use cached types (m_SeqTypes) /// if possible. @@ -1249,6 +1312,122 @@ int CSeq_loc_Mapper_Base::GetWidthById(const CSeq_id& id) const } +inline +CSeq_loc_Mapper_Options::CSeq_loc_Mapper_Options(void) + : m_SeqInfo(0), m_Options(0) {} + +inline +CSeq_loc_Mapper_Options::CSeq_loc_Mapper_Options(IMapper_Sequence_Info* seq_info, + TMapOptions opts) + : m_SeqInfo(seq_info), m_Options(opts) {} + +inline +CSeq_loc_Mapper_Options::CSeq_loc_Mapper_Options(TMapOptions opts) + : m_SeqInfo(0), m_Options(opts) {} + +inline +IMapper_Sequence_Info* +CSeq_loc_Mapper_Options::GetMapperSequenceInfo(void) const +{ + return m_SeqInfo; +} + +inline +CSeq_loc_Mapper_Options& +CSeq_loc_Mapper_Options::SetMapperSequenceInfo(IMapper_Sequence_Info* seq_info) +{ + m_SeqInfo = seq_info; + return *this; +} + +inline +bool CSeq_loc_Mapper_Options::GetAlign_Dense_seg_TotalRange(void) const +{ + return x_IsSetOption(CSeq_loc_Mapper_Base::fAlign_Dense_seg_TotalRange); +} + +inline +CSeq_loc_Mapper_Options& +CSeq_loc_Mapper_Options::SetAlign_Dense_seg_TotalRange(bool value) +{ + x_SetOption(CSeq_loc_Mapper_Base::fAlign_Dense_seg_TotalRange, value); + return *this; +} + +inline +bool CSeq_loc_Mapper_Options::GetAlign_Sparse_ToFirst(void) const +{ + return !x_IsSetOption(CSeq_loc_Mapper_Base::fAlign_Sparse_ToSecond); +} + +inline +bool CSeq_loc_Mapper_Options::GetAlign_Sparse_ToSecond(void) const +{ + return x_IsSetOption(CSeq_loc_Mapper_Base::fAlign_Sparse_ToSecond); +} + +inline +CSeq_loc_Mapper_Options& +CSeq_loc_Mapper_Options::SetAlign_Sparse_ToFirst(bool value) +{ + x_SetOption(CSeq_loc_Mapper_Base::fAlign_Sparse_ToSecond, !value); + return *this; +} + +inline +CSeq_loc_Mapper_Options& +CSeq_loc_Mapper_Options::SetAlign_Sparse_ToSecond(bool value) +{ + x_SetOption(CSeq_loc_Mapper_Base::fAlign_Sparse_ToSecond, value); + return *this; +} + +inline +bool CSeq_loc_Mapper_Options::GetMapSingleLevel(void) const +{ + return x_IsSetOption(CSeq_loc_Mapper_Base::fMapSingleLevel); +} + +inline +CSeq_loc_Mapper_Options& +CSeq_loc_Mapper_Options::SetMapSingleLevel(bool value) +{ + x_SetOption(CSeq_loc_Mapper_Base::fMapSingleLevel, value); + return *this; +} + +inline +bool CSeq_loc_Mapper_Options::GetTrimMappedLocation(void) const +{ + return x_IsSetOption(CSeq_loc_Mapper_Base::fTrimMappedLocation); +} + +inline +CSeq_loc_Mapper_Options& +CSeq_loc_Mapper_Options::SetTrimMappedLocation(bool value) +{ + x_SetOption(CSeq_loc_Mapper_Base::fTrimMappedLocation, value); + return *this; +} + +inline +bool CSeq_loc_Mapper_Options::x_IsSetOption(int opt) const +{ + return (m_Options & opt) != 0; +} + +inline +void CSeq_loc_Mapper_Options::x_SetOption(int opt, bool enable) +{ + if ( enable ) { + m_Options |= opt; + } + else { + m_Options &= ~opt; + } +} + + /* @} */ diff --git a/c++/include/objects/seq/sofa_map.hpp b/c++/include/objects/seq/sofa_map.hpp index 1dbb5d22..08c75172 100644 --- a/c++/include/objects/seq/sofa_map.hpp +++ b/c++/include/objects/seq/sofa_map.hpp @@ -1,4 +1,4 @@ -/* $Id: sofa_map.hpp 496057 2016-03-23 15:31:16Z ivanov $ +/* $Id: sofa_map.hpp 493092 2016-02-24 12:36:34Z ludwigf $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/objects/seqfeat/BioSource.hpp b/c++/include/objects/seqfeat/BioSource.hpp index f283d156..4812637c 100644 --- a/c++/include/objects/seqfeat/BioSource.hpp +++ b/c++/include/objects/seqfeat/BioSource.hpp @@ -1,4 +1,4 @@ -/* $Id: BioSource.hpp 488225 2015-12-28 20:52:28Z kans $ +/* $Id: BioSource.hpp 512289 2016-08-29 18:14:36Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -40,6 +40,7 @@ // generated includes #include +#include // generated classes @@ -49,6 +50,7 @@ BEGIN_objects_SCOPE // namespace ncbi::objects:: class COrgName; class CFieldDiff; +class CSubSource; typedef vector< CRef > TFieldDiffList; @@ -135,6 +137,40 @@ public: bool RemoveSubSource(int subtype); bool RemoveOrgMod(int subtype); + //If taxname starts with uncultured, set environmental-sample to true + //If metagenomic, set environmental_sample + // Add environmental_sample to BioSource if BioSource.org.orgname.div == "ENV" + // Add metagenomic(and environmental_sample) if BioSource.org.orgname.lineage contains "metagenomes" + // Add metagenomic(and environmental_sample) if BioSource has / metagenome_source qualifier + // returns true if change was made + bool FixEnvironmentalSample(); + + // Remove null terms from SubSource values and OrgMod values + bool RemoveNullTerms(); + + // do not allow sex qualifier if virus, bacteria, Archaea, or fungus + static bool AllowSexQualifier(const string& lineage); + bool AllowSexQualifier() const; + + // do not allow mating_type qualifier if animal, plant, or virus + static bool AllowMatingTypeQualifier(const string& lineage); + bool AllowMatingTypeQualifier() const; + + //Remove /sex qualifier from virus, bacteria, archaea, fungus organisms + //Remove /mating_type qualifier from animal, plant, and virus organisms + //Move /mating_type qualifier that is valid /sex qualifier word to /sex qualifier + bool FixSexMatingTypeInconsistencies(); + + //Remove qualifiers not appropriate for virus organisms from Virus organisms + bool RemoveUnexpectedViralQualifiers(); + + bool FixGenomeForQualifiers(); + + static bool IsViral(const string& lineage); + bool IsViral() const; + + bool HasSubtype(CSubSource::TSubtype subtype) const; + CRef MakeCommon( const CBioSource& other) const; private: diff --git a/c++/include/objects/seqfeat/Delta_item.hpp b/c++/include/objects/seqfeat/Delta_item.hpp new file mode 100644 index 00000000..d9ff406e --- /dev/null +++ b/c++/include/objects/seqfeat/Delta_item.hpp @@ -0,0 +1,94 @@ +/* $Id: Delta_item.hpp 492313 2016-02-16 18:52:15Z foleyjp $ + * =========================================================================== + * + * PUBLIC DOMAIN NOTICE + * National Center for Biotechnology Information + * + * This software/database is a "United States Government Work" under the + * terms of the United States Copyright Act. It was written as part of + * the author's official duties as a United States Government employee and + * thus cannot be copyrighted. This software/database is freely available + * to the public for use. The National Library of Medicine and the U.S. + * Government have not placed any restriction on its use or reproduction. + * + * Although all reasonable efforts have been taken to ensure the accuracy + * and reliability of the software and data, the NLM and the U.S. + * Government do not and cannot warrant the performance or results that + * may be obtained by using this software or data. The NLM and the U.S. + * Government disclaim all warranties, express or implied, including + * warranties of performance, merchantability or fitness for any particular + * purpose. + * + * Please cite the author in any work or product based on this material. + * + * =========================================================================== + * + */ + +/// @file Delta_item.hpp +/// User-defined methods of the data storage class. +/// +/// This file was originally generated by application DATATOOL +/// using the following specifications: +/// 'seqfeat.asn'. +/// +/// New methods or data members can be added to it if needed. +/// See also: Delta_item_.hpp + + +#ifndef OBJECTS_SEQFEAT_DELTA_ITEM_HPP +#define OBJECTS_SEQFEAT_DELTA_ITEM_HPP + + +#include + +// generated includes +#include + +// generated classes + +BEGIN_NCBI_SCOPE + +BEGIN_objects_SCOPE // namespace ncbi::objects:: + +///////////////////////////////////////////////////////////////////////////// +class NCBI_SEQFEAT_EXPORT CDelta_item : public CDelta_item_Base +{ + typedef CDelta_item_Base Tparent; +public: + // constructor + CDelta_item(void); + // destructor + ~CDelta_item(void); + + void SetDeletion(void); + void SetDuplication(void); + void SetInsertion(const CIUPACna& sequence, + TSeqPos seq_length=0); + +private: + // Prohibit copy constructor and assignment operator + CDelta_item(const CDelta_item& value); + CDelta_item& operator=(const CDelta_item& value); + +}; + +/////////////////// CDelta_item inline methods + +// constructor +inline +CDelta_item::CDelta_item(void) +{ +} + + +/////////////////// end of CDelta_item inline methods + + +END_objects_SCOPE // namespace ncbi::objects:: + +END_NCBI_SCOPE + + +#endif // OBJECTS_SEQFEAT_DELTA_ITEM_HPP +/* Original file checksum: lines: 86, chars: 2435, CRC32: be4d21ba */ diff --git a/c++/include/objects/seqfeat/Gb_qual.hpp b/c++/include/objects/seqfeat/Gb_qual.hpp index db820dc8..fb5710a7 100644 --- a/c++/include/objects/seqfeat/Gb_qual.hpp +++ b/c++/include/objects/seqfeat/Gb_qual.hpp @@ -1,4 +1,4 @@ -/* $Id: Gb_qual.hpp 493884 2016-03-02 14:18:51Z ivanov $ +/* $Id: Gb_qual.hpp 514391 2016-09-21 15:38:23Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -87,6 +87,10 @@ public: static const TLegalPseudogeneSet &GetSetOfLegalPseudogenes(void); static bool IsValidPseudogeneValue(const string& val); + // for misc_recomb qualifiers + typedef CStaticArraySet TLegalRecombinationClassSet; + static const TLegalRecombinationClassSet &GetSetOfLegalRecombinationClassValues(void); + static bool IsLegalMobileElementValue(const string& val); static void GetMobileElementValueElements(const string& val, string& element_type, string& element_name); diff --git a/c++/include/objects/seqfeat/OrgMod.hpp b/c++/include/objects/seqfeat/OrgMod.hpp index db6460f1..716a84bb 100644 --- a/c++/include/objects/seqfeat/OrgMod.hpp +++ b/c++/include/objects/seqfeat/OrgMod.hpp @@ -1,4 +1,4 @@ -/* $Id: OrgMod.hpp 462584 2015-03-19 16:38:52Z kachalos $ +/* $Id: OrgMod.hpp 515540 2016-10-03 16:03:50Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -77,7 +77,7 @@ public: static bool IsValidSubtypeName(const string& str, EVocabulary vocabulary = eVocabulary_raw); - static bool IsDiscouraged(const TSubtype stype); + static bool IsDiscouraged(const TSubtype stype, bool indexer=false); static bool IsMultipleValuesAllowed(TSubtype); /// This indicates if the given Org-mod subtype is supposed to hold an @@ -102,6 +102,7 @@ public: static string FixStrain( const string& strain); static bool FuzzyStrainMatch( const string& strain1, const string& strain2 ); + static bool IsStrainValid(const string& strain); static string FixHost(const string& value); static string FixHostCapitalization(const string& value); @@ -111,6 +112,14 @@ public: static string AutoFix(TSubtype subtype, const string& value); void AutoFix(); + // Remove "subsp. " and "serovar " from start of strain + // Remove "subsp. " and "serovar " from start of serovar + // Remove "subsp. " from start of sub-species qualifier + bool RemoveAbbreviation(); + + static bool IsUnexpectedViralOrgModQualifier(TSubtype subtype); + bool IsUnexpectedViralOrgModQualifier() const; + private: // Prohibit copy constructor and assignment operator COrgMod(const COrgMod& value); diff --git a/c++/include/objects/seqfeat/SeqFeatData.hpp b/c++/include/objects/seqfeat/SeqFeatData.hpp index ce4ff5d7..96c85f93 100644 --- a/c++/include/objects/seqfeat/SeqFeatData.hpp +++ b/c++/include/objects/seqfeat/SeqFeatData.hpp @@ -1,4 +1,4 @@ -/* $Id: SeqFeatData.hpp 477822 2015-09-02 12:03:07Z bollin $ +/* $Id: SeqFeatData.hpp 514392 2016-09-21 15:38:46Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -230,7 +230,8 @@ public: eSubtype_telomere = 101, eSubtype_assembly_gap = 102, eSubtype_regulatory = 103, - eSubtype_max = 104, + eSubtype_propeptide = 104, // Prot-ref propeptide + eSubtype_max = 105, eSubtype_any = 255 }; ESubtype GetSubtype(void) const; @@ -410,6 +411,7 @@ public: eQual_pseudo, eQual_pseudogene, eQual_rearranged, + eQual_recombination_class, eQual_region_name, eQual_regulatory_class, eQual_replace, @@ -483,6 +485,7 @@ public: static bool IsRegulatory(ESubtype subtype); static const string & GetRegulatoryClass(ESubtype subtype); static ESubtype GetRegulatoryClass(const string & class_name ); + static vector GetRegulatoryClassList(); static bool IsDiscouragedSubtype(ESubtype subtype); static bool IsDiscouragedQual(EQualifier qual); @@ -503,6 +506,11 @@ public: static bool ShouldRepresentAsGbqual (CSeqFeatData::ESubtype feat_subtype, const CGb_qual& qual); static bool ShouldRepresentAsGbqual (CSeqFeatData::ESubtype feat_subtype, CSeqFeatData::EQualifier qual_type); + static void s_InitXrefAllowedSubtypesTable(void); + static void s_InitXrefProhibitedSubtypesTable(void); + static bool AllowXref(CSeqFeatData::ESubtype subtype1, CSeqFeatData::ESubtype subtype2); + static bool ProhibitXref(CSeqFeatData::ESubtype subtype1, CSeqFeatData::ESubtype subtype2); + // Internal structure to hold additional info struct SFeatDataInfo { diff --git a/c++/include/objects/seqfeat/Seq_feat.hpp b/c++/include/objects/seqfeat/Seq_feat.hpp index 7e28ec5a..1b27e25f 100644 --- a/c++/include/objects/seqfeat/Seq_feat.hpp +++ b/c++/include/objects/seqfeat/Seq_feat.hpp @@ -1,4 +1,4 @@ -/* $Id: Seq_feat.hpp 490392 2016-01-25 17:20:58Z bollin $ +/* $Id: Seq_feat.hpp 518385 2016-11-02 17:27:05Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -45,6 +45,7 @@ #include #include #include +#include // generated classes @@ -78,6 +79,9 @@ public: void SetProtXref(CProt_ref& value); CProt_ref& SetProtXref(void); + bool HasSeqFeatXref(const CSeqFeatXref::TId& id) const; + bool AddSeqFeatXref(const CSeqFeatXref::TId& id); + /// Add a qualifier to this feature void AddQualifier(const string& qual_name, const string& qual_val); diff --git a/c++/include/objects/seqfeat/SubSource.hpp b/c++/include/objects/seqfeat/SubSource.hpp index 400dc716..3a3ce221 100644 --- a/c++/include/objects/seqfeat/SubSource.hpp +++ b/c++/include/objects/seqfeat/SubSource.hpp @@ -1,4 +1,4 @@ -/* $Id: SubSource.hpp 493853 2016-03-02 14:07:56Z ivanov $ +/* $Id: SubSource.hpp 502999 2016-05-31 15:35:13Z bollin $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -208,6 +208,7 @@ public: static string AutoFix(TSubtype subtype, const string& value); void AutoFix(); + static bool HasCultureNotes(const string& value); static void RemoveCultureNotes(string& value, bool is_species_level = true); void RemoveCultureNotes(bool is_species_level = true); diff --git a/c++/include/objects/seqfeat/Trna_ext.hpp b/c++/include/objects/seqfeat/Trna_ext.hpp index 3bd2dc0c..b206bb50 100644 --- a/c++/include/objects/seqfeat/Trna_ext.hpp +++ b/c++/include/objects/seqfeat/Trna_ext.hpp @@ -1,4 +1,4 @@ -/* $Id: Trna_ext.hpp 500111 2016-05-02 15:51:42Z ivanov $ +/* $Id: Trna_ext.hpp 499339 2016-04-25 18:08:43Z bollin $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/objects/seqfeat/Variation_ref.hpp b/c++/include/objects/seqfeat/Variation_ref.hpp index 877a2424..8d0f673e 100644 --- a/c++/include/objects/seqfeat/Variation_ref.hpp +++ b/c++/include/objects/seqfeat/Variation_ref.hpp @@ -1,4 +1,4 @@ -/* $Id: Variation_ref.hpp 341186 2011-10-17 21:23:07Z dicuccio $ +/* $Id: Variation_ref.hpp 492328 2016-02-16 19:46:22Z foleyjp $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -39,6 +39,9 @@ #ifndef OBJECTS_SEQFEAT_VARIATION_REF_HPP #define OBJECTS_SEQFEAT_VARIATION_REF_HPP +#include +#include +#include // generated includes #include @@ -68,6 +71,23 @@ public: /// PostRead() hooks to establish correct, non-deprecated data layout void PostRead(); + + void SetSNV(const CSeq_data& nucleotide, + CRef offset=null); + + void SetMNP(const CSeq_data& nucleotide, + TSeqPos length, + CRef offset=null); + + void SetMissense(const CSeq_data& amino_acid); + + void SetDuplication(CRef start_offset=null, + CRef stop_offset=null); + + void SetIdentity(CRef seq_literal, + CRef start_offset=null, + CRef stop_offset=null); + /// Set a standard single nucleotide variant. The replaces set can include /// empty strings and/or '-' as a character to indicate a deletion. void SetSNV(const vector& replaces, diff --git a/c++/include/objects/seqloc/Seq_loc.hpp b/c++/include/objects/seqloc/Seq_loc.hpp index 2e713811..b8c7d3e1 100644 --- a/c++/include/objects/seqloc/Seq_loc.hpp +++ b/c++/include/objects/seqloc/Seq_loc.hpp @@ -1,4 +1,4 @@ -/* $Id: Seq_loc.hpp 496694 2016-03-30 14:14:36Z ivanov $ +/* $Id: Seq_loc.hpp 495960 2016-03-22 19:19:34Z grichenk $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -113,7 +113,7 @@ public: // destructor virtual ~CSeq_loc(void); - /// See related functions in util/sequence.hpp: + /// See related functions in objmgr/util/seq_loc_util.hpp: /// /// TSeqPos GetLength(const CSeq_loc&, CScope*) /// bool IsOneBioseq(const CSeq_loc&, CScope*) @@ -127,7 +127,7 @@ public: TRange GetTotalRange(void) const; void InvalidateTotalRangeCache(void) const; - + /// Check if strand is set for any/all part(s) of the seq-loc /// depending on the flag. bool IsSetStrand(EIsSetStrand flag = eIsSetStrand_Any) const; @@ -259,7 +259,7 @@ public: /// Minus strand locations' order is reversed. /// Seq-ids are not checked in this method, unless you set /// filter, which will allow the user to pick which parts to skip. - int CompareSubLoc(const CSeq_loc& loc, ENa_strand strand, + int CompareSubLoc(const CSeq_loc& loc, ENa_strand strand, const ISubLocFilter *filter = NULL) const; /// Simple adding of seq-locs. @@ -530,7 +530,7 @@ public: /// or GetEmbeddingSeq_loc instead. NCBI_DEPRECATED const CSeq_loc& GetSeq_loc(void) const; - // Return null if non-fuzzy + // Return null if non-fuzzy const CInt_fuzz* GetFuzzFrom(void) const; const CInt_fuzz* GetFuzzTo (void) const; @@ -765,7 +765,7 @@ public: /// C. the insertion point is in the middle of existing part /// then the existing part will be split at the insertion point /// and new element will be added to the second part after splitting. - /// + /// /// The mode will switch to eEquiv_append after the insertion. eEquiv_new_part, @@ -868,14 +868,14 @@ void CSeq_loc::InvalidateTotalRangeCache(void) const } -inline +inline void CSeq_loc::InvalidateIdCache(void) const { m_IdCache = NULL; } -inline +inline void CSeq_loc::InvalidateCache(void) const { InvalidateTotalRangeCache(); @@ -976,7 +976,7 @@ DEFINE_NCBI_SEQ_LOC_SETTERS(Feat) inline bool CSeq_loc::IsReverseStrand(void) const { - return IsReverse(GetStrand()); + return IsReverse(GetStrand()); } diff --git a/c++/include/objects/seqset/Bioseq_set.hpp b/c++/include/objects/seqset/Bioseq_set.hpp index 867f6669..c866e614 100644 --- a/c++/include/objects/seqset/Bioseq_set.hpp +++ b/c++/include/objects/seqset/Bioseq_set.hpp @@ -1,4 +1,4 @@ -/* $Id: Bioseq_set.hpp 132506 2008-06-30 18:09:32Z kans $ +/* $Id: Bioseq_set.hpp 519216 2016-11-14 16:06:08Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -86,6 +86,9 @@ public: const CBioseq& GetGenomicFromGenProdSet(void) const; const CBioseq& GetMasterFromSegSet(void) const; + bool NeedsDocsumTitle() const; + static bool NeedsDocsumTitle(EClass set_class); + private: // Prohibit copy constructor & assignment operator CBioseq_set(const CBioseq_set&); diff --git a/c++/include/objects/taxon1/Taxon2_data.hpp b/c++/include/objects/taxon1/Taxon2_data.hpp index 465a50d3..b08e8af5 100644 --- a/c++/include/objects/taxon1/Taxon2_data.hpp +++ b/c++/include/objects/taxon1/Taxon2_data.hpp @@ -1,4 +1,4 @@ -/* $Id: Taxon2_data.hpp 454834 2014-12-18 16:56:57Z domrach $ +/* $Id: Taxon2_data.hpp 494538 2016-03-08 14:31:04Z bollin $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/objects/taxon1/taxon1.hpp b/c++/include/objects/taxon1/taxon1.hpp index 03f9358a..d985b613 100644 --- a/c++/include/objects/taxon1/taxon1.hpp +++ b/c++/include/objects/taxon1/taxon1.hpp @@ -1,7 +1,7 @@ #ifndef NCBI_TAXON1_HPP #define NCBI_TAXON1_HPP -/* $Id: taxon1.hpp 488663 2016-01-04 18:15:48Z domrach $ +/* $Id: taxon1.hpp 497983 2016-04-12 17:06:15Z domrach $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -607,6 +607,11 @@ public: // false otherwise virtual bool IsRoot() const = 0; + //------------------------------------------------- + // Returns: true if node is hidden in the GenBank lineage, + // false otherwise + virtual bool IsGenBankHidden() const = 0; + }; //------------------------------------------------- diff --git a/c++/include/objects/trackmgr/TMgr_ClientInfo.hpp b/c++/include/objects/trackmgr/TMgr_ClientInfo.hpp index afe0b0fa..5d0c88a1 100644 --- a/c++/include/objects/trackmgr/TMgr_ClientInfo.hpp +++ b/c++/include/objects/trackmgr/TMgr_ClientInfo.hpp @@ -1,4 +1,4 @@ -/* $Id: TMgr_ClientInfo.hpp 441154 2014-07-21 19:21:04Z clausen $ +/* $Id: TMgr_ClientInfo.hpp 494538 2016-03-08 14:31:04Z bollin $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/objects/trackmgr/TMgr_DTrackId.hpp b/c++/include/objects/trackmgr/TMgr_DTrackId.hpp index 89505e6b..27b29023 100755 --- a/c++/include/objects/trackmgr/TMgr_DTrackId.hpp +++ b/c++/include/objects/trackmgr/TMgr_DTrackId.hpp @@ -1,4 +1,4 @@ -/* $Id: TMgr_DTrackId.hpp 414270 2013-09-23 13:00:48Z meric $ +/* $Id: TMgr_DTrackId.hpp 498695 2016-04-19 04:42:31Z meric $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -51,14 +51,17 @@ BEGIN_objects_SCOPE // namespace ncbi::objects:: class NCBI_TRACKMGR_EXPORT CTMgr_DTrackId : public CTMgr_DTrackId_Base { typedef CTMgr_DTrackId_Base Tparent; + public: - CTMgr_DTrackId(void) {} + CTMgr_DTrackId(void) + { + } - static CRef FromTrackIdString(const string& track_id) + static CRef FromTrackIdString(const string& track_id, const string& db = "TMS") { - CRef id(new CTMgr_DTrackId()); + auto id = Ref(new CTMgr_DTrackId()); CDbtag& tag = id->Set(); - tag.SetDb("TMS"); + tag.SetDb(db); tag.SetTag().SetStr(track_id); return id; } diff --git a/c++/include/objects/trackmgr/displaytrack_client.hpp b/c++/include/objects/trackmgr/displaytrack_client.hpp index 82c04d37..ba092f16 100644 --- a/c++/include/objects/trackmgr/displaytrack_client.hpp +++ b/c++/include/objects/trackmgr/displaytrack_client.hpp @@ -1,7 +1,7 @@ #ifndef OBJECTS_TRACKMGR_GRIDCLI__DISPLAY_TRACK_CLIENT_HPP #define OBJECTS_TRACKMGR_GRIDCLI__DISPLAY_TRACK_CLIENT_HPP -/* $Id: displaytrack_client.hpp 488465 2015-12-30 23:55:06Z meric $ +/* $Id: displaytrack_client.hpp 506052 2016-06-30 21:39:40Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -36,6 +36,8 @@ /// NetSchedule grid client for TrackManager display-track request/reply #include +#include +#include BEGIN_NCBI_SCOPE @@ -49,13 +51,23 @@ END_SCOPE(objects) class CTMS_DisplayTrack_Client : private CGridRPCBaseClient { private: - typedef CGridRPCBaseClient TBaseClient; + using TBaseClient = CGridRPCBaseClient; + + struct HttpService + { + explicit HttpService(const string& svc) + : service(svc) + { + } + string service; + }; + public: - typedef objects::CTMgr_DisplayTrackRequest TRequest; - typedef objects::CTMgr_DisplayTrackReply TReply; - typedef CConstRef TRequestCRef; - typedef CRef TReplyRef; + using TRequest = objects::CTMgr_DisplayTrackRequest; + using TReply = objects::CTMgr_DisplayTrackReply; + using TRequestCRef = CConstRef; + using TReplyRef = CRef; public: CTMS_DisplayTrack_Client(const string& NS_service, @@ -67,10 +79,31 @@ public: CTMS_DisplayTrack_Client(const string& NS_registry_section = "netschedule_api", const string& NC_registry_section = kEmptyStr ); + CTMS_DisplayTrack_Client(CTMS_DisplayTrack_Client&& c) + : TBaseClient(move(c)), + m_Http_svc(move(c.m_Http_svc)), + m_Http_session(move(c.m_Http_session)), + m_Rpc_client(move(c.m_Rpc_client)) + { + } + virtual ~CTMS_DisplayTrack_Client() = default; - virtual ~CTMS_DisplayTrack_Client(); + static CTMS_DisplayTrack_Client CreateServiceClient(const string& http_svc = "TMS_DisplayTracks"); TReplyRef Fetch(const TRequest& request) const; + bool FetchRawStream(CNcbiIstream& requeststr, CNcbiOstream& replystr) const; + +protected: + CTMS_DisplayTrack_Client(CTMS_DisplayTrack_Client&) = delete; + CTMS_DisplayTrack_Client(const HttpService&& http_svc); + TReplyRef x_HttpFetch(const TRequest& request) const; + + +protected: + CUrl m_Http_svc; + mutable CRef m_Http_session; + using TRPCBaseClient = CGridRPCHttpClient; + mutable CRef m_Rpc_client; }; diff --git a/c++/include/objects/trackmgr/gridrpcclient.hpp b/c++/include/objects/trackmgr/gridrpcclient.hpp index 2619a990..e2d4a0fb 100644 --- a/c++/include/objects/trackmgr/gridrpcclient.hpp +++ b/c++/include/objects/trackmgr/gridrpcclient.hpp @@ -1,7 +1,7 @@ #ifndef OBJECTS_MISC_SERIAL___GRID_RPC_CLIENT__HPP #define OBJECTS_MISC_SERIAL___GRID_RPC_CLIENT__HPP -/* $Id: gridrpcclient.hpp 489744 2016-01-15 16:50:24Z sadyrovr $ +/* $Id: gridrpcclient.hpp 514371 2016-09-21 15:22:54Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -74,7 +75,7 @@ public: class CAsnBinCompressed : public CAsnBin { public: - typedef int TOwnership; + using TOwnership = int; struct SStreamProp { @@ -93,17 +94,17 @@ public: /// underlying output stream /// @return /// object stream - static CObjectOStream* + static unique_ptr GetOStream(CNcbiOstream& ostr, SStreamProp stream_prop = SStreamProp(CCompressStream::eZip)) { - auto_ptr outstr_zip( + unique_ptr outstr_zip( new CCompressionOStream( ostr, CreateStreamCompressor(stream_prop), CCompressionStream::fOwnProcessor ) ); - return CObjectOStream::Open(GetDataFormat(), *outstr_zip.release(), eTakeOwnership); + return unique_ptr(CObjectOStream::Open(GetDataFormat(), *outstr_zip.release(), eTakeOwnership)); } /// Return an object input stream (CObjectIStream) @@ -112,43 +113,57 @@ public: /// underlying input stream /// @return /// object stream - static CObjectIStream* + static unique_ptr GetIStream(CNcbiIstream& istr) { return GetIStream(istr, GetIStreamProperties(istr)); } - static CObjectIStream* + static unique_ptr GetIStream(const string& job_content, CNetCacheAPI& nc_api) { SStreamProp sp; return GetIStream(job_content, nc_api, sp); } - static CObjectIStream* + static unique_ptr GetIStream(const string& job_content, CNetCacheAPI& nc_api, SStreamProp& streamprop) { - streamprop = GetJobStreamProperties(job_content, nc_api); - auto_ptr reader(new CStringOrBlobStorageReader(job_content, nc_api)); - auto_ptr rstr(new CRStream(reader.release(), CRWStreambuf::fOwnReader)); + auto rstr = GetRawIStream(job_content, nc_api, streamprop); return GetIStream(*rstr.release(), streamprop, CCompressionStream::fOwnAll); } + static unique_ptr + GetRawIStream(const string& job_content, CNetCacheAPI& nc_api) + { + SStreamProp sp; + return GetRawIStream(job_content, nc_api, sp); + } + + static unique_ptr + GetRawIStream(const string& job_content, CNetCacheAPI& nc_api, SStreamProp& streamprop) + { + streamprop = GetJobStreamProperties(job_content, nc_api); + unique_ptr reader(new CStringOrBlobStorageReader(job_content, nc_api)); + unique_ptr rstr(new CRStream(reader.release(), CRWStreambuf::fOwnReader)); + return rstr; + } + protected: - static CObjectIStream* + static unique_ptr GetIStream(CNcbiIstream& istr, const SStreamProp& stream_prop, TOwnership ownership = CCompressionStream::fOwnProcessor ) { - auto_ptr instr_zip( + unique_ptr instr_zip( new CCompressionIStream( istr, CreateStreamDecompressor(stream_prop), ownership ) ); - return CObjectIStream::Open(GetDataFormat(), *instr_zip.release(), eTakeOwnership); + return unique_ptr(CObjectIStream::Open(GetDataFormat(), *instr_zip.release(), eTakeOwnership)); } static SStreamProp GetJobStreamProperties(const string& job_content, CNetCacheAPI& nc_api) @@ -192,7 +207,7 @@ protected: static CCompressionStreamProcessor* CreateStreamCompressor(const SStreamProp& stream_prop) { - auto_ptr sp; + unique_ptr sp; if (stream_prop.compress_method == CCompressStream::eLZO) { sp.reset(new CLZOStreamCompressor()); } @@ -204,7 +219,7 @@ protected: static CCompressionStreamProcessor* CreateStreamDecompressor(const SStreamProp& stream_prop) { - auto_ptr sp; + unique_ptr sp; if (stream_prop.compress_method == CCompressStream::eLZO) { sp.reset(new CLZOStreamDecompressor()); } @@ -257,7 +272,7 @@ public: /// TConnectTraits template classes: CAsnBinCompressed /// template -class CGridRPCBaseClient : private TConnectTraits +class CGridRPCBaseClient : protected TConnectTraits { public: CGridRPCBaseClient(const string& NS_service, @@ -297,8 +312,65 @@ public: m_NC_api = CNetCacheAPI(CNetCacheAPI::eAppRegistry, NC_registry_section); } - virtual ~CGridRPCBaseClient() + virtual ~CGridRPCBaseClient() = default; + + pair AskStream(CNcbiIstream& request, CNcbiOstream& reply) const { + CGridClient grid_cli(m_NS_api.GetSubmitter(), + m_NC_api, + CGridClient::eManualCleanup, + CGridClient::eProgressMsgOn + ); + auto& job_in = grid_cli.GetOStream(); // job input stream + NcbiStreamCopy(job_in, request); + if (job_in.bad()) { + NCBI_THROW(CIOException, eWrite, "Error while writing request"); + } + grid_cli.CloseStream(); + + CNetScheduleJob& job = grid_cli.GetJob(); + bool timed_out = false; + x_PrepareJob(job); + + try { + const CNetScheduleAPI::EJobStatus evt = grid_cli.SubmitAndWait(m_Timeout); + switch (evt) { + case CNetScheduleAPI::eDone: + { + m_NS_api.GetJobDetails(job); + auto instr = TConnectTraits::GetRawIStream(job.output, m_NC_api); + NcbiStreamCopy(reply, *instr); + break; + } + case CNetScheduleAPI::eFailed: + NCBI_THROW(CGridRPCBaseClientException, eUnexpectedFailure, "Job failed"); + + case CNetScheduleAPI::eCanceled: + NCBI_THROW(CGridRPCBaseClientException, eUnexpectedFailure, "Job canceled"); + + case CNetScheduleAPI::eRunning: + NCBI_THROW(CGridRPCBaseClientException, eUnexpectedFailure, "Job running"); + + default: + NCBI_THROW(CGridRPCBaseClientException, + eWaitTimeout, + "Unexpected status: " + CNetScheduleAPI::StatusToString(evt) + ); + } + } + catch (const CGridRPCBaseClientException& e) { + switch (e.GetErrCode()) { + case CGridRPCBaseClientException::eUnexpectedFailure: + timed_out = true; + break; + + case CGridRPCBaseClientException::eWaitTimeout: + default: + break; + } + throw e; + } + return make_pair(job, timed_out); } template @@ -309,8 +381,8 @@ public: CGridClient::eManualCleanup, CGridClient::eProgressMsgOn ); - CNcbiOstream& job_in = grid_cli.GetOStream(); // job input stream - auto_ptr outstr(TConnectTraits::GetOStream(job_in)); + auto& job_in = grid_cli.GetOStream(); // job input stream + auto outstr = TConnectTraits::GetOStream(job_in); *outstr << request; if (job_in.bad()) { NCBI_THROW(CIOException, eWrite, "Error while writing request"); @@ -328,7 +400,7 @@ public: case CNetScheduleAPI::eDone: { m_NS_api.GetJobDetails(job); - auto_ptr instr(TConnectTraits::GetIStream(job.output, m_NC_api)); + auto instr = TConnectTraits::GetIStream(job.output, m_NC_api); *instr >> reply; break; } @@ -364,7 +436,14 @@ public: } protected: - virtual void x_PrepareJob(CNetScheduleJob& job) const + CGridRPCBaseClient(const CGridRPCBaseClient&) = delete; + CGridRPCBaseClient(CGridRPCBaseClient&& c) + : m_NS_api(move(c.m_NS_api)), m_NC_api(move(c.m_NC_api)), + m_Timeout(c.m_Timeout) + { + } + + virtual void x_PrepareJob(CNetScheduleJob& /*job*/) const { } @@ -380,7 +459,7 @@ protected: case CNetScheduleAPI::eDone: { m_NS_api.GetJobDetails(job); - auto_ptr instr(TConnectTraits::GetIStream(job.output, m_NC_api)); + auto instr = TConnectTraits::GetIStream(job.output, m_NC_api); *instr >> reply; break; } @@ -409,6 +488,30 @@ private: }; +template +class CGridRPCHttpClient : public CRPCClient +{ +protected: + using TParent = CRPCClient; + +public: + CGridRPCHttpClient(const string& http_service) + : TParent(http_service) + { + } + + virtual ~CGridRPCHttpClient() = default; + +protected: + virtual void x_Connect() override + { + TParent::x_Connect(); + TParent::m_In.reset(CAsnBinCompressed::GetIStream(*TParent::m_Stream).release()); + TParent::m_Out.reset(CAsnBinCompressed::GetOStream(*TParent::m_Stream).release()); + } +}; + + END_NCBI_SCOPE #endif // OBJECTS_MISC_SERIAL___GRID_RPC_CLIENT__HPP diff --git a/c++/include/objects/valerr/ValidErrItem.hpp b/c++/include/objects/valerr/ValidErrItem.hpp index 1254c40a..73191d2a 100644 --- a/c++/include/objects/valerr/ValidErrItem.hpp +++ b/c++/include/objects/valerr/ValidErrItem.hpp @@ -1,4 +1,4 @@ -/* $Id: ValidErrItem.hpp 473063 2015-07-15 23:22:36Z kans $ +/* $Id: ValidErrItem.hpp 519224 2016-11-14 16:08:42Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -251,6 +251,7 @@ enum EErrType { eErr_SEQ_DESCR_WrongBiomolForTechnique, eErr_SEQ_DESCR_WrongOrganismFor16SrRNA, eErr_SEQ_DESCR_InconsistentWGSFlags, + eErr_SEQ_DESCR_TitleNotAppropriateForSet, ERR_CODE_END(SEQ_DESCR), @@ -275,6 +276,19 @@ enum EErrType { eErr_GENERIC_MissingVolumeEpub, eErr_GENERIC_MissingPages, eErr_GENERIC_MissingPagesEpub, + eErr_GENERIC_BarcodeTooShort, + eErr_GENERIC_BarcodeMissingPrimers, + eErr_GENERIC_BarcodeMissingCountry, + eErr_GENERIC_BarcodeMissingVoucher, + eErr_GENERIC_BarcodeTooManyNs, + eErr_GENERIC_BarcodeBadCollectionDate, + eErr_GENERIC_BarcodeMissingOrderAssignment, + eErr_GENERIC_BarcodeLowTrace, + eErr_GENERIC_BarcodeFrameShift, + eErr_GENERIC_BarcodeStructuredVoucher, + eErr_GENERIC_BarcodeTestFails, + eErr_GENERIC_BarcodeTestPasses, + eErr_GENERIC_InvalidAsn, ERR_CODE_END(GENERIC), ERR_CODE_BEGIN(SEQ_PKG) = 3000, @@ -410,6 +424,7 @@ enum EErrType { eErr_SEQ_FEAT_BadFullLengthFeature, eErr_SEQ_FEAT_RedundantFields, eErr_SEQ_FEAT_CDSwithNoMRNAOverlap, + eErr_SEQ_FEAT_CDSwithNoMRNA, eErr_SEQ_FEAT_FeatureProductInconsistency, eErr_SEQ_FEAT_ImproperBondLocation, eErr_SEQ_FEAT_GeneXrefWithoutGene, @@ -521,6 +536,9 @@ enum EErrType { eErr_SEQ_FEAT_InconsistentPseudogeneValue, eErr_SEQ_FEAT_MultiIntervalIntron, eErr_SEQ_FEAT_SeqLocTypeProblem, + eErr_SEQ_FEAT_RefSeqInText, + eErr_SEQ_FEAT_ColdShockProteinProblem, + eErr_SEQ_FEAT_BadLocation, ERR_CODE_END(SEQ_FEAT), ERR_CODE_BEGIN(SEQ_ALIGN) = 5000, diff --git a/c++/include/objects/valerr/ValidError.hpp b/c++/include/objects/valerr/ValidError.hpp index e13d4ce9..70f09261 100644 --- a/c++/include/objects/valerr/ValidError.hpp +++ b/c++/include/objects/valerr/ValidError.hpp @@ -1,4 +1,4 @@ -/* $Id: ValidError.hpp 447658 2014-09-29 18:29:18Z bollin $ +/* $Id: ValidError.hpp 513779 2016-09-15 11:23:57Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -91,6 +91,10 @@ public: const int ver, // version of object. const int seq_offset = 0); + void AddValidErrItem(EDiagSev sev, // severity + unsigned int ec, // error code + const string& msg); // specific error message + // Statistics SIZE_TYPE TotalSize(void) const; SIZE_TYPE Size(EDiagSev sev) const; diff --git a/c++/include/objects/valid/Comment_rule.hpp b/c++/include/objects/valid/Comment_rule.hpp index 000a88dc..5573b0ae 100644 --- a/c++/include/objects/valid/Comment_rule.hpp +++ b/c++/include/objects/valid/Comment_rule.hpp @@ -1,4 +1,4 @@ -/* $Id: Comment_rule.hpp 493827 2016-03-02 13:59:27Z ivanov $ +/* $Id: Comment_rule.hpp 491404 2016-02-04 17:37:54Z bollin $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/objects/varrep/AaInterval.hpp b/c++/include/objects/varrep/AaInterval.hpp new file mode 100644 index 00000000..1d354d37 --- /dev/null +++ b/c++/include/objects/varrep/AaInterval.hpp @@ -0,0 +1,90 @@ +/* $Id: AaInterval.hpp 497242 2016-04-05 14:40:38Z foleyjp $ + * =========================================================================== + * + * PUBLIC DOMAIN NOTICE + * National Center for Biotechnology Information + * + * This software/database is a "United States Government Work" under the + * terms of the United States Copyright Act. It was written as part of + * the author's official duties as a United States Government employee and + * thus cannot be copyrighted. This software/database is freely available + * to the public for use. The National Library of Medicine and the U.S. + * Government have not placed any restriction on its use or reproduction. + * + * Although all reasonable efforts have been taken to ensure the accuracy + * and reliability of the software and data, the NLM and the U.S. + * Government do not and cannot warrant the performance or results that + * may be obtained by using this software or data. The NLM and the U.S. + * Government disclaim all warranties, express or implied, including + * warranties of performance, merchantability or fitness for any particular + * purpose. + * + * Please cite the author in any work or product based on this material. + * + * =========================================================================== + * + */ + +/// @file AaInterval.hpp +/// User-defined methods of the data storage class. +/// +/// This file was originally generated by application DATATOOL +/// using the following specifications: +/// 'variation_irep.asn'. +/// +/// New methods or data members can be added to it if needed. +/// See also: AaInterval_.hpp + + +#ifndef OBJECTS_VARREP_AAINTERVAL_HPP +#define OBJECTS_VARREP_AAINTERVAL_HPP + + +// generated includes +#include + +// generated classes + +BEGIN_NCBI_SCOPE + +BEGIN_objects_SCOPE // namespace ncbi::objects:: + +///////////////////////////////////////////////////////////////////////////// +class CAaInterval : public CAaInterval_Base +{ + typedef CAaInterval_Base Tparent; +public: + // constructor + CAaInterval(void); + // destructor + ~CAaInterval(void); + + size_t size(void) const; + string GetString(void) const; + +private: + // Prohibit copy constructor and assignment operator + CAaInterval(const CAaInterval& value); + CAaInterval& operator=(const CAaInterval& value); + +}; + +/////////////////// CAaInterval inline methods + +// constructor +inline +CAaInterval::CAaInterval(void) +{ +} + + +/////////////////// end of CAaInterval inline methods + + +END_objects_SCOPE // namespace ncbi::objects:: + +END_NCBI_SCOPE + + +#endif // INTERNAL_VARIATION_EXCHANGE_OBJECTS_HGVS_PARSER_AAINTERVAL_HPP +/* Original file checksum: lines: 86, chars: 2550, CRC32: d1dc9d82 */ diff --git a/c++/include/objects/varrep/AaLocation.hpp b/c++/include/objects/varrep/AaLocation.hpp new file mode 100644 index 00000000..bdd75ec9 --- /dev/null +++ b/c++/include/objects/varrep/AaLocation.hpp @@ -0,0 +1,90 @@ +/* $Id: AaLocation.hpp 497242 2016-04-05 14:40:38Z foleyjp $ + * =========================================================================== + * + * PUBLIC DOMAIN NOTICE + * National Center for Biotechnology Information + * + * This software/database is a "United States Government Work" under the + * terms of the United States Copyright Act. It was written as part of + * the author's official duties as a United States Government employee and + * thus cannot be copyrighted. This software/database is freely available + * to the public for use. The National Library of Medicine and the U.S. + * Government have not placed any restriction on its use or reproduction. + * + * Although all reasonable efforts have been taken to ensure the accuracy + * and reliability of the software and data, the NLM and the U.S. + * Government do not and cannot warrant the performance or results that + * may be obtained by using this software or data. The NLM and the U.S. + * Government disclaim all warranties, express or implied, including + * warranties of performance, merchantability or fitness for any particular + * purpose. + * + * Please cite the author in any work or product based on this material. + * + * =========================================================================== + * + */ + +/// @file AaLocation.hpp +/// User-defined methods of the data storage class. +/// +/// This file was originally generated by application DATATOOL +/// using the following specifications: +/// 'variation_irep.asn'. +/// +/// New methods or data members can be added to it if needed. +/// See also: AaLocation_.hpp + + +#ifndef OBJECTS_VARREP_AALOCATION_HPP +#define OBJECTS_VARREP_AALOCATION_HPP + + +// generated includes +#include + +// generated classes + +BEGIN_NCBI_SCOPE + +BEGIN_objects_SCOPE // namespace ncbi::objects:: + +///////////////////////////////////////////////////////////////////////////// +class CAaLocation : public CAaLocation_Base +{ + typedef CAaLocation_Base Tparent; +public: + // constructor + CAaLocation(void); + // destructor + ~CAaLocation(void); + + size_t size(void) const; + string GetString(void) const; + +private: + // Prohibit copy constructor and assignment operator + CAaLocation(const CAaLocation& value); + CAaLocation& operator=(const CAaLocation& value); + +}; + +/////////////////// CAaLocation inline methods + +// constructor +inline +CAaLocation::CAaLocation(void) +{ +} + + +/////////////////// end of CAaLocation inline methods + + +END_objects_SCOPE // namespace ncbi::objects:: + +END_NCBI_SCOPE + + +#endif // INTERNAL_VARIATION_EXCHANGE_OBJECTS_HGVS_PARSER_AALOCATION_HPP +/* Original file checksum: lines: 86, chars: 2550, CRC32: d954b9b7 */ diff --git a/c++/include/objmgr/annot_selector.hpp b/c++/include/objmgr/annot_selector.hpp index 731ae351..b65edcc9 100644 --- a/c++/include/objmgr/annot_selector.hpp +++ b/c++/include/objmgr/annot_selector.hpp @@ -1,7 +1,7 @@ #ifndef ANNOT_SELECTOR__HPP #define ANNOT_SELECTOR__HPP -/* $Id: annot_selector.hpp 499042 2016-04-21 17:39:04Z ivanov $ +/* $Id: annot_selector.hpp 519943 2016-11-21 15:34:20Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -466,6 +466,21 @@ struct NCBI_XOBJMGR_EXPORT SAnnotSelector : public SAnnotTypeSelector return *this; } + enum EMaxSearchSegmentsAction { + eMaxSearchSegmentsThrow, // default + eMaxSearchSegmentsLog, // log error message, and stop searching + eMaxSearchSegmentsSilent // silently stop searching + }; + EMaxSearchSegmentsAction GetMaxSearchSegmentsAction(void) const + { + return m_MaxSearchSegmentsAction; + } + SAnnotSelector& SetMaxSearchSegmentsAction(EMaxSearchSegmentsAction action) + { + m_MaxSearchSegmentsAction = action; + return *this; + } + typedef float TMaxSearchTime; /// Get maximum time (in seconds) to search before giving up. TMaxSearchTime GetMaxSearchTime(void) const @@ -726,6 +741,35 @@ struct NCBI_XOBJMGR_EXPORT SAnnotSelector : public SAnnotTypeSelector return m_IgnoreFarLocationsForSorting; } + /// Set bit filter for annotations that support it (SNP) + /// If filter is set then collect only annotations + /// that have masked (filter_mask) bits equal to the filter_bits + typedef Uint8 TBitFilter; + SAnnotSelector& SetBitFilter(TBitFilter filter_bits, + TBitFilter filter_mask = TBitFilter(-1)) + { + m_FilterMask = filter_mask; + m_FilterBits = filter_bits & filter_mask; + return *this; + } + SAnnotSelector& ResetBitFilter(void) + { + m_FilterMask = m_FilterBits = 0; + return *this; + } + bool HasBitFilter(void) const + { + return m_FilterMask != 0; + } + TBitFilter GetFilterMask(void) const + { + return m_FilterMask; + } + TBitFilter GetFilterBits(void) const + { + return m_FilterBits; + } + protected: friend class CAnnot_Collector; @@ -760,6 +804,7 @@ protected: TAnnotsNames m_IncludeAnnotsNames; TAnnotsNames m_ExcludeAnnotsNames; AutoPtr m_NamedAnnotAccessions; + EMaxSearchSegmentsAction m_MaxSearchSegmentsAction; bool m_NoMapping; TAdaptiveDepthFlags m_AdaptiveDepthFlags; bool m_ExactDepth; @@ -773,6 +818,8 @@ protected: TAnnotTypesBitset m_AnnotTypesBitset; AutoPtr m_SourceLoc; CBioseq_Handle m_IgnoreFarLocationsForSorting; + TBitFilter m_FilterMask; + TBitFilter m_FilterBits; }; diff --git a/c++/include/objmgr/annot_types_ci.hpp b/c++/include/objmgr/annot_types_ci.hpp index dfba1065..03e907cd 100644 --- a/c++/include/objmgr/annot_types_ci.hpp +++ b/c++/include/objmgr/annot_types_ci.hpp @@ -1,7 +1,7 @@ #ifndef ANNOT_TYPES_CI__HPP #define ANNOT_TYPES_CI__HPP -/* $Id: annot_types_ci.hpp 439336 2014-06-27 16:08:17Z vasilche $ +/* $Id: annot_types_ci.hpp 519943 2016-11-21 15:34:20Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -92,6 +92,9 @@ public: // Get number of annotations size_t GetSize(void) const; + // check if empty segment limit is reached + bool MaxSearchSegmentsLimitIsReached(void) const; + typedef vector TAnnotTypes; // Get annot types const TAnnotTypes& GetAnnotTypes(void) const; diff --git a/c++/include/objmgr/bioseq_handle.hpp b/c++/include/objmgr/bioseq_handle.hpp index d3b6162b..612eb79d 100644 --- a/c++/include/objmgr/bioseq_handle.hpp +++ b/c++/include/objmgr/bioseq_handle.hpp @@ -1,7 +1,7 @@ #ifndef BIOSEQ_HANDLE__HPP #define BIOSEQ_HANDLE__HPP -/* $Id: bioseq_handle.hpp 499042 2016-04-21 17:39:04Z ivanov $ +/* $Id: bioseq_handle.hpp 496211 2016-03-24 15:33:11Z vasilche $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/objmgr/data_loader.hpp b/c++/include/objmgr/data_loader.hpp index f6d46f5a..2838f42c 100644 --- a/c++/include/objmgr/data_loader.hpp +++ b/c++/include/objmgr/data_loader.hpp @@ -1,7 +1,7 @@ #ifndef OBJECTS_OBJMGR___DATA_LOADER__HPP #define OBJECTS_OBJMGR___DATA_LOADER__HPP -/* $Id: data_loader.hpp 498421 2016-04-15 18:44:37Z ivanov $ +/* $Id: data_loader.hpp 498345 2016-04-15 14:39:08Z vasilche $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/objmgr/impl/annot_collector.hpp b/c++/include/objmgr/impl/annot_collector.hpp index e2d249d9..8c114f4d 100644 --- a/c++/include/objmgr/impl/annot_collector.hpp +++ b/c++/include/objmgr/impl/annot_collector.hpp @@ -1,7 +1,7 @@ #ifndef ANNOT_COLLECTOR__HPP #define ANNOT_COLLECTOR__HPP -/* $Id: annot_collector.hpp 493571 2016-02-29 19:45:30Z ivanov $ +/* $Id: annot_collector.hpp 519943 2016-11-21 15:34:20Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -61,6 +61,8 @@ struct SAnnotObject_Index; class CSeq_entry_Info; class CSeq_annot_Info; class CSeq_annot_SNP_Info; +class CSeq_annot_SortedIter; +class CSeqTableInfo; struct SSNP_Info; struct SIdAnnotObjs; class CSeq_loc_Conversion; @@ -177,9 +179,15 @@ class NCBI_XOBJMGR_EXPORT CAnnotObject_Ref public: typedef CRange TRange; typedef Int4 TAnnotIndex; - enum { - kSNPTableBit = 0x80000000, - kAnnotIndexMask = 0x7fffffff + enum EAnnotType { + fAnnot_NoAnnotInfo = 1<<0, + fAnnot_SNPTable = 1<<1, + fAnnot_SeqTable = 1<<2, + + eAnnot_Regular = 0, + eAnnot_SNPTable = fAnnot_NoAnnotInfo | fAnnot_SNPTable, + eAnnot_SeqTable = fAnnot_SeqTable, + eAnnot_SortedSeqTable = fAnnot_NoAnnotInfo | fAnnot_SeqTable, }; CAnnotObject_Ref(void); @@ -189,15 +197,34 @@ public: const CSeq_annot_Handle& annot_handle, const SSNP_Info& snp_info, CSeq_loc_Conversion* cvt); + CAnnotObject_Ref(const CSeq_annot_Handle& annot_handle, + const CSeq_annot_SortedIter& iter, + CSeq_loc_Conversion* cvt); + // the annotation has CAnnotObject_Info object and entry in annot index bool HasAnnotObject_Info(void) const; + // the annotation has CSeq_feat, CAnnotObject_Info, and annot index bool IsPlainFeat(void) const; - bool IsSNPFeat(void) const; - bool IsTableFeat(void) const; + + // the feature is from parsed SNP table (GenBank SNP external annotations) + // it doesn't have corresponding CAnnotObject_Info and entry in annot index + bool IsSNPTableFeat(void) const; + // the feature is from Seq-table + // it may or may not have corresponding CAnnotObject_Info and annot index + bool IsAnySeqTableFeat(void) const; + // the feature is from pre-sorted Seq-table + // it doesn't have corresponding CAnnotObject_Info and entry in annot index + bool IsSortedSeqTableFeat(void) const; + + // replaced with IsSNPTableFeat() and IsSortedSeqTableFeat() + NCBI_DEPRECATED bool IsSNPFeat(void) const; + // replaced with IsAnySeqTableFeat() and IsSortedSeqTableFeat() + NCBI_DEPRECATED bool IsTableFeat(void) const; const CSeq_annot_Handle& GetSeq_annot_Handle(void) const; const CSeq_annot_Info& GetSeq_annot_Info(void) const; const CSeq_annot_SNP_Info& GetSeq_annot_SNP_Info(void) const; + const CSeqTableInfo& GetSeqTableInfo(void) const; TAnnotIndex GetAnnotIndex(void) const; const CAnnotObject_Info& GetAnnotObject_Info(void) const; @@ -226,8 +253,12 @@ private: friend class CAnnot_Collector; CSeq_annot_Handle m_Seq_annot; // 4 or 8 + mutable CAnnotMapping_Info m_MappingInfo; // 20 or 32 TAnnotIndex m_AnnotIndex; // 4 or 4 - mutable CAnnotMapping_Info m_MappingInfo; // 16 or 20 + EAnnotType m_AnnotType; // 4 or 4 + // total size: + // 32 B on 32-bit system (can be packed into 28 B) + // 48 B on 64-bit system (can be packed into 40 B) }; @@ -459,6 +490,10 @@ private: const TAnnotNames& x_GetAnnotNames(void) const; void x_StopSearchLimits(void); + bool x_MaxSearchSegmentsLimitIsReached(void) const + { + return m_SearchSegments == 0; + } const SAnnotSelector* m_Selector; CHeapScope m_Scope; @@ -482,6 +517,7 @@ private: typedef SAnnotSelector::TMaxSearchSegments TMaxSearchSegments; CStopWatch m_SearchTime; TMaxSearchSegments m_SearchSegments; + SAnnotSelector::EMaxSearchSegmentsAction m_SearchSegmentsAction; bool m_FromOtherTSE; friend class CAnnotTypes_CI; @@ -792,7 +828,7 @@ void CAnnotMapping_Info::Swap(CAnnotMapping_Info& info) inline CAnnotObject_Ref::CAnnotObject_Ref(void) - : m_AnnotIndex(0) + : m_AnnotIndex(0), m_AnnotType(eAnnot_Regular) { } @@ -800,37 +836,56 @@ CAnnotObject_Ref::CAnnotObject_Ref(void) inline CAnnotObject_Ref::TAnnotIndex CAnnotObject_Ref::GetAnnotIndex(void) const { - return m_AnnotIndex & kAnnotIndexMask; + return m_AnnotIndex; } inline bool CAnnotObject_Ref::HasAnnotObject_Info(void) const { - return (m_AnnotIndex & kSNPTableBit) == 0; + return (m_AnnotType & fAnnot_NoAnnotInfo) == 0; } inline bool CAnnotObject_Ref::IsPlainFeat(void) const { - return (m_AnnotIndex & kSNPTableBit) == 0 && - GetAnnotObject_Info().IsRegular(); + return m_AnnotType == eAnnot_Regular; +} + + +inline +bool CAnnotObject_Ref::IsSNPTableFeat(void) const +{ + return m_AnnotType == eAnnot_SNPTable; +} + + +inline +bool CAnnotObject_Ref::IsSortedSeqTableFeat(void) const +{ + return m_AnnotType == eAnnot_SortedSeqTable; +} + + +inline +bool CAnnotObject_Ref::IsAnySeqTableFeat(void) const +{ + return (m_AnnotType & fAnnot_SeqTable) != 0; } inline bool CAnnotObject_Ref::IsSNPFeat(void) const { - return (m_AnnotIndex & kSNPTableBit) != 0; + return IsSNPTableFeat(); } inline bool CAnnotObject_Ref::IsTableFeat(void) const { - return (m_AnnotIndex & kSNPTableBit) == 0 && - !GetAnnotObject_Info().IsRegular(); + return IsAnySeqTableFeat(); } @@ -854,6 +909,9 @@ bool CAnnotObject_Ref::operator<(const CAnnotObject_Ref& ref) const if ( m_Seq_annot != ref.m_Seq_annot ) { return m_Seq_annot.OrderedBefore(ref.m_Seq_annot); } + if ( m_AnnotType != ref.m_AnnotType ) { + return m_AnnotType < ref.m_AnnotType; + } return m_AnnotIndex < ref.m_AnnotIndex; } @@ -861,16 +919,16 @@ bool CAnnotObject_Ref::operator<(const CAnnotObject_Ref& ref) const inline bool CAnnotObject_Ref::operator==(const CAnnotObject_Ref& ref) const { - return (m_Seq_annot == ref.m_Seq_annot && - m_AnnotIndex == ref.m_AnnotIndex); + return (m_AnnotIndex == ref.m_AnnotIndex && + m_AnnotType == ref.m_AnnotType && + m_Seq_annot == ref.m_Seq_annot); } inline bool CAnnotObject_Ref::operator!=(const CAnnotObject_Ref& ref) const { - return (m_Seq_annot != ref.m_Seq_annot || - m_AnnotIndex != ref.m_AnnotIndex); + return !(*this == ref); } @@ -927,6 +985,7 @@ void CAnnotObject_Ref::Swap(CAnnotObject_Ref& ref) { m_Seq_annot.Swap(ref.m_Seq_annot); swap(m_AnnotIndex, ref.m_AnnotIndex); + swap(m_AnnotType, ref.m_AnnotType); m_MappingInfo.Swap(ref.m_MappingInfo); } diff --git a/c++/include/objmgr/impl/annot_object_index.hpp b/c++/include/objmgr/impl/annot_object_index.hpp index 1767ac85..a4ac61c2 100644 --- a/c++/include/objmgr/impl/annot_object_index.hpp +++ b/c++/include/objmgr/impl/annot_object_index.hpp @@ -1,7 +1,7 @@ #ifndef OBJECTS_OBJMGR_IMPL___ANNOT_OBJECT_INDEX__HPP #define OBJECTS_OBJMGR_IMPL___ANNOT_OBJECT_INDEX__HPP -/* $Id: annot_object_index.hpp 382134 2012-12-03 19:56:38Z vasilche $ +/* $Id: annot_object_index.hpp 514368 2016-09-21 15:22:14Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -129,15 +129,15 @@ struct SAnnotObject_Index } void SetLocationIsPoint(void) { - m_Flags = (m_Flags & ~fSimpleLocation_Mask) | fLocation_Point; + m_Flags = TFlags((m_Flags & ~fSimpleLocation_Mask) | fLocation_Point); } void SetLocationIsInterval(void) { - m_Flags = (m_Flags & ~fSimpleLocation_Mask) | fLocation_Interval; + m_Flags = TFlags((m_Flags & ~fSimpleLocation_Mask) | fLocation_Interval); } void SetLocationIsWhole(void) { - m_Flags = (m_Flags & ~fSimpleLocation_Mask) | fLocation_Whole; + m_Flags = TFlags((m_Flags & ~fSimpleLocation_Mask) | fLocation_Whole); } CAnnotObject_Info* m_AnnotObject_Info; diff --git a/c++/include/objmgr/impl/bioseq_base_info.hpp b/c++/include/objmgr/impl/bioseq_base_info.hpp index 520ebcbe..eb52c969 100644 --- a/c++/include/objmgr/impl/bioseq_base_info.hpp +++ b/c++/include/objmgr/impl/bioseq_base_info.hpp @@ -1,7 +1,7 @@ #ifndef OBJECTS_OBJMGR_IMPL___BIOSEQ_BASE_INFO__HPP #define OBJECTS_OBJMGR_IMPL___BIOSEQ_BASE_INFO__HPP -/* $Id: bioseq_base_info.hpp 465027 2015-04-16 13:18:40Z vasilche $ +/* $Id: bioseq_base_info.hpp 507368 2016-07-18 21:33:41Z vasilche $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -111,6 +111,8 @@ public: const CSeqdesc* x_SearchFirstDesc(TDescTypeMask type) const; + TDescTypeMask x_GetExistingDescrMask(void) const; + // annot typedef vector< CRef > TAnnot; typedef list< CRef > TObjAnnot; @@ -153,7 +155,7 @@ public: void x_DoUpdate(TNeedUpdateFlags flags); void x_SetNeedUpdateParent(TNeedUpdateFlags flags); -private: +protected: bool x_IsEndNextDesc(TDesc_CI iter) const; // internal inlined method friend class CAnnotTypes_CI; diff --git a/c++/include/objmgr/impl/bioseq_info.hpp b/c++/include/objmgr/impl/bioseq_info.hpp index 0c36a7fc..20b770d9 100644 --- a/c++/include/objmgr/impl/bioseq_info.hpp +++ b/c++/include/objmgr/impl/bioseq_info.hpp @@ -1,7 +1,7 @@ #ifndef OBJECTS_OBJMGR_IMPL___BIOSEQ_INFO__HPP #define OBJECTS_OBJMGR_IMPL___BIOSEQ_INFO__HPP -/* $Id: bioseq_info.hpp 499042 2016-04-21 17:39:04Z ivanov $ +/* $Id: bioseq_info.hpp 496211 2016-03-24 15:33:11Z vasilche $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/objmgr/impl/data_source.hpp b/c++/include/objmgr/impl/data_source.hpp index 2357de31..070305d0 100644 --- a/c++/include/objmgr/impl/data_source.hpp +++ b/c++/include/objmgr/impl/data_source.hpp @@ -1,7 +1,7 @@ #ifndef OBJECTS_OBJMGR_IMPL___DATA_SOURCE__HPP #define OBJECTS_OBJMGR_IMPL___DATA_SOURCE__HPP -/* $Id: data_source.hpp 494477 2016-03-07 19:25:35Z ivanov $ +/* $Id: data_source.hpp 493168 2016-02-24 19:28:38Z vasilche $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/objmgr/impl/scope_impl.hpp b/c++/include/objmgr/impl/scope_impl.hpp index 380a11d9..efa3893d 100644 --- a/c++/include/objmgr/impl/scope_impl.hpp +++ b/c++/include/objmgr/impl/scope_impl.hpp @@ -1,7 +1,7 @@ #ifndef OBJMGR_IMPL_SCOPE_IMPL__HPP #define OBJMGR_IMPL_SCOPE_IMPL__HPP -/* $Id: scope_impl.hpp 496835 2016-03-31 15:49:15Z ivanov $ +/* $Id: scope_impl.hpp 495071 2016-03-14 17:45:32Z grichenk $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/objmgr/impl/seq_annot_info.hpp b/c++/include/objmgr/impl/seq_annot_info.hpp index 8fc77298..3a222885 100644 --- a/c++/include/objmgr/impl/seq_annot_info.hpp +++ b/c++/include/objmgr/impl/seq_annot_info.hpp @@ -1,7 +1,7 @@ #ifndef SEQ_ANNOT_INFO__HPP #define SEQ_ANNOT_INFO__HPP -/* $Id: seq_annot_info.hpp 496424 2016-03-28 15:16:13Z ivanov $ +/* $Id: seq_annot_info.hpp 502681 2016-05-26 16:04:36Z vasilche $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -42,6 +42,7 @@ #include #include #include +#include #include @@ -61,6 +62,7 @@ class CSeqTableInfo; class CFeat_id; class CGene_ref; class CSeq_feat_Handle; +class CSeq_annot_SortedIter; class NCBI_XOBJMGR_EXPORT CSeq_annot_Info : public CTSE_Info_Object { @@ -73,7 +75,10 @@ public: typedef C_Data::TGraph TGraph; typedef C_Data::TLocs TLocs; typedef C_Data::TSeq_table TSeq_table; - typedef Uint4 TAnnotIndex; + typedef Int4 TAnnotIndex; + + // annotation index marking the Seq-annot as a whole + static const TAnnotIndex kWholeAnnotIndex = kMax_I4; explicit CSeq_annot_Info(CSeq_annot& annot, int chunk_id = 0); explicit CSeq_annot_Info(CSeq_annot_SNP_Info& snp_annot); @@ -159,6 +164,10 @@ public: const CAnnotObject_Info& GetInfo(TAnnotIndex index) const; const CSeqTableInfo& GetTableInfo(void) const; + bool IsSortedTable(void) const; + CSeq_annot_SortedIter StartSortedIterator(CRange range) const; + bool MatchBitFilter(const SAnnotSelector& sel, + const CSeq_annot_SortedIter& iter) const; void UpdateTableFeat(CRef& seq_feat, CRef& seq_point, @@ -176,6 +185,10 @@ public: virtual string GetDescription(void) const; + // special access to SNP or sorted table features + bool TableFeat_HasLabel(TAnnotIndex index) const; + string TableFeat_GetLabel(TAnnotIndex index) const; + protected: friend class CDataSource; friend class CTSE_Info; @@ -260,6 +273,43 @@ private: }; +class NCBI_XOBJMGR_EXPORT CSeq_annot_SortedIter +{ +public: + + DECLARE_OPERATOR_BOOL(m_ObjectRow < m_NumRows); + + CSeq_annot_SortedIter& operator++(void) + { + ++m_ObjectRow; + x_Settle(); + return *this; + } + + size_t GetRow(void) const + { + return m_ObjectRow; + } + + const CRange& GetRange(void) const + { + return m_ObjectRange; + } + +protected: + void x_Settle(void); + bool x_Valid(void); + +private: + friend class CSeq_annot_Info; + + CRange m_RequestRange; + CRef m_Table_Info; + size_t m_ObjectRow, m_NumRows; + CRange m_ObjectRange; +}; + + ///////////////////////////////////////////////////////////////////// // // Inline methods @@ -326,7 +376,7 @@ CConstRef CSeq_annot_Info::GetSeq_annotSkeleton(void) const inline const CAnnotObject_Info& CSeq_annot_Info::GetInfo(TAnnotIndex index) const { - _ASSERT(index < GetAnnotObjectInfos().size()); + _ASSERT(size_t(index) < GetAnnotObjectInfos().size()); return GetAnnotObjectInfos()[index]; } diff --git a/c++/include/objmgr/impl/seq_entry_info.hpp b/c++/include/objmgr/impl/seq_entry_info.hpp index c3d98e54..188c27ce 100644 --- a/c++/include/objmgr/impl/seq_entry_info.hpp +++ b/c++/include/objmgr/impl/seq_entry_info.hpp @@ -1,7 +1,7 @@ #ifndef OBJECTS_OBJMGR_IMPL___SEQ_ENTRY_INFO__HPP #define OBJECTS_OBJMGR_IMPL___SEQ_ENTRY_INFO__HPP -/* $Id: seq_entry_info.hpp 203738 2010-09-01 19:02:10Z vasilche $ +/* $Id: seq_entry_info.hpp 518178 2016-11-01 11:46:07Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -91,7 +91,7 @@ public: typedef CSeq_entry TObject; - bool HasSeq_entry(void) const; + bool HasNoSeq_entry(void) const; CConstRef GetCompleteSeq_entry(void) const; CConstRef GetSeq_entryCore(void) const; CConstRef GetSeq_entrySkeleton(void) const; @@ -215,6 +215,9 @@ protected: void x_UpdateAnnotIndexContents(CTSE_Info& tse); + void x_UpdateSkeleton() const; + void x_Update(TNeedUpdateFlags flags) const; + void x_DoUpdate(TNeedUpdateFlags flags); void x_SetNeedUpdateContents(TNeedUpdateFlags flags); @@ -241,43 +244,11 @@ protected: ///////////////////////////////////////////////////////////////////// inline -bool CSeq_entry_Info::HasSeq_entry(void) const -{ - return m_Object.NotEmpty(); -} - - -inline -CSeq_entry::E_Choice CSeq_entry_Info::Which(void) const +bool CSeq_entry_Info::HasNoSeq_entry(void) const { - return m_Which; + return !m_Object; } -inline -CConstRef CSeq_entry_Info::GetSeq_entrySkeleton(void) const -{ - return m_Object; -} - -inline -CSeq_entry& CSeq_entry_Info::x_GetObject(void) -{ - return *m_Object; -} - - -inline -const CSeq_entry& CSeq_entry_Info::x_GetObject(void) const -{ - return *m_Object; -} - - -inline -const CBioseq_Base_Info& CSeq_entry_Info::x_GetBaseInfo(void) const -{ - return *m_Contents; -} inline bool CSeq_entry_Info::IsSet(void) const diff --git a/c++/include/objmgr/impl/seq_id_sort.hpp b/c++/include/objmgr/impl/seq_id_sort.hpp index 08bb0e74..d7e26a62 100644 --- a/c++/include/objmgr/impl/seq_id_sort.hpp +++ b/c++/include/objmgr/impl/seq_id_sort.hpp @@ -1,7 +1,7 @@ #ifndef OBJMGR_IMPL_SEQ_ID_SORT__HPP #define OBJMGR_IMPL_SEQ_ID_SORT__HPP -/* $Id: seq_id_sort.hpp 496835 2016-03-31 15:49:15Z ivanov $ +/* $Id: seq_id_sort.hpp 495071 2016-03-14 17:45:32Z grichenk $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/objmgr/impl/seq_table_info.hpp b/c++/include/objmgr/impl/seq_table_info.hpp index 59df0fae..0e25558c 100644 --- a/c++/include/objmgr/impl/seq_table_info.hpp +++ b/c++/include/objmgr/impl/seq_table_info.hpp @@ -1,7 +1,7 @@ #ifndef SEQ_TABLE_INFO__HPP #define SEQ_TABLE_INFO__HPP -/* $Id: seq_table_info.hpp 458003 2015-01-29 19:47:52Z vasilche $ +/* $Id: seq_table_info.hpp 502681 2016-05-26 16:04:36Z vasilche $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -53,6 +54,8 @@ class CSeq_point; class CSeq_feat; struct SAnnotObject_Key; struct SAnnotObject_Index; +struct SAnnotTypeSelector; +struct SAnnotSelector; ///////////////////////////////////////////////////////////////////////////// // information about Seq-table column @@ -83,6 +86,8 @@ public: return m_Column.GetPointer(); } + bool IsSingular(void) const; + bool IsSet(size_t row) const; bool GetBool(size_t row) const @@ -152,6 +157,7 @@ public: CConstRef GetLoc(size_t row) const; CConstRef GetId(size_t row) const; CSeq_id_Handle GetIdHandle(size_t row) const; + TSeqPos GetFrom(size_t row) const; CRange GetRange(size_t row) const; ENa_strand GetStrand(size_t row) const; @@ -162,11 +168,14 @@ public: return m_Is_real_loc; } + void SetTableKeyAndIndex(size_t row, SAnnotObject_Key& key, SAnnotObject_Index& index) const; private: + friend class CSeqTableInfo; + CTempString m_FieldName; CSeqTable_column_info::EField_id m_BaseValue; @@ -205,12 +214,23 @@ public: return m_IsFeatTable; } + size_t GetNumRows(void) const { + return m_Seq_table->GetNum_rows(); + } + void UpdateSeq_feat(size_t row, CRef& seq_feat, CRef& seq_pnt, CRef& seq_int) const; CConstRef GetTableLocation(void) const; + TSeqPos GetSortedMaxLength(void) const; + + bool IsSorted(void) const { + return m_IsSorted; + } + + SAnnotTypeSelector GetType(void) const; const CSeqTableLocColumns& GetLocation(void) const { return m_Location; @@ -224,6 +244,24 @@ public: bool IsPartial(size_t row) const { return m_Partial.GetBool(row); } + + CConstRef GetLocationId(size_t row) const { + return GetLocation().GetId(row); + } + TSeqPos GetLocationFrom(size_t row) const { + return GetLocation().GetFrom(row); + } + CRange GetLocationRange(size_t row) const { + return GetLocation().GetRange(row); + } + ENa_strand GetLocationStrand(size_t row) const { + return GetLocation().GetStrand(row); + } + + bool HasLabel(size_t row) const; + string GetLabel(size_t row) const; + + bool MatchBitFilter(const SAnnotSelector& sel, size_t row) const; // returns null if column not found const CSeqTableColumnInfo* FindColumn(int field_id) const; @@ -240,14 +278,20 @@ private: typedef vector TExtraColumns; void x_Initialize(const CSeq_table& table); + bool x_IsSorted(void) const; + CConstRef m_Seq_table; bool m_IsFeatTable; + bool m_IsSorted; CSeqTableColumnInfo m_Disabled; CSeqTableLocColumns m_Location; CSeqTableLocColumns m_Product; CSeqTableColumnInfo m_Partial; TExtraColumns m_ExtraColumns; + CConstRef m_TableLocation; + TSeqPos m_SortedMaxLength; + typedef map TColumnsById; typedef map TColumnsByName; TColumnsById m_ColumnsById; diff --git a/c++/include/objmgr/impl/seq_table_setters.hpp b/c++/include/objmgr/impl/seq_table_setters.hpp index 0c18456c..a447a84a 100644 --- a/c++/include/objmgr/impl/seq_table_setters.hpp +++ b/c++/include/objmgr/impl/seq_table_setters.hpp @@ -1,7 +1,7 @@ #ifndef SEQ_TABLE_SETTERS__HPP #define SEQ_TABLE_SETTERS__HPP -/* $Id: seq_table_setters.hpp 458003 2015-01-29 19:47:52Z vasilche $ +/* $Id: seq_table_setters.hpp 514368 2016-09-21 15:22:14Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -86,8 +86,8 @@ public: class CSeqTableSetQual : public CSeqTableSetFeatField { public: - CSeqTableSetQual(const CTempString& name) - : name(name.substr(2)) + CSeqTableSetQual(const CTempString& name_str) + : name(name_str.substr(2)) { } @@ -122,8 +122,8 @@ private: class CSeqTableSetDbxref : public CSeqTableSetFeatField { public: - CSeqTableSetDbxref(const CTempString& name) - : name(name.substr(2)) + CSeqTableSetDbxref(const CTempString& name_str) + : name(name_str.substr(2)) { } diff --git a/c++/include/objmgr/impl/seq_vector_cvt_gen.hpp b/c++/include/objmgr/impl/seq_vector_cvt_gen.hpp index 46435dbc..fce3a418 100644 --- a/c++/include/objmgr/impl/seq_vector_cvt_gen.hpp +++ b/c++/include/objmgr/impl/seq_vector_cvt_gen.hpp @@ -1,6 +1,6 @@ #ifndef SEQ_VECTOR_CVT_GEN__HPP #define SEQ_VECTOR_CVT_GEN__HPP -/* $Id: seq_vector_cvt_gen.hpp 103491 2007-05-04 17:18:18Z kazimird $ +/* $Id: seq_vector_cvt_gen.hpp 514368 2016-09-21 15:22:14Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -245,9 +245,9 @@ void copy_2bit(DstIter dst, size_t count, _ASSERT(src >= srcCont.begin() && src < srcCont.end()); char c3 = *src; ++src; - char c0 = c3 >> 6; - char c1 = c3 >> 4; - char c2 = c3 >> 2; + char c0 = char(c3 >> 6); + char c1 = char(c3 >> 4); + char c2 = char(c3 >> 2); c0 &= 0x03; c1 &= 0x03; c2 &= 0x03; @@ -303,9 +303,9 @@ void copy_2bit_table(DstIter dst, size_t count, _ASSERT(src >= srcCont.begin() && src < srcCont.end()); char c3 = *src; ++src; - char c0 = c3 >> 6; - char c1 = c3 >> 4; - char c2 = c3 >> 2; + char c0 = char(c3 >> 6); + char c1 = char(c3 >> 4); + char c2 = char(c3 >> 2); c0 = table[c0 & 0x03]; c1 = table[c1 & 0x03]; *dst = c0; @@ -359,9 +359,9 @@ void copy_2bit_reverse(DstIter dst, size_t count, for ( DstIter end = dst + (count & ~3); dst != end; dst += 4 ) { _ASSERT(src > srcCont.begin() && src <= srcCont.end()); char c0 = *--src; - char c1 = c0 >> 2; - char c2 = c0 >> 4; - char c3 = c0 >> 6; + char c1 = char(c0 >> 2); + char c2 = char(c0 >> 4); + char c3 = char(c0 >> 6); c0 &= 0x03; c1 &= 0x03; c2 &= 0x03; @@ -416,9 +416,9 @@ void copy_2bit_table_reverse(DstIter dst, size_t count, for ( DstIter end = dst + (count & ~3); dst != end; dst += 4 ) { _ASSERT(src > srcCont.begin() && src <= srcCont.end()); char c0 = *--src; - char c1 = c0 >> 2; - char c2 = c0 >> 4; - char c3 = c0 >> 6; + char c1 = char(c0 >> 2); + char c2 = char(c0 >> 4); + char c3 = char(c0 >> 6); c0 = table[c0 & 0x03]; c1 = table[c1 & 0x03]; *dst = c0; diff --git a/c++/include/objmgr/impl/snp_annot_info.hpp b/c++/include/objmgr/impl/snp_annot_info.hpp index 7055bea2..690f7342 100644 --- a/c++/include/objmgr/impl/snp_annot_info.hpp +++ b/c++/include/objmgr/impl/snp_annot_info.hpp @@ -1,7 +1,7 @@ #ifndef SNP_ANNOT_INFO__HPP #define SNP_ANNOT_INFO__HPP -/* $Id: snp_annot_info.hpp 484035 2015-11-05 18:59:48Z vasilche $ +/* $Id: snp_annot_info.hpp 500967 2016-05-10 14:39:30Z vasilche $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -202,6 +202,9 @@ public: CSeq_annot& GetRemainingSeq_annot(void); void Reset(void); + bool HasLabel(size_t index) const; + string GetLabel(size_t index) const; + // filling SNP table from parser void x_AddSNP(const SSNP_Info& snp_info); void x_FinishParsing(void); @@ -425,6 +428,20 @@ size_t CSeq_annot_SNP_Info::GetIndex(const SSNP_Info& info) const } +inline +bool CSeq_annot_SNP_Info::HasLabel(size_t index) const +{ + return GetInfo(index).HasLabel(*this); +} + + +inline +string CSeq_annot_SNP_Info::GetLabel(size_t index) const +{ + return GetInfo(index).GetLabel(*this); +} + + END_SCOPE(objects) END_NCBI_SCOPE diff --git a/c++/include/objmgr/impl/snp_info.hpp b/c++/include/objmgr/impl/snp_info.hpp index 7fb0cefc..74845a2a 100644 --- a/c++/include/objmgr/impl/snp_info.hpp +++ b/c++/include/objmgr/impl/snp_info.hpp @@ -1,7 +1,7 @@ #ifndef SNP_INFO__HPP #define SNP_INFO__HPP -/* $Id: snp_info.hpp 406813 2013-07-16 15:04:34Z vasilche $ +/* $Id: snp_info.hpp 500967 2016-05-10 14:39:30Z vasilche $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -167,6 +167,7 @@ public: fQualityCodesMask = fQualityCodesStr | fQualityCodesOs }; + bool HasAlleles(void) const; size_t GetAllelesCount(void) const; TAlleleIndex GetAlleleStrIndex(size_t index) const; TExtraIndex GetExtraIndex(void) const; @@ -174,6 +175,9 @@ public: TQualityCodesIndex GetQualityCodesStrIndex(void) const; TQualityCodesIndex GetQualityCodesOsIndex(void) const; + bool HasLabel(const CSeq_annot_SNP_Info& info) const; + string GetLabel(const CSeq_annot_SNP_Info& info) const; + TSeqPos m_ToPosition; TSNPId m_SNP_Id; TFlags m_Flags; @@ -259,6 +263,13 @@ bool SSNP_Info::NotThis(const TRange& range) const } +inline +bool SSNP_Info::HasAlleles(void) const +{ + return m_AllelesIndices[0] != kNo_AlleleIndex; +} + + inline SSNP_Info::TAlleleIndex SSNP_Info::GetAlleleStrIndex(size_t index) const { @@ -267,6 +278,13 @@ SSNP_Info::TAlleleIndex SSNP_Info::GetAlleleStrIndex(size_t index) const } +inline +bool SSNP_Info::HasLabel(const CSeq_annot_SNP_Info&) const +{ + return HasAlleles(); +} + + inline SSNP_Info::TExtraIndex SSNP_Info::GetExtraIndex(void) const { diff --git a/c++/include/objmgr/impl/tse_info.hpp b/c++/include/objmgr/impl/tse_info.hpp index 7d7f1436..8cc9b820 100644 --- a/c++/include/objmgr/impl/tse_info.hpp +++ b/c++/include/objmgr/impl/tse_info.hpp @@ -1,7 +1,7 @@ #ifndef OBJECTS_OBJMGR_IMPL___TSE_INFO__HPP #define OBJECTS_OBJMGR_IMPL___TSE_INFO__HPP -/* $Id: tse_info.hpp 446824 2014-09-18 14:47:47Z vasilche $ +/* $Id: tse_info.hpp 518178 2016-11-01 11:46:07Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -371,6 +371,7 @@ public: const CTSE_Split_Info& GetSplitInfo(void) const; bool HasSplitInfo(void) const; bool x_NeedsDelayedMainChunk(void) const; + void x_LoadDelayedMainChunk(void) const; const CSeq_id_Handle& GetRequestedId(void) const; void SetRequestedId(const CSeq_id_Handle& requested_id) const; diff --git a/c++/include/objmgr/impl/tse_info_object.hpp b/c++/include/objmgr/impl/tse_info_object.hpp index 21b13833..830af921 100644 --- a/c++/include/objmgr/impl/tse_info_object.hpp +++ b/c++/include/objmgr/impl/tse_info_object.hpp @@ -1,7 +1,7 @@ #ifndef OBJECTS_OBJMGR_IMPL___TSE_INFO_OBJECT__HPP #define OBJECTS_OBJMGR_IMPL___TSE_INFO_OBJECT__HPP -/* $Id: tse_info_object.hpp 381070 2012-11-19 15:49:14Z vasilche $ +/* $Id: tse_info_object.hpp 516279 2016-10-12 13:41:47Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -130,7 +130,8 @@ public: fNeedUpdate_children_annot = fNeedUpdate_annot <IsSetProduct(); + return x_HasAnnotObjectInfo() && GetSeq_feat()->IsSetProduct(); } @@ -585,24 +596,6 @@ const CSeq_feat::TExts& CSeq_feat_Handle::GetExts(void) const } -inline -CSeqFeatData::E_Choice CSeq_feat_Handle::GetFeatType(void) const -{ - return IsTableSNP()? - CSeqFeatData::e_Imp: - x_GetAnnotObject_Info().GetFeatType(); -} - - -inline -CSeqFeatData::ESubtype CSeq_feat_Handle::GetFeatSubtype(void) const -{ - return IsTableSNP()? - CSeqFeatData::eSubtype_variation: - x_GetAnnotObject_Info().GetFeatSubtype(); -} - - ///////////////////////////////////////////////////////////////////////////// /// /// CSeq_feat_EditHandle -- @@ -801,8 +794,8 @@ class NCBI_XOBJMGR_EXPORT CSeq_annot_ftable_I { public: enum EFlags { - fIncludeTable = 1<<0, - fOnlyTable = 1<<1 + fIncludeTable = 1<<0, // include SNP table into iteration + fOnlyTable = 1<<1 // only SNP table features }; typedef int TFlags; diff --git a/c++/include/objmgr/seq_loc_mapper.hpp b/c++/include/objmgr/seq_loc_mapper.hpp index 82f4398a..93040e39 100644 --- a/c++/include/objmgr/seq_loc_mapper.hpp +++ b/c++/include/objmgr/seq_loc_mapper.hpp @@ -1,7 +1,7 @@ #ifndef SEQ_LOC_MAPPER__HPP #define SEQ_LOC_MAPPER__HPP -/* $Id: seq_loc_mapper.hpp 479439 2015-09-21 13:04:11Z grichenk $ +/* $Id: seq_loc_mapper.hpp 505837 2016-06-29 15:06:52Z grichenk $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -113,23 +113,23 @@ public: /// target one. If scope is set, synonyms are resolved for each source ID. /// Only the first row matching target ID is used, all other rows /// are considered source. - CSeq_loc_Mapper(const CSeq_align& map_align, - const CSeq_id& to_id, - CScope* scope = 0, - TMapOptions opts = 0); - CSeq_loc_Mapper(const CSeq_align& map_align, - size_t to_row, - CScope* scope = 0, - TMapOptions opts = 0); + CSeq_loc_Mapper(const CSeq_align& map_align, + const CSeq_id& to_id, + CScope* scope = 0, + CSeq_loc_Mapper_Options options = CSeq_loc_Mapper_Options()); + CSeq_loc_Mapper(const CSeq_align& map_align, + size_t to_row, + CScope* scope = 0, + CSeq_loc_Mapper_Options options = CSeq_loc_Mapper_Options()); /// Mapping between segments and the top level sequence. /// @param target_seq /// Top level bioseq /// @param direction /// Direction of mapping: up (from segments to master) or down. - CSeq_loc_Mapper(CBioseq_Handle target_seq, - ESeqMapDirection direction, - TMapOptions opts = 0); + CSeq_loc_Mapper(CBioseq_Handle target_seq, + ESeqMapDirection direction, + CSeq_loc_Mapper_Options options = CSeq_loc_Mapper_Options()); /// Mapping between segments and the top level sequence. /// @param target_seq @@ -139,10 +139,10 @@ public: /// @param selector /// Seq-map selector with additional restrictions (range, strand etc.). /// Some properties of the selector are always adjusted by the mapper. - CSeq_loc_Mapper(CBioseq_Handle target_seq, - ESeqMapDirection direction, - SSeqMapSelector selector, - TMapOptions opts = 0); + CSeq_loc_Mapper(CBioseq_Handle target_seq, + ESeqMapDirection direction, + SSeqMapSelector selector, + CSeq_loc_Mapper_Options options = CSeq_loc_Mapper_Options()); /// Mapping through a seq-map. /// @param seq_map @@ -152,11 +152,11 @@ public: /// @param top_level_id /// Explicit destination id when mapping up, may be used with /// seq-maps constructed from a seq-loc with multiple ids. - CSeq_loc_Mapper(const CSeqMap& seq_map, - ESeqMapDirection direction, - const CSeq_id* top_level_id = 0, - CScope* scope = 0, - TMapOptions opts = 0); + CSeq_loc_Mapper(const CSeqMap& seq_map, + ESeqMapDirection direction, + const CSeq_id* top_level_id = 0, + CScope* scope = 0, + CSeq_loc_Mapper_Options options = CSeq_loc_Mapper_Options()); /// Mapping through a seq-map. /// @param seq_map @@ -169,12 +169,12 @@ public: /// @param top_level_id /// Explicit destination id when mapping up, may be used with /// seq-maps constructed from a seq-loc with multiple ids. - CSeq_loc_Mapper(const CSeqMap& seq_map, - ESeqMapDirection direction, - SSeqMapSelector selector, - const CSeq_id* top_level_id = 0, - CScope* scope = 0, - TMapOptions opts = 0); + CSeq_loc_Mapper(const CSeqMap& seq_map, + ESeqMapDirection direction, + SSeqMapSelector selector, + const CSeq_id* top_level_id = 0, + CScope* scope = 0, + CSeq_loc_Mapper_Options options = CSeq_loc_Mapper_Options()); /// Mapping between segments and the top level sequence limited by depth. /// @param depth @@ -183,10 +183,10 @@ public: /// Top level bioseq /// @param direction /// Direction of mapping: up (from segments to master) or down. - CSeq_loc_Mapper(size_t depth, - const CBioseq_Handle& top_level_seq, - ESeqMapDirection direction, - TMapOptions opts = 0); + CSeq_loc_Mapper(size_t depth, + const CBioseq_Handle& top_level_seq, + ESeqMapDirection direction, + CSeq_loc_Mapper_Options options = CSeq_loc_Mapper_Options()); /// Depth-limited mapping through a seq-map. /// @param depth @@ -198,12 +198,12 @@ public: /// @param top_level_id /// Explicit destination id when mapping up, may be used with /// seq-maps constructed from a seq-loc with multiple ids. - CSeq_loc_Mapper(size_t depth, - const CSeqMap& top_level_seq, - ESeqMapDirection direction, - const CSeq_id* top_level_id = 0, - CScope* scope = 0, - TMapOptions opts = 0); + CSeq_loc_Mapper(size_t depth, + const CSeqMap& top_level_seq, + ESeqMapDirection direction, + const CSeq_id* top_level_id = 0, + CScope* scope = 0, + CSeq_loc_Mapper_Options options = CSeq_loc_Mapper_Options()); /// Destination of seq-id mapping through a GC-Assembly. enum EGCAssemblyAlias { @@ -231,12 +231,12 @@ public: CScope* scope = 0, EScopeFlag scope_flag = eCopyScope); /// Initialize the mapper to map through deltas from a GC-Assembly. - CSeq_loc_Mapper(const CGC_Assembly& gc_assembly, - ESeqMapDirection direction, - SSeqMapSelector selector, - CScope* scope = 0, - EScopeFlag scope_flag = eCopyScope, - TMapOptions opts = 0); + CSeq_loc_Mapper(const CGC_Assembly& gc_assembly, + ESeqMapDirection direction, + SSeqMapSelector selector, + CScope* scope = 0, + EScopeFlag scope_flag = eCopyScope, + CSeq_loc_Mapper_Options options = CSeq_loc_Mapper_Options()); ~CSeq_loc_Mapper(void); diff --git a/c++/include/objmgr/seq_map.hpp b/c++/include/objmgr/seq_map.hpp index 822e04cf..d9ccc0b4 100644 --- a/c++/include/objmgr/seq_map.hpp +++ b/c++/include/objmgr/seq_map.hpp @@ -1,7 +1,7 @@ #ifndef OBJECTS_OBJMGR___SEQ_MAP__HPP #define OBJECTS_OBJMGR___SEQ_MAP__HPP -/* $Id: seq_map.hpp 499042 2016-04-21 17:39:04Z ivanov $ +/* $Id: seq_map.hpp 496211 2016-03-24 15:33:11Z vasilche $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/objmgr/seq_map_ci.hpp b/c++/include/objmgr/seq_map_ci.hpp index 7844834a..ffcb3f64 100644 --- a/c++/include/objmgr/seq_map_ci.hpp +++ b/c++/include/objmgr/seq_map_ci.hpp @@ -1,7 +1,7 @@ #ifndef OBJECTS_OBJMGR___SEQ_MAP_CI__HPP #define OBJECTS_OBJMGR___SEQ_MAP_CI__HPP -/* $Id: seq_map_ci.hpp 499042 2016-04-21 17:39:04Z ivanov $ +/* $Id: seq_map_ci.hpp 496211 2016-03-24 15:33:11Z vasilche $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/objmgr/seq_vector_ci.hpp b/c++/include/objmgr/seq_vector_ci.hpp index 91ad057b..cc9b4fc6 100644 --- a/c++/include/objmgr/seq_vector_ci.hpp +++ b/c++/include/objmgr/seq_vector_ci.hpp @@ -1,7 +1,7 @@ #ifndef SEQ_VECTOR_CI__HPP #define SEQ_VECTOR_CI__HPP -/* $Id: seq_vector_ci.hpp 414728 2013-09-26 15:15:41Z vasilche $ +/* $Id: seq_vector_ci.hpp 520631 2016-11-30 13:12:58Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -133,7 +133,7 @@ public: void GetSeqData(string& buffer, TSeqPos count); /// Get number of chars from current position to the current buffer end - size_t GetBufferSize(void) const; + TSeqPos GetBufferSize(void) const; /// Get pointer to current char in the buffer const char* GetBufferPtr(void) const; /// Get pointer to current position+size. @@ -201,6 +201,8 @@ public: DECLARE_OPERATOR_BOOL(IsValid()); + const CSeqMap_CI& GetCurrentSeqMap_CI() const; + /// true if current position of CSeqVector_CI is inside of sequence gap bool IsInGap(void) const; /// returns gap Seq-data object ref @@ -473,6 +475,13 @@ CSeqVector_CI::TResidue CSeqVector_CI::operator*(void) const } +inline +const CSeqMap_CI& CSeqVector_CI::GetCurrentSeqMap_CI(void) const +{ + return m_Seg; +} + + inline bool CSeqVector_CI::IsInGap(void) const { @@ -517,9 +526,9 @@ void CSeqVector_CI::GetSeqData(TSeqPos start, TSeqPos stop, string& buffer) inline -size_t CSeqVector_CI::GetBufferSize(void) const +TSeqPos CSeqVector_CI::GetBufferSize(void) const { - return m_CacheEnd - m_Cache; + return TSeqPos(m_CacheEnd - m_Cache); } diff --git a/c++/include/objmgr/split/size.hpp b/c++/include/objmgr/split/size.hpp index 8941f5e7..24c33562 100644 --- a/c++/include/objmgr/split/size.hpp +++ b/c++/include/objmgr/split/size.hpp @@ -1,7 +1,7 @@ #ifndef NCBI_OBJMGR_SPLIT_SIZE__HPP #define NCBI_OBJMGR_SPLIT_SIZE__HPP -/* $Id: size.hpp 160976 2009-05-21 15:38:31Z vasilche $ +/* $Id: size.hpp 514368 2016-09-21 15:22:14Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -96,7 +96,7 @@ public: } double GetRatio(void) const { - return double(m_ZipSize)/m_AsnSize; + return (double)m_ZipSize/(double)m_AsnSize; } CNcbiOstream& Print(CNcbiOstream& out) const; diff --git a/c++/include/objmgr/util/create_defline.hpp b/c++/include/objmgr/util/create_defline.hpp index 2df694f5..b5137042 100644 --- a/c++/include/objmgr/util/create_defline.hpp +++ b/c++/include/objmgr/util/create_defline.hpp @@ -276,6 +276,9 @@ private: bool m_IsUnverified; CTempString m_TargetedLocus; + /// comment fields + bool m_IsPseudogene; + /// map fields string m_rEnzyme; diff --git a/c++/include/objmgr/util/feature.hpp b/c++/include/objmgr/util/feature.hpp index 6ac0749c..046714aa 100644 --- a/c++/include/objmgr/util/feature.hpp +++ b/c++/include/objmgr/util/feature.hpp @@ -1,7 +1,7 @@ #ifndef FEAT__HPP #define FEAT__HPP -/* $Id: feature.hpp 499447 2016-04-26 14:17:39Z ivanov $ +/* $Id: feature.hpp 497406 2016-04-06 15:30:54Z ludwigf $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -69,10 +69,11 @@ BEGIN_SCOPE(feature) */ enum FFeatLabelFlags { - fFGL_Type = 1 << 1, ///< Always include the feature's type. - fFGL_Content = 1 << 2, ///< Include its content if there is any. - fFGL_Both = fFGL_Type | fFGL_Content, - fFGL_NoComments = 1 << 3 ///< Leave out comments, even as fallbacks. + fFGL_Type = 1 << 1, ///< Always include the feature's type. + fFGL_Content = 1 << 2, ///< Include its content if there is any. + fFGL_Both = fFGL_Type | fFGL_Content, + fFGL_NoComments = 1 << 3, ///< Leave out comments, even as fallbacks. + fFGL_NoQualifiers = 1 << 4 ///< Leave out qualifiers. }; typedef int TFeatLabelFlags; ///< binary OR of FFeatLabelFlags diff --git a/c++/include/objmgr/util/obj_sniff.hpp b/c++/include/objmgr/util/obj_sniff.hpp index 237317e8..6f1cbfa8 100644 --- a/c++/include/objmgr/util/obj_sniff.hpp +++ b/c++/include/objmgr/util/obj_sniff.hpp @@ -1,7 +1,7 @@ #ifndef OBJ_SNIFF__HPP #define OBJ_SNIFF__HPP -/* $Id: obj_sniff.hpp 462343 2015-03-18 12:44:25Z vasilche $ +/* $Id: obj_sniff.hpp 518485 2016-11-03 16:05:20Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -162,9 +162,26 @@ public: bool GetDiscardObjectInfo() const { return m_DiscardObjInfo; } + /// Report syntax errors to client (as an exception) + /// + /// In case Sniffer has enough information about expected data type + /// but the data has syntax error, the read attempt fails and the Sniffer + /// can either hide the error reporting it as an unrecognized type, + /// or rethrow the exception to be caught by client for further analysis. + /// + /// @param report + /// Rethrow serialization exceptions + void SetReportDataErrors(bool report = true) { + m_ReportErrors = report; + } + bool GetReportDataErrors(void) const { + return m_ReportErrors; + } + protected: void ProbeText(CObjectIStream& input); void ProbeASN1_Bin(CObjectIStream& input); + void ProbeAny(CObjectIStream& input); protected: TObjectStack m_CallStack; @@ -172,7 +189,7 @@ protected: friend class COffsetReadHook; private: - void x_ReadObject(CObjectIStream& input, + bool x_ReadObject(CObjectIStream& input, CObjectTypeInfo object_info); bool x_TryReadObject(CObjectIStream& input, CObjectTypeInfo object_info); @@ -190,6 +207,8 @@ private: bool m_DiscardCurrObj; /// Flag indicates that object info should be discarded bool m_DiscardObjInfo; + /// Report data errors + bool m_ReportErrors; }; diff --git a/c++/include/objmgr/util/seq_loc_util.hpp b/c++/include/objmgr/util/seq_loc_util.hpp index f6912a6b..311f9670 100644 --- a/c++/include/objmgr/util/seq_loc_util.hpp +++ b/c++/include/objmgr/util/seq_loc_util.hpp @@ -1,7 +1,7 @@ #ifndef SEQ_LOC_UTIL__HPP #define SEQ_LOC_UTIL__HPP -/* $Id: seq_loc_util.hpp 451986 2014-11-13 20:13:31Z grichenk $ +/* $Id: seq_loc_util.hpp 500277 2016-05-03 16:55:57Z grichenk $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -300,7 +300,7 @@ enum EOverlapFlags { fOverlap_IgnoreTopology = 1 << 2, ///< Ignore sequence topology (circularity) fOverlap_Default = 0 ///< Enable multi-id, multi-strand, check topology }; - +typedef int TOverlapFlags; /// Updated version of TestForOverlap64(). Allows more control over /// handling multi-id/multi-strand bioseqs. @@ -311,7 +311,7 @@ Int8 TestForOverlapEx(const CSeq_loc& loc1, const CSeq_loc& loc2, EOverlapType type, CScope* scope = 0, - EOverlapFlags flags = fOverlap_Default); + TOverlapFlags flags = fOverlap_Default); /// Calls TestForOverlap64() and if the result is greater than kMax_Int /// truncates it to kMax_Int. To get the exact value use TestForOverlap64(). diff --git a/c++/include/objmgr/util/sequence.hpp b/c++/include/objmgr/util/sequence.hpp index f94ed775..d9213f7a 100644 --- a/c++/include/objmgr/util/sequence.hpp +++ b/c++/include/objmgr/util/sequence.hpp @@ -1,7 +1,7 @@ #ifndef SEQUENCE__HPP #define SEQUENCE__HPP -/* $Id: sequence.hpp 499692 2016-04-27 17:18:50Z ivanov $ +/* $Id: sequence.hpp 520815 2016-12-01 18:50:10Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -584,6 +584,22 @@ CConstRef GetOverlappingGene( ETransSplicing eTransSplicing = eTransSplicing_Auto); +/// Finds gene for feature, but obeys SeqFeatXref directives +NCBI_XOBJUTIL_EXPORT +CConstRef GetGeneForFeature(const CSeq_feat& feat, CScope& scope); + +/// Determines whether given feature is pseudo, using gene associated with feature +/// if necessary +/// Checks to see if a feature is pseudo. Looks for pseudo flag set on feature, +/// looks for pseudogene qualifier on feature, performs same checks for gene +/// associated with feature +/// @param feat Seq-feat to check +/// @param scope CScope to use when looking for associated gene +/// @return Boolean return value indicates whether any of the "pseudo" markers are found +NCBI_XOBJUTIL_EXPORT +bool IsPseudo(const CSeq_feat& feat, CScope& scope); + + NCBI_XOBJUTIL_EXPORT CConstRef GetOverlappingmRNA(const CSeq_loc& loc, CScope& scope); @@ -726,19 +742,20 @@ END_SCOPE(sequence) class NCBI_XOBJUTIL_EXPORT CFastaOstream { public: enum EFlags { - fAssembleParts = 0x0001, ///< assemble FAR delta sequences; on by dflt - fInstantiateGaps = 0x0002, ///< honor specifed gap mode; on by default - fSuppressRange = 0x0004, ///< never include location details in defline - fReverseStrand = 0x0008, ///< flip the (implicit) location - fKeepGTSigns = 0x0010, ///< don't convert '>' to '_' in title - fMapMasksUp = 0x0020, ///< honor masks specified at a lower level - fMapMasksDown = 0x0040, ///< honor masks specified at a higher level - fNoExpensiveOps = 0x0080, ///< don't try too hard to find titles - fShowModifiers = 0x0100, ///< show key-value pair modifiers (e.g. "[organism=Homo sapiens]") - fNoDupCheck = 0x0200, ///< skip check for duplicate sequence IDs - fShowGapModifiers = 0x0400, ///< show gap key-value pair modifiers (e.g. "[linkage-evidence=map;strobe]"). Only works if gap mode is eGM_count. - fKeepUnknGapNomLen = 0x0800, ///< Keep unknown gap's nominal length. That is, when a gap has an unknown length but nominal length, use that instead of just making it 100. - fShowGapsOfSizeZero = 0x1000, ///< Use this to show gaps of size zero as a lone hyphen at the end of a line. + fAssembleParts = 1 << 0, ///< assemble FAR delta sequences; on by dflt + fInstantiateGaps = 1 << 1, ///< honor specifed gap mode; on by default + fSuppressRange = 1 << 2, ///< never include location details in defline + fReverseStrand = 1 << 3, ///< flip the (implicit) location + fKeepGTSigns = 1 << 4, ///< don't convert '>' to '_' in title + fMapMasksUp = 1 << 5, ///< honor masks specified at a lower level + fMapMasksDown = 1 << 6, ///< honor masks specified at a higher level + fNoExpensiveOps = 1 << 7, ///< don't try too hard to find titles + fShowModifiers = 1 << 8, ///< show key-value pair modifiers (e.g. "[organism=Homo sapiens]") + fNoDupCheck = 1 << 9, ///< skip check for duplicate sequence IDs + fShowGapModifiers = 1 << 10, ///< show gap key-value pair modifiers (e.g. "[linkage-evidence=map;strobe]"). Only works if gap mode is eGM_count. + fKeepUnknGapNomLen = 1 << 11, ///< Keep unknown gap's nominal length. That is, when a gap has an unknown length but nominal length, use that instead of just making it 100. + fShowGapsOfSizeZero = 1 << 12, ///< Use this to show gaps of size zero as a lone hyphen at the end of a line. + fEnableGI = 1 << 13, ///< Use this flag to enable GI output in the defline // historically misnamed as eFlagName eAssembleParts = fAssembleParts, eInstantiateGaps = fInstantiateGaps @@ -844,6 +861,7 @@ protected: virtual void x_WriteSeqIds ( const CBioseq& bioseq, const CSeq_loc* location); + virtual void x_WriteAsFasta ( const CBioseq& bioseq ); virtual void x_WriteModifiers ( const CBioseq_Handle & handle ); virtual void x_WriteSeqTitle ( const CBioseq& bioseq, CScope* scope, diff --git a/c++/include/objtools/align_format/align_format_util.hpp b/c++/include/objtools/align_format/align_format_util.hpp index e58e7e36..91aa89a9 100644 --- a/c++/include/objtools/align_format/align_format_util.hpp +++ b/c++/include/objtools/align_format/align_format_util.hpp @@ -1,4 +1,4 @@ -/* $Id: align_format_util.hpp 488861 2016-01-06 15:45:07Z fongah2 $ +/* $Id: align_format_util.hpp 520427 2016-11-28 18:24:56Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -63,9 +63,10 @@ BEGIN_SCOPE(align_format) ///class info static const char kClassInfo[] = "class=\"info\""; +static const char kDefaultProtocol[] = "https:"; ///entrez // .ncbirc alias: ENTREZ -static const char kEntrezUrl[] = "\" <@cssInf@>href=\"//www.ncbi.nlm.nih.gov/<@db@>/<@gi@>?report=genbank&log$=<@log@>&blast_rank=<@blast_rank@>&RID=<@rid@>\" <@target@>>"; +static const char kEntrezUrl[] = "\" <@cssInf@>href=\"<@protocol@>//www.ncbi.nlm.nih.gov/<@db@>/<@gi@>?report=genbank&log$=<@log@>&blast_rank=<@blast_rank@>&RID=<@rid@>\" <@target@>>"; //.ncbirc alias: ENTREZ_TM static const char kEntrezTMUrl[] = "//www.ncbi.nlm.nih.gov/<@db@>/<@gi@>?report=genbank&log$=<@log@>&blast_rank=<@blast_rank@>&RID=<@rid@>"; @@ -466,6 +467,16 @@ public: eDbTypeNotSet }; + //Formatting flag for adding spaces + enum SpacesFormatingFlag { + eSpacePosToCenter = (1 << 0), ///place the param in the center of the string + eSpacePosAtLineStart = (1 << 1), ///add spaces at the begining of the string + eSpacePosAtLineEnd = (1 << 2), ///add spaces at the end of the string + eAddEOLAtLineStart = (1 << 3), ///add EOL at the beginning of the string + eAddEOLAtLineEnd = (1 << 4) ///add EOL at the end of the string + }; + + ///Output blast errors ///@param error_return: list of errors to report ///@param error_post: post to stderr or not @@ -634,6 +645,7 @@ public: int& comp_adj_method); + static void GetUseThisSequence(const objects::CSeq_align& aln,list& use_this_gi); ///Add the specified white space ///@param out: ostream to add white space ///@param number: the number of white spaces desired @@ -1092,7 +1104,29 @@ public: /// ///<@tmplParamName@> is replaced by templParamVal static string MapTemplate(string inpString,string tmplParamName,string templParamVal); - + + ///Replace template tags by real data and calculate and add spaces dependent on maxParamLength and spacesFormatFlag + ///@param inpString: string containing template data + ///@param tmplParamName:string with template tag name + ///@param templParamVal: string value that replaces template + ///@param maxParamLength: unsigned int maxParamLength + ///@param spacesFormatFlag: int formatting flag + ///@return:string containing template data replaced by real data + /// + ///<@tmplParamName@> is replaced by templParamVal + static string MapSpaceTemplate(string inpString,string tmplParamName,string templParamVal, unsigned int maxParamLength, int spacesFormatFlag = eSpacePosAtLineEnd); + + ///Calculate the number of spaces and add them to paramVal + ///@param string: input parameter value + ///@param string: max length for the string that holds parameter + ///@param int: additional fomatting after adding spaces + ///@param string: the position of spaces and additional formatting + ///@return:string containing paramVal and spaces place appropriately + static string AddSpaces(string paramVal, unsigned int maxParamLength, int spacesFormatFlag = eSpacePosToCenter); + + + static string GetProtocol(void); + ///Create URL for seqid ///@param seqUrlInfo: struct SSeqURLInfo containing data for URL construction ///@param id: seqid CSeq_id @@ -1189,6 +1223,18 @@ public: static map < string, CRef > HspListToHitMap(vector seqIdList, const objects::CSeq_align_set& source); + ///Scan the the list of blast deflines and find seqID to be use in display + ///@param handle: CBioseq_Handle [in] + ///@param aln_id: CSeq_id object for alignment seq [in] + ///@param use_this_gi: list list of gis to use [in] + ///@param gi: gi to be used for display if exists or 0 + ///@param taxid: taxid to be used for display if exists or 0 + ///@return: CSeq_id object to be used for display + static CRef GetDisplayIds(const objects::CBioseq_Handle& handle, + const objects::CSeq_id& aln_id, + list& use_this_gi, + TGi& gi, + int& taxid); ///Scan the the list of blast deflines and find seqID to be use in display ///@param handle: CBioseq_Handle [in] ///@param aln_id: CSeq_id object for alignment seq [in] @@ -1229,6 +1275,9 @@ public: static string GetTitle(const objects::CBioseq_Handle & bh); + /// Get sequence id with no database source (bare accession) + static string GetBareId(const objects::CSeq_id& id); + protected: ///Wrap a string to specified length. If break happens to be in diff --git a/c++/include/objtools/align_format/format_flags.hpp b/c++/include/objtools/align_format/format_flags.hpp index c9a3ae2e..85773fb1 100644 --- a/c++/include/objtools/align_format/format_flags.hpp +++ b/c++/include/objtools/align_format/format_flags.hpp @@ -1,4 +1,4 @@ -/* $Id: format_flags.hpp 495725 2016-03-21 14:24:26Z ivanov $ +/* $Id: format_flags.hpp 518046 2016-10-31 14:58:35Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -160,7 +160,8 @@ NCBI_ALIGN_FORMAT_EXPORT extern const size_t kNumTabularOutputFormatSpecifiers; NCBI_ALIGN_FORMAT_EXPORT string DescribeTabularOutputFormatSpecifiers(bool is_igblast=false); enum ESAMField { - eSAM_SeqData = 0 ///< Include seq data + eSAM_SeqData = 0, ///< Include seq data + eSAM_SubjAsRefSeq ///< Subject as reference seqs }; struct SSAMFormatSpec { diff --git a/c++/include/objtools/align_format/showalign.hpp b/c++/include/objtools/align_format/showalign.hpp index b72dea89..f8ca315a 100644 --- a/c++/include/objtools/align_format/showalign.hpp +++ b/c++/include/objtools/align_format/showalign.hpp @@ -1,4 +1,4 @@ -/* $Id: showalign.hpp 403059 2013-06-12 14:34:48Z zaretska $ +/* $Id: showalign.hpp 513849 2016-09-15 17:36:45Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -35,7 +35,7 @@ #define OBJTOOLS_ALIGN_FORMAT___SHOWALIGN_HPP #include -#include +#include #include #include @@ -255,7 +255,7 @@ class NCBI_ALIGN_FORMAT_EXPORT CDisplaySeqalign { } //Display pariwise seqalign for the set of seq IDS (for future use) - void DisplayPairwiseSeqalign(CNcbiOstream& out,hash_set selectedIDs); + void DisplayPairwiseSeqalign(CNcbiOstream& out,unordered_set selectedIDs); //Data representing templates for defline display struct SAlignTemplates { string alignHeaderTmpl; ///< Template for displaying header,deflines and gene info - BLAST_ALIGN_HEADER @@ -416,6 +416,9 @@ class NCBI_ALIGN_FORMAT_EXPORT CDisplaySeqalign { m_PreComputedResID = preComputedResID; } + /// Sets usage of long sequence ids (database|accession) + void UseLongSequenceIds(void) {m_UseLongSeqIds = true;} + /// static functions ///Need to call this if the seqalign is stdseg or dendiag for ungapped ///blast alignment display as each stdseg ro dendiag is a distinct @@ -670,6 +673,9 @@ protected: ///result position index for multiple query case int m_ResultPositionIndex; + /// print long sequence ids (with gi and accession with database source) + bool m_UseLongSeqIds; + string x_PrintDynamicFeatures(void); ///Display the current alnvec ///@param out: stream for display diff --git a/c++/include/objtools/align_format/showdefline.hpp b/c++/include/objtools/align_format/showdefline.hpp index 145a1614..4460efd4 100644 --- a/c++/include/objtools/align_format/showdefline.hpp +++ b/c++/include/objtools/align_format/showdefline.hpp @@ -1,4 +1,4 @@ -/* $Id: showdefline.hpp 436590 2014-05-29 15:00:05Z zaretska $ +/* $Id: showdefline.hpp 513849 2016-09-15 17:36:45Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -93,7 +93,8 @@ public: eNoShowHeader = (1 << 6), //defline annotation at the top eNewTargetWindow = (1 << 7), //open url link in a new window eShowNewSeqGif = (1 << 8), //show new sequence gif image - eShowPercentIdent = (1 << 9) //show percent identity column + eShowPercentIdent = (1 << 9), //show percent identity column + eLongSeqId = (1 << 10) //print long sequences id (with bars) }; ///Data Representing each defline @@ -108,7 +109,8 @@ public: string score_url; //score url (quick jump to alignment) bool is_new; //is this sequence new (for psiblast)? bool was_checked; //was this sequence checked before? - string fullDefline; //defline, containing all seq defines (PIG for example) + string fullDefline; //defline, containing all seq defines (PIG for example) + int taxid; }; //Data representing templates for defline display @@ -123,6 +125,17 @@ public: bool advancedView; }; + //data represnting info to record in applog amd metadata + struct SAppLogInfo { + int topMatchesNum; + int currInd; + vector deflIdVec; + vector taxidVec; + vector queryCoverageVec; + vector percentIdentityVec; + }; + + ///options per DisplayOption ///@param option: input option using bit numbers defined in DisplayOption /// @@ -258,6 +271,13 @@ public: void SetDeflineTemplates (SDeflineTemplates *deflineTemplates) { m_DeflineTemplates = deflineTemplates; } + + ///Set this to record datda in applog + ///Param appLogInfo: struct containg applog setup info + /// + void SetApplog(SAppLogInfo *appLogInfo) { + m_AppLogInfo = appLogInfo; + } ///Sets CDD precomputed results ID /// @param string containing seq id used in contsructing URL to CDART @@ -359,7 +379,7 @@ protected: CRange subjRange; //subject sequence range bool flip; //indicates opposite strands in the first seq align }; - + ///Seqalign CConstRef m_AlnSetRef; @@ -461,6 +481,10 @@ protected: ///result position index for multiple query case int m_PositionIndex; + //info to record in applog amd metadata + SAppLogInfo *m_AppLogInfo; + + ///Internal function to return score info ///@param aln seq-align we are working with [in] ///@param blast_rank ordinal nubmer of defline [in] diff --git a/c++/include/objtools/align_format/tabular.hpp b/c++/include/objtools/align_format/tabular.hpp index 70bf4bbe..d69f1601 100644 --- a/c++/include/objtools/align_format/tabular.hpp +++ b/c++/include/objtools/align_format/tabular.hpp @@ -1,4 +1,4 @@ -/* $Id: tabular.hpp 495725 2016-03-21 14:24:26Z ivanov $ +/* $Id: tabular.hpp 503717 2016-06-07 17:51:40Z jianye $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -617,6 +617,7 @@ public: m_IgDomains.push_back(domain); }; + /// Set gene info void SetVGene(const string &id, int s, int e) { m_VGene.Set(id, s,e); @@ -636,6 +637,30 @@ public: void SetIgAnnotation(const CRef &annot, const CConstRef &ig_opts); + ///Getter + const void GetIgInfo (string& v, + string& d, + string& j, + string& master_chain_to_show, + string& cdr3_nuc, + string& cdr3_aa, + string& productive) const { + v = m_VGene.sid; + d = m_DGene.sid; + j = m_JGene.sid; + master_chain_to_show = m_MasterChainTypeToShow; + cdr3_nuc = m_Cdr3Seq; + cdr3_aa = m_Cdr3SeqTrans; + productive = m_OtherInfo[4]; + } + + ///Get Ig domain + const vector& GetIgDomains() const { + + return m_IgDomains; + } + + protected: void x_ResetIgFields(); void x_PrintIgGenes(bool isHtml=false, const string& header="# ") const; @@ -654,12 +679,16 @@ private: SIgGene m_VGene; SIgGene m_DGene; SIgGene m_JGene; - vector m_IgDomains; + vector m_IgDomains; + // index 4, productive/non-productive + // index 3, stop codon or not + vector m_OtherInfo; int m_Cdr3Start; int m_Cdr3End; string m_Cdr3Seq; string m_Cdr3SeqTrans; + }; END_SCOPE(align_format) diff --git a/c++/include/objtools/align_format/taxFormat.hpp b/c++/include/objtools/align_format/taxFormat.hpp index 595bf9b1..ab830627 100644 --- a/c++/include/objtools/align_format/taxFormat.hpp +++ b/c++/include/objtools/align_format/taxFormat.hpp @@ -1,4 +1,4 @@ -/* $Id: taxFormat.hpp 486926 2015-12-11 17:32:50Z zaretska $ +/* $Id: taxFormat.hpp 506577 2016-07-08 17:18:41Z zaretska $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -63,29 +63,47 @@ BEGIN_SCOPE(align_format) * @endcode */ - const string kTaxBrowserURL = "//www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi"; + const string kTaxBrowserURL = "<@protocol@>//www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi"; const string kBlastNameLink = "?id=<@bl_taxid@>\" target=\"lnktx<@rid@>\" title=\"Show taxonomy info for <@blast_name@> (taxid <@bl_taxid@>)\"><@blast_name@>"; - const string kOrgReportTable = "<@table_rows@>

Organism Report

AccessionDescrScoreE-value
<@taxidToSeqsMap@>"; - const string kOrgReportOrganismHeader = "?id=<@taxid@>\" name=\"<@taxid@>\" title=\"Show taxonomy info for <@scientific_name@> (taxid <@taxid@>)\" target=\"lnktx<@rid@>\"><@scientific_name@>[<@blast_name_link@>] taxid <@taxid@>"; - const string kOrgReportOrganismHeaderNoTaxConnect = "?id=<@taxid@>\" name=\"<@taxid@>\" title=\"Show taxonomy info for <@scientific_name@> (taxid <@taxid@>)\" target=\"lnktx<@rid@>\"><@scientific_name@>[<@blast_name@>]"; + const string kOrgReportTable = "<@table_rows@>

Organism Report

AccessionDescrScoreE-value
<@taxidToSeqsMap@>"; + const string kOrgReportOrganismHeader = "
?id=<@taxid@>\" name=\"<@taxid@>\" title=\"Show taxonomy info for <@scientific_name@> (taxid <@taxid@>)\" target=\"lnktx<@rid@>\"><@scientific_name@> <@common_name@> [<@blast_name_link@>] taxid <@taxid@>"; + const string kOrgReportOrganismHeaderNoTaxConnect = "?id=<@taxid@>\" name=\"<@taxid@>\" title=\"Show taxonomy info for <@scientific_name@> (taxid <@taxid@>)\" target=\"lnktx<@rid@>\"><@scientific_name@> <@common_name@> [<@blast_name@>]"; const string kOrgReportTableHeader = "AccessionDescriptionScoreE-value"; - const string kOrgReportTableRow = "\" target=\"lnktx<@rid@>\" href=\"//www.ncbi.nlm.nih.gov/protein/<@gi@>?report=fwwwtax&log$=taxrep&RID=<@rid@>\"><@acc@><@descr_abbr@><@score@><@evalue@>"; + const string kOrgReportTableRow = "\" target=\"lnktx<@rid@>\" href=\"<@protocol@>//www.ncbi.nlm.nih.gov/protein/<@gi@>?report=fwwwtax&log$=taxrep&RID=<@rid@>\"><@acc@><@descr_abbr@><@score@><@evalue@>"; const string kTaxIdToSeqsMap = "\" value=\"<@giList@>\" />"; - const string kLineageReportTable = "

Linage Report

<@table_rows@>
"; + const string kLineageReportTable = "

Linage Report

<@table_rows@>
"; const string kLineageReportTableHeader = "OrganismBlast NameScoreNumber of HitsDescription"; const string kLineageReportOrganismHeader = "<@depth@>?id=<@taxid@>\" title=\"Show taxonomy info for <@scientific_name@> (taxid <@taxid@>)\" target=\"lnktx<@rid@>\"><@scientific_name@><@blast_name_link@>"; - const string kLineageReportTableRow = "<@depth@>?id=<@taxid@>\" title=\"Show taxonomy info for <@scientific_name@> (taxid <@taxid@>)\" target=\"lnktx<@rid@>\"><@scientific_name@><@blast_name_link@><@score@>\" title=\"Show organism report for <@scientific_name@>\"><@numhits@> <@descr_abbr@>\" target=\"lnktx<@rid@>\" href=\"//www.ncbi.nlm.nih.gov/protein/<@gi@>?report=genbank&log$=taxrep&RID=<@rid@>\"><@descr_abbr@>"; + const string kLineageReportTableRow = "<@depth@>?id=<@taxid@>\" title=\"Show taxonomy info for <@scientific_name@> (taxid <@taxid@>)\" target=\"lnktx<@rid@>\"><@scientific_name@><@blast_name_link@><@score@>\" title=\"Show organism report for <@scientific_name@>\"><@numhits@> <@descr_abbr@>\" target=\"lnktx<@rid@>\" href=\"<@protocol@>//www.ncbi.nlm.nih.gov/protein/<@gi@>?report=genbank&log$=taxrep&RID=<@rid@>\"><@descr_abbr@>"; - const string kTaxonomyReportTable = "

Taxonomy Report

<@table_rows@>
"; + const string kTaxonomyReportTable = "

Taxonomy Report

<@table_rows@>
"; const string kTaxonomyReportTableHeader = "TaxonomyNumber of hitsNumber of organismsDescription"; const string kTaxonomyReportOrganismHeader = "<@depth@>?id=<@taxid@>\" title=\"Show taxonomy info for <@scientific_name@> (taxid <@taxid@>)\" target=\"lnktx<@rid@>\"><@scientific_name@><@numhits@><@numOrgs@><@descr_abbr@>"; const string kTaxonomyReportTableRow = "<@depth@>?id=<@taxid@>\" title=\"Show taxonomy info for <@scientific_name@> (taxid <@taxid@>)\" target=\"lnktx<@rid@>\"><@scientific_name@><@numhits@><@numOrgs@><@descr_abbr@>"; + const string kOrgReportTxtTable = "<@org_report_caption@>\n<@acc_hd@><@descr_hd@><@score_hd@><@evalue_hd@>\n<@table_rows@>"; + const string kOrgReportTxtOrganismHeader = "<@scientific_name@> <@common_name@> [<@blast_name_link@>] taxid <@taxid@>"; + const string kOrgReportTxtOrganismHeaderNoTaxConnect = "<@scientific_name@> <@common_name@> [<@blast_name@>]"; + const string kOrgReportTxtTableHeader = " <@acc_hd@><@descr_hd@><@score_hd@><@evalue_hd@>\n"; + const string kOrgReportTxtTableRow = " <@acc@><@descr_text@><@score@><@evalue@>\n"; + + + const string kOrgReportTxtTableCaption = "Organism Report"; + const string kOrgAccTxtTableHeader = "Accession"; + const string kOrgDescrTxtTableHeader = "Description"; + const string kOrgScoreTxtTableHeader = "Score"; + const string kOrgEValueTxtTableHeader = "E-value"; + + const unsigned int kMinLineLength = 100; //used for text output + + + + class NCBI_ALIGN_FORMAT_EXPORT CTaxFormat { @@ -96,12 +114,22 @@ class NCBI_ALIGN_FORMAT_EXPORT CTaxFormat { ///@param seqalign: seqalign used to display taxonomy info ///@param scope: scope to fetch your sequence ///@param connectToTaxServe: default true indicates to connect to Tax server + ///@param lineLength: lineLength for text formatting + ///@param displayOption: displayOption HTML or text formatting CTaxFormat(const objects::CSeq_align_set & seqalign, objects::CScope & scope, - bool connectToTaxServer = true); + unsigned int displayOption = eHtml, + bool connectToTaxServer = true, + unsigned int lineLength = 100); + /// Destructor - ~CTaxFormat(); + ~CTaxFormat(); + + enum eDisplayOption { + eHtml, + eText + }; ///Displays Organism Report ///@param out: stream for display @@ -124,11 +152,12 @@ class NCBI_ALIGN_FORMAT_EXPORT CTaxFormat { CRef seqID; ///< seqID used in defline string label; ///< sequence label string title; ///< sequnce title - double bit_score; ///< score - double evalue; ///< evalue + string bit_score; ///< score + string evalue; ///< evalue TGi displGi; /// m_TreeIterator; + + + //Text formatting + unsigned int m_MaxAccLength; + unsigned int m_MaxDescrLength; + unsigned int m_MaxScoreLength; + unsigned int m_MaxEvalLength; + + unsigned int m_LineLength; + + + string m_Protocol; ///< protocol, default https otherwise get from .ncbirc CTaxFormat::SSeqInfo *x_FillTaxDispParams(const CRef< objects::CBlast_def_line > &bdl, const objects::CBioseq_Handle& bsp_handle, @@ -284,6 +329,7 @@ protected: string x_MapSeqTemplate(string seqTemplate, SSeqInfo *seqInfo); string x_MapSeqTemplate(string seqTemplate, STaxInfo &taxInfo); string x_MapTaxInfoTemplate(string tableRowTemplate,STaxInfo &taxInfo,unsigned int depth = 0); + void x_InitTextFormatInfo(CTaxFormat::SSeqInfo *seqInfo); void x_PrintTaxInfo(vector taxids, string title); void x_PrintLineage(void); diff --git a/c++/include/objtools/alnmgr/sparse_aln.hpp b/c++/include/objtools/alnmgr/sparse_aln.hpp index 79d19040..0f57ed21 100644 --- a/c++/include/objtools/alnmgr/sparse_aln.hpp +++ b/c++/include/objtools/alnmgr/sparse_aln.hpp @@ -1,6 +1,6 @@ #ifndef OBJTOOLS_ALNMGR___SPARSE_ALN__HPP #define OBJTOOLS_ALNMGR___SPARSE_ALN__HPP -/* $Id: sparse_aln.hpp 498721 2016-04-19 13:29:11Z ivanov $ +/* $Id: sparse_aln.hpp 519681 2016-11-17 15:42:28Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -237,10 +237,24 @@ public: return aln_pos/GetBaseWidth(row); } + /// For protein sequences get frame for the specified coordinated. + /// For genomic sequences always returns 0. + int AlnPosToNativeFrame(TNumrow row, TSignedSeqPos aln_pos) const + { + int w = GetBaseWidth(row); + return (w == 3) ? aln_pos % 3 + 1 : 0; + } + /// Convert sequence position to alignment (genomic) coordinate. - TSignedSeqPos NativeSeqPosToAlnPos(TNumrow row, TSignedSeqPos seq_pos) const + /// Optional frame can be used with protein positions. + TSignedSeqPos NativeSeqPosToAlnPos(TNumrow row, + TSignedSeqPos seq_pos, + int frame = 0) const { - return seq_pos*GetBaseWidth(row); + int w = GetBaseWidth(row); + TSignedSeqPos ret = seq_pos*w; + if (w == 3 && frame) ret += frame - 1; + return ret; } /// Convert alignment range (genomic coordinates) on the selected row @@ -269,14 +283,19 @@ public: } /// Convert sequence range to alignment range (genomic coordinates). + /// Optional frames argument can be provided for protein ranges. /// NOTE: Need to use template since there are many range types: /// TRng, TAlnRng, TRange, TSignedRange etc. template - _TRange NativeSeqRangeToAlnRange(TNumrow row, _TRange seq_range) const + _TRange NativeSeqRangeToAlnRange(TNumrow row, + _TRange seq_range, + TFrames frames = TFrames(0, 0)) const { if (seq_range.Empty() || seq_range.IsWhole()) return seq_range; int w = GetBaseWidth(row); - return _TRange(seq_range.GetFrom()*w, seq_range.GetToOpen()*w - 1); + int from_frame = frames.first ? frames.first - 1 : 0; + int to_frame = frames.second ? frames.second - 1 : 0; + return _TRange(seq_range.GetFrom()*w + from_frame, seq_range.GetToOpen()*w + to_frame - 1); } protected: diff --git a/c++/include/objtools/blast/blastdb_format/blastdb_dataextract.hpp b/c++/include/objtools/blast/blastdb_format/blastdb_dataextract.hpp index b94f9b47..52bc1d2e 100644 --- a/c++/include/objtools/blast/blastdb_format/blastdb_dataextract.hpp +++ b/c++/include/objtools/blast/blastdb_format/blastdb_dataextract.hpp @@ -1,4 +1,4 @@ -/* $Id: blastdb_dataextract.hpp 434826 2014-05-12 14:08:40Z rackerst $ +/* $Id: blastdb_dataextract.hpp 516398 2016-10-13 12:26:59Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -69,11 +69,17 @@ public: m_UseCtrlA(ctrl_a), m_Oid(0) { - m_Gi2TaxidMap.first = -1; - m_Gi2AccMap.first = -1; - m_Gi2TitleMap.first = -1; - m_Oid2Pig.first = -1; - m_Gi2SeqIdMap.first = -1; + m_Gi2TaxidMap.first = -1; + m_Gi2AccMap.first = -1; + m_Gi2TitleMap.first = -1; + m_Oid2Pig.first = -1; + m_Gi2SeqIdMap.first = -1; + + CNcbiApplication* app = CNcbiApplication::Instance(); + if (app) { + const CNcbiRegistry& registry = app->GetConfig(); + m_UseLongSeqIds = (registry.Get("BLAST", "LONG_SEQID") == "1"); + } } /// Setting seqid @@ -146,6 +152,8 @@ protected: pair m_Oid2Pig; // Pair with a gi2seqid for one Oid. pair > m_Gi2SeqIdMap; + /// Use long sequence ids (with gi and accessions with database source) + bool m_UseLongSeqIds; private: void x_ExtractMaskingData(CSeqDB::TSequenceRanges &ranges, int algo_id); int x_ExtractTaxId(); @@ -164,6 +172,70 @@ private: void x_SetGi(); }; +class NCBI_BLASTDB_FORMAT_EXPORT CBlastDeflineUtil +{ +public: + struct BlastDeflineFields{ + unsigned int accession:1; + unsigned int seq_id:1; + unsigned int gi:1; + unsigned int title:1; + unsigned int membership:1; + unsigned int tax_id:1; + unsigned int leaf_node_tax_ids:1; + // The tax names include: scientific_name, common_name, blast_name and super kingdom + unsigned int tax_names:1; + unsigned int leaf_node_tax_names:1; + unsigned int pig:1; + unsigned int links:1; + unsigned int asn_defline:1; + + }; + + enum FieldIndex { + accession = 0, + seq_id, + gi, + title, + membership, + pig, + tax_id, + leaf_node_tax_ids, + scientific_name, + leaf_node_scientific_names, + common_name, + leaf_node_common_names, + blast_name, + super_kingdom, + links, + asn_defline, + max_index + }; + static void ExtractDataFromBlastDeflineSet(const CBlast_def_line_set & dl_set, + vector & results, + BlastDeflineFields fields, + string target_id, + bool use_long_id); + + static void ExtractDataFromBlastDefline(const CBlast_def_line & dl, + vector & results, + BlastDeflineFields fields, + bool use_long_id); + + static void ProcessFastaDeflines(CBioseq & bioseq, string & out, bool use_ctrla); +}; + +class NCBI_BLASTDB_FORMAT_EXPORT CBlastSeqUtil +{ +public: + static Uint4 GetSeqHash(const char* buffer, int length); + static void ApplySeqMask(string & seq, + const CSeqDB::TSequenceRanges & masks, + const TSeqRange r=TSeqRange::GetEmpty()); + static void GetReverseStrandSeq(string & seq); + static string GetMasksString(const CSeqDB::TSequenceRanges & masks); + +}; END_NCBI_SCOPE diff --git a/c++/include/objtools/blast/blastdb_format/blastdb_seqid.hpp b/c++/include/objtools/blast/blastdb_format/blastdb_seqid.hpp index b024f307..6fd23d26 100644 --- a/c++/include/objtools/blast/blastdb_format/blastdb_seqid.hpp +++ b/c++/include/objtools/blast/blastdb_format/blastdb_seqid.hpp @@ -1,4 +1,4 @@ -/* $Id: blastdb_seqid.hpp 496013 2016-03-23 11:31:35Z ivanov $ +/* $Id: blastdb_seqid.hpp 495929 2016-03-22 17:15:46Z rackerst $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/objtools/blast/blastdb_format/seq_formatter.hpp b/c++/include/objtools/blast/blastdb_format/seq_formatter.hpp new file mode 100644 index 00000000..867c3b24 --- /dev/null +++ b/c++/include/objtools/blast/blastdb_format/seq_formatter.hpp @@ -0,0 +1,197 @@ +/* + * =========================================================================== + * + * PUBLIC DOMAIN NOTICE + * National Center for Biotechnology Information + * + * This software/database is a "United States Government Work" under the + * terms of the United States Copyright Act. It was written as part of + * the author's official duties as a United States Government employee and + * thus cannot be copyrighted. This software/database is freely available + * to the public for use. The National Library of Medicine and the U.S. + * Government have not placed any restriction on its use or reproduction. + * + * Although all reasonable efforts have been taken to ensure the accuracy + * and reliability of the software and data, the NLM and the U.S. + * Government do not and cannot warrant the performance or results that + * may be obtained by using this software or data. The NLM and the U.S. + * Government disclaim all warranties, express or implied, including + * warranties of performance, merchantability or fitness for any particular + * purpose. + * + * Please cite the author in any work or product based on this material. + * + * =========================================================================== + * + * Author: Amelia Fong + * + */ + +/** @file seq_formatter.hpp + * Definition of a blastdb formatter interfaces + */ + +#ifndef OBJTOOLS_BLASTDB_FORMAT___SEQ_FORMATTER__HPP +#define OBJTOOLS_BLASTDB_FORMAT___SEQ_FORMATTER__HPP + +#include +#include + +BEGIN_NCBI_SCOPE + +/// Configuration object for CBlastDB_Formatter classes +struct CBlastDB_FormatterConfig { + /// Default constructor + CBlastDB_FormatterConfig() { + m_SeqRange = TSeqRange(); + m_Strand = objects::eNa_strand_other; + m_UseCtrlA = false; + m_FiltAlgoId = -1; + m_FmtAlgoId = -1; + } + + + /// The range of the sequence to retrieve, if empty, the + /// entire sequence will be retrived + TSeqRange m_SeqRange; + /// All SeqLoc types will have this strand assigned; If set to 'other', the + /// strand will be set to 'unknown' for protein sequences and 'both' for + /// nucleotide + objects::ENa_strand m_Strand; + /// Determines whether Ctrl-A characters should be used as defline + /// separators + bool m_UseCtrlA; + /// Filtering algorithm ID to mask the FASTA + int m_FiltAlgoId; + /// Filtering algorithm ID for outfmt %m + int m_FmtAlgoId; +}; + +class NCBI_BLASTDB_FORMAT_EXPORT CBlastDB_Formatter +{ +public: + CBlastDB_Formatter() {} + + virtual int Write(CSeqDB::TOID oid, const CBlastDB_FormatterConfig & config, string target_id = kEmptyStr) = 0; + virtual void DumpAll(const CBlastDB_FormatterConfig & config) = 0; + virtual ~CBlastDB_Formatter() {} + +private: + /// Prohibit copy constructor + CBlastDB_Formatter(const CBlastDB_Formatter& rhs); + /// Prohibit assignment operator + CBlastDB_Formatter& operator=(const CBlastDB_Formatter& rhs); + +}; + +/// Customizable sequence formatter interface +class NCBI_BLASTDB_FORMAT_EXPORT CBlastDB_SeqFormatter : public CBlastDB_Formatter +{ +public: + /// Constructor + /// @param fmt_spec format specification [in] + /// @param blastdb BLAST database from which to retrieve the data [in] + /// @param out output stream to write the data [in] + CBlastDB_SeqFormatter(const string& fmt_spec, CSeqDB& blastdb, CNcbiOstream& out); + + int Write(CSeqDB::TOID oid, const CBlastDB_FormatterConfig & config, string target_id = kEmptyStr); + void DumpAll(const CBlastDB_FormatterConfig & config); + +private: + /// Fields not in defline + enum EOtherFields { + e_seq = 0, + e_mask, + e_hash, + e_max_other_fields + }; + + /// Stream to write output + CNcbiOstream& m_Out; + /// The output format specification + string m_FmtSpec; + /// The BLAST database from which to extract data + CSeqDB& m_BlastDb; + /// Vector of offsets where the replacements will take place + vector m_Seperators; + /// Vector of convertor objects + vector m_ReplTypes; + bool m_GetDefline; + CBlastDeflineUtil::BlastDeflineFields m_DeflineFields; + /// Bit Mask for other fields + unsigned int m_OtherFields; + /// Build data for write + void x_Print(CSeqDB::TOID oid, vector & defline_data, vector & other_fields); + + void x_DataRequired(); + + void x_GetSeq(CSeqDB::TOID oid, const CBlastDB_FormatterConfig & config, string & seq); + string x_GetSeqHash(CSeqDB::TOID oid); + string x_GetSeqMask(CSeqDB::TOID oid, int algo_id); + + /// Prohibit copy constructor + CBlastDB_SeqFormatter(const CBlastDB_SeqFormatter& rhs); + /// Prohibit assignment operator + CBlastDB_SeqFormatter& operator=(const CBlastDB_SeqFormatter& rhs); + +}; + +/// Fasta formatter interface +class NCBI_BLASTDB_FORMAT_EXPORT CBlastDB_FastaFormatter : public CBlastDB_Formatter +{ +public: + /// Constructor + /// @param blastdb BLAST database from which to retrieve the data [in] + /// @param out output stream to write the data [in] + /// @param width fasta line width [in] + CBlastDB_FastaFormatter(CSeqDB& blastdb, CNcbiOstream& out, TSeqPos width = 80, bool useLongSeqId = false); + + void DumpAll(const CBlastDB_FormatterConfig & config); + + /// Retun 0 if Sucess otherwise -1 + int Write(CSeqDB::TOID oid, const CBlastDB_FormatterConfig & config, string target_id = kEmptyStr); + +private: + + /// The BLAST database from which to extract data + CSeqDB& m_BlastDb; + CNcbiOstream& m_Out; + CFastaOstream m_fasta; + bool m_UseLongSeqIds; + + /// Prohibit copy constructor + CBlastDB_FastaFormatter(const CBlastDB_FastaFormatter& rhs); + /// Prohibit assignment operator + CBlastDB_FastaFormatter& operator=(const CBlastDB_FastaFormatter& rhs); +}; + +class NCBI_BLASTDB_FORMAT_EXPORT CBlastDB_BioseqFormatter : public CBlastDB_Formatter +{ +public: + /// Constructor + /// @param blastdb BLAST database from which to retrieve the data [in] + /// @param out output stream to write the data [in] + CBlastDB_BioseqFormatter(CSeqDB& blastdb, CNcbiOstream& out); + + void DumpAll(const CBlastDB_FormatterConfig & config); + + /// Retun 0 if Sucess otherwise -1 + int Write(CSeqDB::TOID oid, const CBlastDB_FormatterConfig & config, string target_id = kEmptyStr); + +private: + + /// The BLAST database from which to extract data + CSeqDB& m_BlastDb; + CNcbiOstream& m_Out; + + /// Prohibit copy constructor + CBlastDB_BioseqFormatter(const CBlastDB_BioseqFormatter& rhs); + /// Prohibit assignment operator + CBlastDB_BioseqFormatter& operator=(const CBlastDB_BioseqFormatter& rhs); + +}; + +END_NCBI_SCOPE + +#endif /* OBJTOOLS_BLASTDB_FORMAT___SEQ_FORMATTER__HPP */ + diff --git a/c++/include/objtools/blast/blastdb_format/seq_writer.hpp b/c++/include/objtools/blast/blastdb_format/seq_writer.hpp index 61d162b6..4c70855a 100644 --- a/c++/include/objtools/blast/blastdb_format/seq_writer.hpp +++ b/c++/include/objtools/blast/blastdb_format/seq_writer.hpp @@ -1,4 +1,4 @@ -/* $Id: seq_writer.hpp 404550 2013-06-25 16:51:53Z madden $ +/* $Id: seq_writer.hpp 516393 2016-10-13 12:26:14Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -40,7 +40,7 @@ BEGIN_NCBI_SCOPE /// Configuration object for CSeqFormatter -struct CSeqFormatterConfig { +struct NCBI_DEPRECATED CSeqFormatterConfig { /// Default constructor CSeqFormatterConfig() { m_LineWidth = 80; @@ -74,7 +74,7 @@ struct CSeqFormatterConfig { }; /// Customizable sequence writer interface -class NCBI_BLASTDB_FORMAT_EXPORT CSeqFormatter +class NCBI_BLASTDB_FORMAT_EXPORT NCBI_DEPRECATED CSeqFormatter { public: /// Constructor diff --git a/c++/include/objtools/blast/seqdb_reader/impl/seqdbatlas.hpp b/c++/include/objtools/blast/seqdb_reader/impl/seqdbatlas.hpp index 72321813..8d960e1e 100644 --- a/c++/include/objtools/blast/seqdb_reader/impl/seqdbatlas.hpp +++ b/c++/include/objtools/blast/seqdb_reader/impl/seqdbatlas.hpp @@ -1,7 +1,7 @@ #ifndef OBJTOOLS_READERS_SEQDB__SEQDBATLAS_HPP #define OBJTOOLS_READERS_SEQDB__SEQDBATLAS_HPP -/* $Id: seqdbatlas.hpp 484524 2015-11-12 15:32:31Z rackerst $ +/* $Id: seqdbatlas.hpp 516398 2016-10-13 12:26:59Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -1785,12 +1785,14 @@ public: path += CDirEntry::NormalizePath(env.Get("BLASTDB"),eFollowLinks); path += splitter; // Finally, the config file. - CMetaRegistry::SEntry sentry = - CMetaRegistry::Load("ncbi", CMetaRegistry::eName_RcOrIni); - if (sentry.registry) { - path += CDirEntry::NormalizePath(sentry.registry->Get("BLAST", "BLASTDB"),eFollowLinks); - path += splitter; - } + CNcbiApplication* app = CNcbiApplication::Instance(); + if (app) { + const CNcbiRegistry& registry = app->GetConfig(); + if (registry.HasEntry("BLAST", "BLASTDB")) { + path += CDirEntry::NormalizePath(registry.Get("BLAST", "BLASTDB"),eFollowLinks); + path += splitter; + } + } return path; } diff --git a/c++/include/objtools/blast/seqdb_reader/impl/seqdbgeneral.hpp b/c++/include/objtools/blast/seqdb_reader/impl/seqdbgeneral.hpp index 4c67ef33..9c5b0618 100644 --- a/c++/include/objtools/blast/seqdb_reader/impl/seqdbgeneral.hpp +++ b/c++/include/objtools/blast/seqdb_reader/impl/seqdbgeneral.hpp @@ -1,7 +1,7 @@ #ifndef CORELIB__SEQDB__SEQDBGENERAL_HPP #define CORELIB__SEQDB__SEQDBGENERAL_HPP -/* $Id: seqdbgeneral.hpp 480259 2015-09-29 14:58:22Z fongah2 $ +/* $Id: seqdbgeneral.hpp 514045 2016-09-19 12:26:51Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -434,6 +434,7 @@ private: /// @param front Region before delim if found. [out] /// @param delim Character for which to search. [in] /// @return true if the character was found, false otherwise. +NCBI_XOBJREAD_EXPORT bool SeqDB_SplitString(CSeqDB_Substring & buffer, CSeqDB_Substring & front, char delim); @@ -460,6 +461,7 @@ bool SeqDB_SplitString(CSeqDB_Substring & buffer, /// The file extension (without the "."), or NULL if none. /// @param outp /// A returned string containing the combined path and file name +NCBI_XOBJREAD_EXPORT void SeqDB_CombinePath(const CSeqDB_Substring & path, const CSeqDB_Substring & file, const CSeqDB_Substring * extn, @@ -475,6 +477,7 @@ void SeqDB_CombinePath(const CSeqDB_Substring & path, /// Input path /// @return /// Path minus file extension +NCBI_XOBJREAD_EXPORT CSeqDB_Substring SeqDB_RemoveFileName(CSeqDB_Substring s); @@ -487,6 +490,7 @@ CSeqDB_Substring SeqDB_RemoveFileName(CSeqDB_Substring s); /// Input path /// @return /// Filename portion of path +NCBI_XOBJREAD_EXPORT CSeqDB_Substring SeqDB_RemoveDirName(CSeqDB_Substring s); @@ -499,6 +503,7 @@ CSeqDB_Substring SeqDB_RemoveDirName(CSeqDB_Substring s); /// Input path /// @return /// Path minus file extension +NCBI_XOBJREAD_EXPORT CSeqDB_Substring SeqDB_RemoveExtn(CSeqDB_Substring s); @@ -511,6 +516,7 @@ CSeqDB_Substring SeqDB_RemoveExtn(CSeqDB_Substring s); /// filesystem sources such as alias files. /// /// @param dbs This string will be changed in-place. +NCBI_XOBJREAD_EXPORT void SeqDB_ConvertOSPath(string & dbs); @@ -1085,11 +1091,13 @@ string SeqDB_FindBlastDBPath(const string & file_name, /// Second component /// @param delim /// The delimiter to use when joining elements +NCBI_XOBJREAD_EXPORT void SeqDB_JoinDelim(string & a, const string & b, const string & delim); /// Thow a SeqDB exception; this is seperated into a function /// primarily to allow a breakpoint to be set. +NCBI_XOBJREAD_EXPORT void SeqDB_ThrowException(CSeqDBException::EErrCode code, const string & msg); @@ -1108,6 +1116,7 @@ void SeqDB_ThrowException(CSeqDBException::EErrCode code, const string & msg); /// @param file Name of the file containing the assert. /// @param line The line the assert in on. /// @param text The text version of the asserted condition. +NCBI_XOBJREAD_EXPORT void SeqDB_FileIntegrityAssert(const string & file, int line, const string & text); @@ -1200,6 +1209,7 @@ private: /// /// @param dbs Database names to combine. /// @param dbname Combined database name. +NCBI_XOBJREAD_EXPORT void SeqDB_CombineAndQuote(const vector & dbs, string & dbname); @@ -1207,6 +1217,7 @@ void SeqDB_CombineAndQuote(const vector & dbs, /// /// @param dbname Combined database name. /// @param dbs Database names to combine. +NCBI_XOBJREAD_EXPORT void SeqDB_SplitQuoted(const string & dbname, vector & dbs, bool keep_quote = false); diff --git a/c++/include/objtools/blast/seqdb_reader/seqdb.hpp b/c++/include/objtools/blast/seqdb_reader/seqdb.hpp index 27c49c6e..3e78b590 100644 --- a/c++/include/objtools/blast/seqdb_reader/seqdb.hpp +++ b/c++/include/objtools/blast/seqdb_reader/seqdb.hpp @@ -1,7 +1,7 @@ #ifndef OBJTOOLS_BLAST_SEQDB_READER___SEQDB__HPP #define OBJTOOLS_BLAST_SEQDB_READER___SEQDB__HPP -/* $Id: seqdb.hpp 468781 2015-05-28 12:51:59Z vasilche $ +/* $Id: seqdb.hpp 516402 2016-10-13 12:28:06Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -1016,6 +1016,9 @@ public: /// Translate a GI to an OID. bool GiToOid(TGi gi, int & oid) const; + /// Translate a GI To an OID with filter check + bool GiToOidwFilterCheck(TGi gi, int & oid) const; + /// Translate a GI to a PIG. bool GiToPig(TGi gi, int & pig) const; diff --git a/c++/include/objtools/blast/seqdb_writer/build_db.hpp b/c++/include/objtools/blast/seqdb_writer/build_db.hpp index 52a40f56..834d332f 100644 --- a/c++/include/objtools/blast/seqdb_writer/build_db.hpp +++ b/c++/include/objtools/blast/seqdb_writer/build_db.hpp @@ -1,4 +1,4 @@ -/* $Id: build_db.hpp 485504 2015-11-23 14:41:02Z rackerst $ +/* $Id: build_db.hpp 514245 2016-09-20 17:05:47Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -150,12 +150,15 @@ public: /// @param Logging will be done to this stream. [in] /// @param use_gi_mask if true will generate GI-based mask files [in] /// @param logfile file to write the log to [in] + /// @param long_seqids if true, requires long sequence ids + /// (database|accession) when parsing fasta sequences [in] CBuildDatabase(const string & dbname, const string & title, bool is_protein, CWriteDB::TIndexType indexing, bool use_gi_mask, - ostream * logfile); + ostream * logfile, + bool long_seqids = false); // Note -- should deprecate (or just remove) the following one: // - sparse does nothing @@ -176,13 +179,16 @@ public: /// @param parse_seqids specify true to parse the sequence IDs [in] /// @param use_gi_mask if true will generate GI-based mask files [in] /// @param indexing index fields to add to database. [in] + /// @param long_seqids if true, requires long sequence ids + /// (database|accession) when parsing fasta sequences [in] CBuildDatabase(const string & dbname, const string & title, bool is_protein, bool sparse, bool parse_seqids, bool use_gi_mask, - ostream * logfile); + ostream * logfil, + bool long_seqids = false); ~CBuildDatabase(); @@ -621,6 +627,9 @@ private: /// If true, string IDs found in FASTA input will be parsed as Seq-ids. bool m_ParseIDs; + /// If true, use long sequence ids (database|accession) + bool m_LongIDs; + /// If true, there were sequences whose IDs matched those in the provided /// masking locations (via SetMaskDataSource). Used to display a warning in /// case this didn't happen diff --git a/c++/include/objtools/blast/seqdb_writer/impl/criteria.hpp b/c++/include/objtools/blast/seqdb_writer/impl/criteria.hpp index 278fca51..08c1b8a0 100644 --- a/c++/include/objtools/blast/seqdb_writer/impl/criteria.hpp +++ b/c++/include/objtools/blast/seqdb_writer/impl/criteria.hpp @@ -1,7 +1,7 @@ #ifndef OBJTOOLS_BLAST_SEQDB_WRITER_IMPL___CRITERIA__HPP #define OBJTOOLS_BLAST_SEQDB_WRITER_IMPL___CRITERIA__HPP -/* $Id: criteria.hpp 401964 2013-06-04 15:01:28Z camacho $ +/* $Id: criteria.hpp 513036 2016-09-06 19:42:13Z fukanchi $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -64,7 +64,7 @@ BEGIN_NCBI_SCOPE /// Structure which corresponds to format of records in DI files. struct SDIRecord { int oid; /// Ordinal ID - int gi; /// GenInfo ID + TGi gi; /// GenInfo ID int taxid; /// Taxonomy ID int owner; /// Owner string div; /// 3-letter division @@ -75,7 +75,8 @@ struct SDIRecord { int mol; /// Molecule type, as in Seq-inst::mol SDIRecord() { - oid = gi = taxid = owner = len = hash = sat_key = mol = 0; + oid = taxid = owner = len = hash = sat_key = mol = 0; + gi = ZERO_GI; } }; @@ -481,7 +482,7 @@ NCBI_XOBJWRITE_EXPORT int CCriteriaSet_CalculateMemberships( const SDIRecord& direcord, /// DI record data - objects::CBlast_def_line& defline /// The + objects::CBlast_def_line& defline /// The ); diff --git a/c++/include/objtools/blast/seqdb_writer/writedb.hpp b/c++/include/objtools/blast/seqdb_writer/writedb.hpp index 72af6c92..2ed03ec4 100644 --- a/c++/include/objtools/blast/seqdb_writer/writedb.hpp +++ b/c++/include/objtools/blast/seqdb_writer/writedb.hpp @@ -1,7 +1,7 @@ #ifndef OBJTOOLS_BLAST_SEQDB_WRITER___WRITEDB__HPP #define OBJTOOLS_BLAST_SEQDB_WRITER___WRITEDB__HPP -/* $Id: writedb.hpp 480531 2015-10-01 15:03:55Z rackerst $ +/* $Id: writedb.hpp 513849 2016-09-15 17:36:45Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -144,6 +144,9 @@ public: /// Indicates the type of indices to build if specified. [in] /// @param parse_ids /// If true, generate ISAM files [in] + /// @param long_ids + /// If true, assume long sequence ids (database|accession) when parsing + /// string ids [in] /// @param use_gi_mask /// If true, generate GI-based mask files [in] CWriteDB(const string & dbname, @@ -151,6 +154,7 @@ public: const string & title, int itype = eDefault, bool parse_ids = true, + bool long_ids = false, bool use_gi_mask = false); /// Destructor. @@ -345,9 +349,11 @@ public: /// /// @param bs The bioseq from which to extract a defline set. [in] /// @param parse_ids If seqid should be parsed [in] + /// @param long_ids It true, use long sequence ids (database|accession) [in] /// @return A set of deflines for this CBioseq. static CRef - ExtractBioseqDeflines(const CBioseq & bs, bool parse_ids=true); + ExtractBioseqDeflines(const CBioseq & bs, bool parse_ids=true, + bool long_ids=false); /// Set letters that should not be used in sequences. /// diff --git a/c++/include/objtools/blast/services/blast_services.hpp b/c++/include/objtools/blast/services/blast_services.hpp index 9225870e..551f19b4 100644 --- a/c++/include/objtools/blast/services/blast_services.hpp +++ b/c++/include/objtools/blast/services/blast_services.hpp @@ -1,7 +1,7 @@ #ifndef ALGO_BLAST_API___REMOTE_SERVICES__HPP #define ALGO_BLAST_API___REMOTE_SERVICES__HPP -/* $Id: blast_services.hpp 464987 2015-04-15 19:29:32Z merezhuk $ +/* $Id: blast_services.hpp 500813 2016-05-09 14:10:24Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -57,6 +57,9 @@ END_SCOPE(objects) using namespace ncbi::objects; +#ifndef NCBI_MODULE +#define NCBI_MODULE NETBLAST +#endif /// RemoteServicesException /// @@ -278,6 +281,8 @@ private: bool m_Verbose; }; +#undef NCBI_MODULE + END_NCBI_SCOPE /* @} */ diff --git a/c++/include/objtools/cleanup/cleanup.hpp b/c++/include/objtools/cleanup/cleanup.hpp index e8a6bc92..1c98ebd0 100644 --- a/c++/include/objtools/cleanup/cleanup.hpp +++ b/c++/include/objtools/cleanup/cleanup.hpp @@ -1,7 +1,7 @@ #ifndef CLEANUP___CLEANUP__HPP #define CLEANUP___CLEANUP__HPP -/* $Id: cleanup.hpp 500220 2016-05-03 14:56:08Z ivanov $ +/* $Id: cleanup.hpp 520817 2016-12-01 18:50:34Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -69,11 +69,17 @@ public: eClean_GpipeMode = 0x2, eClean_NoNcbiUserObjects = 0x4, eClean_SyncGenCodes = 0x8, - eClean_NoProteinTitles = 0x10 + eClean_NoProteinTitles = 0x10, + eClean_KeepTopSet = 0x20 + }; + + enum EScopeOptions { + eScope_Copy, + eScope_UseInPlace }; // Construtor / Destructor - CCleanup(CScope* scope = NULL); + CCleanup(CScope* scope = NULL, EScopeOptions scope_handling = eScope_Copy); ~CCleanup(); void SetScope(CScope* scope); @@ -153,6 +159,28 @@ public: /// @return Boolean return value indicates whether gene-xrefs were removed static bool RemoveNonsuppressingGeneXrefs(CSeq_feat& f); + +/// Repairs non-reciprocal xref pairs for specified feature if xrefs between +/// subtypes are permitted and feature with missing xref does not have an +/// xref to a different feature of the same subtype +/// @param f Seq-feat to edit [in] +/// @param tse top-level Seq-entry in which to search for the other half of the xref pair +/// @return Boolean return value indicates whether xrefs were created + static bool RepairXrefs(const CSeq_feat& f, const CTSE_Handle& tse); + +/// Repairs non-reciprocal xref pairs for specified feature pair if xrefs between +/// subtypes are permitted and feature with missing xref does not have an +/// xref to a different feature of the same subtype +/// @param f Seq-feat to edit [in] +/// @param tse top-level Seq-entry in which to search for the other half of the xref pair +/// @return Boolean return value indicates whether xrefs were created + static bool RepairXrefs(const CSeq_feat& src, CSeq_feat_Handle& dst, const CTSE_Handle& tse); + +/// Repairs non-reciprocal xref pairs in specified seq-entry +/// @param seh Seq-entry to edit [in] +/// @return Boolean return value indicates whether xrefs were created + static bool RepairXrefs(CSeq_entry_Handle seh); + /// Detects gene features with matching locus /// @param f Seq-feat parent feature of gene_xref [in] /// @param gene_xref Gene-ref of gene-xref [in] @@ -179,6 +207,14 @@ public: /// @return Boolean return value indicates whether gene-xrefs were removed static bool RemoveOrphanLocus_tagGeneXrefs(CSeq_feat& f, CBioseq_Handle bsh); +/// Extends a location to the specificed position. +/// @param loc Seq-loc to extend +/// @param pos position of new end of location +/// @param scope Scope in which to look for sequences +/// @return Boolean return value indicates whether the location was extended + static bool SeqLocExtend(CSeq_loc& loc, size_t pos, CScope& scope); + + /// Extends a coding region up to 50 nt. if the coding region: /// 1. does not end with a stop codon /// 2. is adjacent to a stop codon @@ -196,7 +232,8 @@ public: /// @param bsh CBioseq_Handle on which the feature is located /// @param limit maximum number of nt to extend, or 0 if unlimited /// @return Boolean return value indicates whether the feature was extended - static bool ExtendToStopCodon(CSeq_feat& f, CBioseq_Handle bsh, size_t limit, CCdregion::TFrame frame = CCdregion::eFrame_not_set); + static bool ExtendToStopCodon(CSeq_feat& f, CBioseq_Handle bsh, size_t limit); + static bool ExtendStopPosition(CSeq_feat& f, const CSeq_feat* cdregion, size_t extension = 0); /// Translates coding region and selects best frame (without stops, or longest) /// @param cds Coding region Seq-feat to edit @@ -224,11 +261,31 @@ public: /// @return Boolean return value indicates whether the coding region changed static bool SetCDSPartialsByFrameAndTranslation(CSeq_feat& cds, CScope& scope); + +/// Clear internal partials + static bool ClearInternalPartials(CSeq_loc& loc, bool is_first = true, bool is_last = true); + static bool ClearInternalPartials(CSeq_loc_mix& mix, bool is_first = true, bool is_last = true); + static bool ClearInternalPartials(CPacked_seqint& pint, bool is_first = true, bool is_last = true); + static bool ClearInternalPartials(CSeq_entry_Handle seh); + +/// Set feature partial based on feature location + static bool SetFeaturePartial(CSeq_feat& f); + /// Update EC numbers /// @param ec_num_list Prot-ref ec number list to clean /// @return Boolean value indicates whether any changes were made static bool UpdateECNumbers(CProt_ref::TEc & ec_num_list); +/// Delete EC numbers +/// @param ec_num_list Prot-ref ec number list to clean +/// @return Boolean value indicates whether any changes were made + static bool RemoveBadECNumbers(CProt_ref::TEc & ec_num_list); + +/// Fix EC numbers +/// @param entry Seq-entry-handle to clean +/// @return Boolean value indicates whether any changes were made + static bool FixECNumbers(CSeq_entry_Handle entry); + /// Set partialness of gene to match longest feature contained in gene /// @param gene Seq-feat to edit /// @param scope Scope in which to find gene @@ -240,14 +297,6 @@ public: static const string& GetProteinName(const CProt_ref& prot); static const string& GetProteinName(const CSeq_feat& cds, CScope& scope); -/// Checks to see if a feature is pseudo. Looks for pseudo flag set on feature, -/// looks for pseudogene qualifier on feature, performs same checks for gene -/// associated with feature -/// @param feat Seq-feat to check -/// @param scope CScope to use when looking for associated gene -/// @return Boolean return value indicates whether any of the "pseudo" markers are found - static bool IsPseudo(const CSeq_feat& feat, CScope& scope); - /// Sets MolInfo::tech for a sequence /// @param seq Bioseq to edit /// @param tech tech value to set @@ -366,6 +415,9 @@ public: /// @return bool indicates whether any changes were made static bool RescueSiteRefPubs(CSeq_entry_Handle seh); +/// Is this a "minimal" pub? (If yes, do not rescue from a Seq-feat.cit) + static bool IsMinPub(const CPubdesc& pd, bool is_refseq_prot); + //helper function for moving feature to pubdesc descriptor static void MoveOneFeatToPubdesc(CSeq_feat_Handle feat, CRef d, CBioseq_Handle b, bool remove_feat = true); @@ -385,8 +437,6 @@ public: /// @return bool indicates whether any changes were made static bool ConvertSrcFeatsToSrcDescs(CSeq_entry_Handle seh); - static CConstRef GetGeneForFeature(const CSeq_feat& feat, CScope& scope); - /// Examine all genes and gene xrefs in the Seq-entry. /// If no genes have locus and some have locus tag AND no gene xrefs have locus-tag /// and some gene xrefs have locus, change all gene xrefs to use locus tag. @@ -402,6 +452,22 @@ public: /// @return bool indicates whether any changes were made static bool RenormalizeNucProtSets(CSeq_entry_Handle seh); +/// decodes various tags, including carriage-return-line-feed constructs + static bool DecodeXMLMarkChanged(std::string & str); + + static CRef GetProteinLocationFromNucleotideLocation(const CSeq_loc& nuc_loc, CScope& scope); + static CRef GetProteinLocationFromNucleotideLocation(const CSeq_loc& nuc_loc, const CSeq_feat& cds, CScope& scope, bool require_inframe = false); + +/// Find proteins that are not packaged in the same nuc-prot set as the +/// coding region for which they are a product, and move them to that +/// nuc-prot set. Ignore coding regions that are in gen-prod-sets. +/// @param seh Seq-entry to edit +/// @return bool indicates whether any changes were made + static bool RepackageProteins(CSeq_entry_Handle seh); + static bool RepackageProteins(const CSeq_feat& cds, CBioseq_set_Handle np); + + static bool ConvertDeltaSeqToRaw(CSeq_entry_Handle seh, CSeq_inst::EMol filter = CSeq_inst::eMol_not_set); + private: // Prohibit copy constructor & assignment operator CCleanup(const CCleanup&); diff --git a/c++/include/objtools/cleanup/cleanup_change.hpp b/c++/include/objtools/cleanup/cleanup_change.hpp index 411def08..bb50adc5 100644 --- a/c++/include/objtools/cleanup/cleanup_change.hpp +++ b/c++/include/objtools/cleanup/cleanup_change.hpp @@ -1,7 +1,7 @@ #ifndef CLEANUP___CLEANUP_CHANGE__HPP #define CLEANUP___CLEANUP_CHANGE__HPP -/* $Id: cleanup_change.hpp 468092 2015-05-20 13:08:50Z bollin $ +/* $Id: cleanup_change.hpp 518386 2016-11-02 17:27:13Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -159,6 +159,7 @@ public: eRemoveDupBioSource, // 90 eCleanOrgref, eTrimInternalSemicolons, + eAddSeqFeatXref, // set when any other change is made. eChangeOther, diff --git a/c++/include/objtools/data_loaders/genbank/cache/writer_cache.hpp b/c++/include/objtools/data_loaders/genbank/cache/writer_cache.hpp index 69a984be..5b164332 100644 --- a/c++/include/objtools/data_loaders/genbank/cache/writer_cache.hpp +++ b/c++/include/objtools/data_loaders/genbank/cache/writer_cache.hpp @@ -1,7 +1,7 @@ #ifndef WRITER_CACHE__HPP_INCLUDED #define WRITER_CACHE__HPP_INCLUDED -/* $Id: writer_cache.hpp 494478 2016-03-07 19:26:06Z ivanov $ +/* $Id: writer_cache.hpp 493171 2016-02-24 19:31:13Z vasilche $ * =========================================================================== * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information diff --git a/c++/include/objtools/data_loaders/genbank/gbloader.hpp b/c++/include/objtools/data_loaders/genbank/gbloader.hpp index d954c754..626bbfa1 100644 --- a/c++/include/objtools/data_loaders/genbank/gbloader.hpp +++ b/c++/include/objtools/data_loaders/genbank/gbloader.hpp @@ -1,7 +1,7 @@ #ifndef GBLOADER__HPP_INCLUDED #define GBLOADER__HPP_INCLUDED -/* $Id: gbloader.hpp 494478 2016-03-07 19:26:06Z ivanov $ +/* $Id: gbloader.hpp 493171 2016-02-24 19:31:13Z vasilche $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/objtools/data_loaders/genbank/impl/dispatcher.hpp b/c++/include/objtools/data_loaders/genbank/impl/dispatcher.hpp index 9d571b51..0a2e8a7f 100644 --- a/c++/include/objtools/data_loaders/genbank/impl/dispatcher.hpp +++ b/c++/include/objtools/data_loaders/genbank/impl/dispatcher.hpp @@ -2,7 +2,7 @@ #define DISPATCHER__HPP_INCLUDED /* */ -/* $Id: dispatcher.hpp 494478 2016-03-07 19:26:06Z ivanov $ +/* $Id: dispatcher.hpp 493171 2016-02-24 19:31:13Z vasilche $ * =========================================================================== * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information diff --git a/c++/include/objtools/data_loaders/genbank/impl/info_cache.hpp b/c++/include/objtools/data_loaders/genbank/impl/info_cache.hpp index d51e77c5..4252f86f 100644 --- a/c++/include/objtools/data_loaders/genbank/impl/info_cache.hpp +++ b/c++/include/objtools/data_loaders/genbank/impl/info_cache.hpp @@ -1,7 +1,7 @@ #ifndef GENBANK_IMPL_INFO_CACHE #define GENBANK_IMPL_INFO_CACHE -/* $Id: info_cache.hpp 494478 2016-03-07 19:26:06Z ivanov $ +/* $Id: info_cache.hpp 497447 2016-04-06 18:19:05Z vasilche $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -42,7 +42,7 @@ #include #include #include -#include +#include BEGIN_NCBI_SCOPE BEGIN_SCOPE(objects) @@ -275,8 +275,8 @@ protected: return size_t(ptr)>>3; } }; - typedef hash_map, PtrHash> TLockMap; - typedef hash_map, PtrHash> TCacheMap; + typedef unordered_map, PtrHash> TLockMap; + typedef unordered_map, PtrHash> TCacheMap; CRef m_Manager; TLockMap m_LockMap; // map from CInfo_Base -> CInfoRequestorLock diff --git a/c++/include/objtools/data_loaders/genbank/impl/reader_id1_base.hpp b/c++/include/objtools/data_loaders/genbank/impl/reader_id1_base.hpp index 953b4bcf..d4315881 100644 --- a/c++/include/objtools/data_loaders/genbank/impl/reader_id1_base.hpp +++ b/c++/include/objtools/data_loaders/genbank/impl/reader_id1_base.hpp @@ -1,6 +1,6 @@ #ifndef READER_ID1_BASE__HPP_INCLUDED #define READER_ID1_BASE__HPP_INCLUDED -/* $Id: reader_id1_base.hpp 494478 2016-03-07 19:26:06Z ivanov $ +/* $Id: reader_id1_base.hpp 493171 2016-02-24 19:31:13Z vasilche $ * =========================================================================== * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information diff --git a/c++/include/objtools/data_loaders/genbank/impl/reader_id2_base.hpp b/c++/include/objtools/data_loaders/genbank/impl/reader_id2_base.hpp index 50f4d45b..2aa511aa 100644 --- a/c++/include/objtools/data_loaders/genbank/impl/reader_id2_base.hpp +++ b/c++/include/objtools/data_loaders/genbank/impl/reader_id2_base.hpp @@ -1,7 +1,7 @@ #ifndef READER_ID2_BASE__HPP_INCLUDED #define READER_ID2_BASE__HPP_INCLUDED -/* $Id: reader_id2_base.hpp 494478 2016-03-07 19:26:06Z ivanov $ +/* $Id: reader_id2_base.hpp 504899 2016-06-20 17:49:29Z vasilche $ * =========================================================================== * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information @@ -65,9 +65,11 @@ class CID2S_Reply_Get_Chunk; class CID2S_Chunk_Id; class CID2S_Chunk; class CID2Processor; - +class CId2ReaderProcessorResolver; class CReaderRequestResult; struct SId2LoadedSet; +struct SId2PacketInfo; +struct SId2PacketReplies; class NCBI_XREADER_EXPORT CId2ReaderBase : public CReader { @@ -249,7 +251,26 @@ protected: bool x_LoadSeq_idBlob_idsSet(CReaderRequestResult& result, const TSeqIds& seq_ids); + friend class CId2ReaderProcessorResolver; + + void x_DumpPacket(TConn conn, const CID2_Request_Packet& packet); + void x_DumpReply(TConn conn, const char* source, CID2_Reply& reply); void x_SetContextData(CID2_Request& request); + void x_SendToConnection(TConn conn, CID2_Request_Packet& packet); + CRef x_ReceiveFromConnection(TConn conn); + void x_AssignSerialNumbers(SId2PacketInfo& info, + CID2_Request_Packet& packet); + int x_GetReplyIndex(CReaderRequestResult& result, + CConn* conn, + SId2PacketInfo& packet, + const CID2_Reply& reply); + bool x_DoneReply(SId2PacketInfo& info, + int num, + const CID2_Reply& reply); + + void x_GetPacketReplies(CReaderRequestResult& result, + SId2PacketReplies& replies, + CID2_Request_Packet& packet); private: CAtomicCounter_WithAutoInit m_RequestSerialNumber; diff --git a/c++/include/objtools/data_loaders/genbank/impl/request_result.hpp b/c++/include/objtools/data_loaders/genbank/impl/request_result.hpp index d6977199..b37def60 100644 --- a/c++/include/objtools/data_loaders/genbank/impl/request_result.hpp +++ b/c++/include/objtools/data_loaders/genbank/impl/request_result.hpp @@ -1,7 +1,7 @@ #ifndef GBLOADER_REQUEST_RESULT__HPP_INCLUDED #define GBLOADER_REQUEST_RESULT__HPP_INCLUDED -/* $Id: request_result.hpp 494478 2016-03-07 19:26:06Z ivanov $ +/* $Id: request_result.hpp 493171 2016-02-24 19:31:13Z vasilche $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/objtools/data_loaders/genbank/reader.hpp b/c++/include/objtools/data_loaders/genbank/reader.hpp index e2c31e8e..11949e80 100644 --- a/c++/include/objtools/data_loaders/genbank/reader.hpp +++ b/c++/include/objtools/data_loaders/genbank/reader.hpp @@ -1,6 +1,6 @@ #ifndef READER__HPP_INCLUDED #define READER__HPP_INCLUDED -/* $Id: reader.hpp 494478 2016-03-07 19:26:06Z ivanov $ +/* $Id: reader.hpp 493171 2016-02-24 19:31:13Z vasilche $ * =========================================================================== * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information diff --git a/c++/include/objtools/data_loaders/genbank/reader_interface.hpp b/c++/include/objtools/data_loaders/genbank/reader_interface.hpp index 8544b5a6..61579eb3 100644 --- a/c++/include/objtools/data_loaders/genbank/reader_interface.hpp +++ b/c++/include/objtools/data_loaders/genbank/reader_interface.hpp @@ -1,6 +1,6 @@ #ifndef READER_INTERFACE__HPP_INCLUDED #define READER_INTERFACE__HPP_INCLUDED -/* $Id: reader_interface.hpp 494478 2016-03-07 19:26:06Z ivanov $ +/* $Id: reader_interface.hpp 493171 2016-02-24 19:31:13Z vasilche $ * =========================================================================== * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information diff --git a/c++/include/objtools/data_loaders/genbank/writer.hpp b/c++/include/objtools/data_loaders/genbank/writer.hpp index 26c37114..7b9b91a1 100644 --- a/c++/include/objtools/data_loaders/genbank/writer.hpp +++ b/c++/include/objtools/data_loaders/genbank/writer.hpp @@ -2,7 +2,7 @@ #define WRITER__HPP_INCLUDED /* */ -/* $Id: writer.hpp 494478 2016-03-07 19:26:06Z ivanov $ +/* $Id: writer.hpp 493171 2016-02-24 19:31:13Z vasilche $ * =========================================================================== * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information diff --git a/c++/include/objtools/data_loaders/genbank/writer_interface.hpp b/c++/include/objtools/data_loaders/genbank/writer_interface.hpp index 719e4f3b..702507d2 100644 --- a/c++/include/objtools/data_loaders/genbank/writer_interface.hpp +++ b/c++/include/objtools/data_loaders/genbank/writer_interface.hpp @@ -2,7 +2,7 @@ #define WRITER_INTERFACE__HPP_INCLUDED /* */ -/* $Id: writer_interface.hpp 494478 2016-03-07 19:26:06Z ivanov $ +/* $Id: writer_interface.hpp 493171 2016-02-24 19:31:13Z vasilche $ * =========================================================================== * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information diff --git a/c++/include/objtools/data_loaders/loaders.hpp b/c++/include/objtools/data_loaders/loaders.hpp index f105474c..3d7b8094 100644 --- a/c++/include/objtools/data_loaders/loaders.hpp +++ b/c++/include/objtools/data_loaders/loaders.hpp @@ -1,7 +1,7 @@ #ifndef DATA_LOADERS___LOADERS__HPP #define DATA_LOADERS___LOADERS__HPP -/* $Id: loaders.hpp 110873 2007-09-18 18:27:53Z jcherry $ +/* $Id: loaders.hpp 504655 2016-06-16 21:18:41Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/objtools/edit/apply_object.hpp b/c++/include/objtools/edit/apply_object.hpp index 737eb5bd..cffae1c4 100644 --- a/c++/include/objtools/edit/apply_object.hpp +++ b/c++/include/objtools/edit/apply_object.hpp @@ -1,4 +1,4 @@ -/* $Id: apply_object.hpp 447037 2014-09-22 11:21:25Z bollin $ +/* $Id: apply_object.hpp 494538 2016-03-08 14:31:04Z bollin $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/objtools/edit/autodef.hpp b/c++/include/objtools/edit/autodef.hpp index 0f8e90e9..1fd07d69 100644 --- a/c++/include/objtools/edit/autodef.hpp +++ b/c++/include/objtools/edit/autodef.hpp @@ -1,7 +1,7 @@ #ifndef OBJTOOLS_EDIT___AUTODEF__HPP #define OBJTOOLS_EDIT___AUTODEF__HPP -/* $Id: autodef.hpp 490362 2016-01-25 12:43:11Z bollin $ +/* $Id: autodef.hpp 510717 2016-08-15 17:12:40Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -95,6 +95,7 @@ public: void SetGeneClusterOppStrand(bool gene_opp_strand); void SetSuppressFeatureAltSplice (bool suppress_alt_splice); void SuppressMobileElementAndInsertionSequenceSubfeatures(bool suppress); + void SuppressMiscFeatSubfeatures(bool suppress); void SetKeepExons(bool keep); void SetKeepIntrons(bool keep); void SetKeepRegulatoryFeatures(bool keep); @@ -105,8 +106,10 @@ public: void SetKeepOptionalMobileElements(bool keep); void SetKeepPrecursorRNA(bool keep); void SetKeepRepeatRegion(bool keep); + void SetKeepMiscRecomb(bool keep); void SetUseNcRNAComment (bool use_comment); void SetUseFakePromoters (bool use_fake); + void SetCustomFeatureClause(const string& custom_feature_clause); void SuppressFeature(objects::CFeatListItem feat); void SuppressFeature(objects::CSeqFeatData::ESubtype subtype); @@ -236,6 +239,13 @@ void CAutoDef::SuppressMobileElementAndInsertionSequenceSubfeatures(bool suppres } +inline +void CAutoDef::SuppressMiscFeatSubfeatures(bool suppress) +{ + m_Options.SetSuppressMiscFeatureSubfeatures(suppress); +} + + inline void CAutoDef::SetKeepExons(bool keep) { @@ -302,6 +312,12 @@ void CAutoDef::SetKeepRepeatRegion(bool keep) m_Options.SetKeepRepeatRegion(keep); } +inline +void CAutoDef::SetKeepMiscRecomb(bool keep) +{ + m_Options.SetKeepMiscRecomb(keep); +} + inline void CAutoDef::SetUseNcRNAComment(bool use_comment) { @@ -316,6 +332,11 @@ void CAutoDef::SetUseFakePromoters(bool use_fake) } +inline +void CAutoDef::SetCustomFeatureClause(const string& custom_feature_clause) +{ + m_Options.SetCustomFeatureClause(custom_feature_clause); +} END_SCOPE(objects) END_NCBI_SCOPE diff --git a/c++/include/objtools/edit/autodef_feature_clause.hpp b/c++/include/objtools/edit/autodef_feature_clause.hpp index a8e6a0f5..34d1024f 100644 --- a/c++/include/objtools/edit/autodef_feature_clause.hpp +++ b/c++/include/objtools/edit/autodef_feature_clause.hpp @@ -1,7 +1,7 @@ #ifndef OBJTOOLS_EDIT___AUTODEF_FEATURE_CLAUSE__HPP #define OBJTOOLS_EDIT___AUTODEF_FEATURE_CLAUSE__HPP -/* $Id: autodef_feature_clause.hpp 493843 2016-03-02 14:04:45Z ivanov $ +/* $Id: autodef_feature_clause.hpp 519214 2016-11-14 16:05:29Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -77,7 +77,7 @@ public: virtual sequence::ECompare CompareLocation(const CSeq_loc& loc); virtual void AddToLocation(CRef loc, bool also_set_partials = true); virtual bool SameStrand(const CSeq_loc& loc); - virtual bool IsPartial(); + virtual bool IsPartial() const; virtual CRef GetLocation(); // functions for grouping @@ -90,6 +90,7 @@ public: virtual void ReverseCDSClauseLists(); virtual bool ShouldRemoveExons(); + virtual bool IsExonWithNumber(); virtual bool IsBioseqPrecursorRNA(); @@ -97,7 +98,11 @@ protected: CAutoDefFeatureClause(); bool x_GetGenericInterval (string &interval, bool suppress_allele); + void x_GetOperonSubfeatures(string &interval); + virtual bool x_IsPseudo(); + + void x_TypewordFromSequence(); const CSeq_feat& m_MainFeat; CRef m_ClauseLocation; diff --git a/c++/include/objtools/edit/autodef_feature_clause_base.hpp b/c++/include/objtools/edit/autodef_feature_clause_base.hpp index 38fbfce3..ece2ba57 100644 --- a/c++/include/objtools/edit/autodef_feature_clause_base.hpp +++ b/c++/include/objtools/edit/autodef_feature_clause_base.hpp @@ -1,7 +1,7 @@ #ifndef OBJTOOLS_EDIT___AUTODEF_FEATURE_CLAUSE_BASE__HPP #define OBJTOOLS_EDIT___AUTODEF_FEATURE_CLAUSE_BASE__HPP -/* $Id: autodef_feature_clause_base.hpp 490362 2016-01-25 12:43:11Z bollin $ +/* $Id: autodef_feature_clause_base.hpp 519214 2016-11-14 16:05:29Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -64,7 +64,7 @@ public: virtual void AddToOtherLocation(CRef loc); virtual void AddToLocation(CRef loc, bool also_set_partials = true); virtual bool SameStrand(const CSeq_loc& loc); - virtual bool IsPartial() { return false; } + virtual bool IsPartial() const { return false; } virtual bool IsMobileElement() { return false; } virtual bool IsInsertionSequence() { return false; } virtual bool IsControlRegion() { return false; } @@ -88,24 +88,24 @@ public: bool IsGeneMentioned(CAutoDefFeatureClause_Base *gene_clause); bool IsUnattachedGene() const; - bool IsTypewordFirst() { return m_ShowTypewordFirst; } + bool IsTypewordFirst() const { return m_ShowTypewordFirst; } bool DisplayAlleleName (); - string GetInterval() { return m_Interval; } - string GetTypeword() { return m_Typeword; } - string GetDescription() { return m_Description; } - string GetProductName() { return m_ProductName; } - string GetGeneName() { return m_GeneName; } - string GetAlleleName() { return m_AlleleName; } + const string& GetInterval() { return m_Interval; } + const string& GetTypeword() const { return m_Typeword; } + const string& GetDescription() const { return m_Description; } + const string& GetProductName() { return m_ProductName; } + const string& GetGeneName() { return m_GeneName; } + const string& GetAlleleName() { return m_AlleleName; } virtual void SetProductName(string product_name); - bool GetGeneIsPseudo() { return m_GeneIsPseudo; } - bool NeedPlural() { return m_MakePlural; } - bool IsAltSpliced() { return m_IsAltSpliced; } + bool GetGeneIsPseudo() const { return m_GeneIsPseudo; } + bool NeedPlural() const { return m_MakePlural; } + bool IsAltSpliced() const { return m_IsAltSpliced; } void SetAltSpliced(string splice_name); - bool IsMarkedForDeletion() { return m_DeleteMe; } + bool IsMarkedForDeletion() const { return m_DeleteMe; } void MarkForDeletion() { m_DeleteMe = true; } void SetMakePlural() { m_MakePlural = true; } - bool HasmRNA() { return m_HasmRNA; } + bool HasmRNA() const { return m_HasmRNA; } void SetInfoOnly (bool info_only) { m_ClauseInfoOnly = info_only; } void PluralizeInterval(); void PluralizeDescription(); @@ -142,9 +142,12 @@ public: void RemoveFeaturesByType(unsigned int feature_type, bool except_promoter = false); bool IsFeatureTypeLonely(unsigned int feature_type); void RemoveFeaturesInmRNAsByType(unsigned int feature_type, bool except_promoter = false); + void RemoveFeaturesUnderType(unsigned int feature_type); + void RemoveFeaturesInLocation(const CSeq_loc& loc); - virtual bool ShouldRemoveExons(); - + virtual bool ShouldRemoveExons() { return false; } + virtual bool IsExonWithNumber() { return false; } + void RemoveUnwantedExons(); virtual bool IsBioseqPrecursorRNA(); @@ -188,9 +191,10 @@ protected: bool m_DeleteMe; - unsigned int x_LastIntervalChangeBeforeEnd (); + size_t x_LastIntervalChangeBeforeEnd () const; bool x_OkToConsolidate (unsigned int clause1, unsigned int clause2); - bool x_MeetAltSpliceRules (unsigned int clause1, unsigned int clause2, string &splice_name); + bool x_OkToConsolidate(const CAutoDefFeatureClause_Base& other) const; + bool x_MeetAltSpliceRules (size_t clause1, size_t clause2, string &splice_name); void x_RemoveNullClauses(); @@ -201,6 +205,7 @@ protected: eMiscRnaWordType_RNAIntergenicSpacer, eMiscRnaWordType_RNA, eMiscRnaWordType_IntergenicSpacer, + eMiscRnaWordType_tRNA, eMiscRnaWordType_Unrecognized } ERnaMiscWord; static bool x_AddOneMiscWordElement(const string& phrase, vector& elements); diff --git a/c++/include/objtools/edit/autodef_mod_combo.hpp b/c++/include/objtools/edit/autodef_mod_combo.hpp index 561cd425..0c733017 100644 --- a/c++/include/objtools/edit/autodef_mod_combo.hpp +++ b/c++/include/objtools/edit/autodef_mod_combo.hpp @@ -1,7 +1,7 @@ #ifndef OBJTOOLS_EDIT___AUTODEF_MOD_COMBO__HPP #define OBJTOOLS_EDIT___AUTODEF_MOD_COMBO__HPP -/* $Id: autodef_mod_combo.hpp 500380 2016-05-04 13:50:52Z ivanov $ +/* $Id: autodef_mod_combo.hpp 500268 2016-05-03 16:31:45Z bollin $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/objtools/edit/autodef_options.hpp b/c++/include/objtools/edit/autodef_options.hpp index 8b35784d..ddd1f09e 100644 --- a/c++/include/objtools/edit/autodef_options.hpp +++ b/c++/include/objtools/edit/autodef_options.hpp @@ -1,7 +1,7 @@ #ifndef OBJTOOLS_EDIT___AUTODEF_OPTIONS__HPP #define OBJTOOLS_EDIT___AUTODEF_OPTIONS__HPP -/* $Id: autodef_options.hpp 490362 2016-01-25 12:43:11Z bollin $ +/* $Id: autodef_options.hpp 510717 2016-08-15 17:12:40Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -88,10 +88,13 @@ public: eOptionFieldType_KeepMobileElements, eOptionFieldType_KeepPrecursorRNA, eOptionFieldType_KeepRepeatRegion, + eOptionFieldType_KeepMiscRecomb, eOptionFieldType_UseNcRNAComment, eOptionFieldType_SuppressedFeatures, eOptionFieldType_ModifierList, eOptionFieldType_TargetedLocusName, + eOptionFieldType_SuppressMiscFeatureSubfeatures, + eOptionFieldType_CustomFeatureClause, eOptionFieldMax }; @@ -187,7 +190,9 @@ public: AUTODEFBOOLFIELD(KeepMobileElements) AUTODEFBOOLFIELD(KeepPrecursorRNA) AUTODEFBOOLFIELD(KeepRepeatRegion) + AUTODEFBOOLFIELD(KeepMiscRecomb) AUTODEFBOOLFIELD(UseNcRNAComment) + AUTODEFBOOLFIELD(SuppressMiscFeatureSubfeatures) bool IsFeatureSuppressed(CSeqFeatData::ESubtype subtype) const; bool AreAnyFeaturesSuppressed() const { return !m_SuppressedFeatureSubtypes.empty(); } @@ -221,6 +226,9 @@ public: string GetTargetedLocusName() const { return m_TargetedLocusName; } void SetTargetedLocusName(const string& tls) { m_TargetedLocusName = tls; } + string GetCustomFeatureClause() const { return m_CustomFeatureClause; } + void SetCustomFeatureClause(const string& val) { m_CustomFeatureClause = val; } + private: bool m_BooleanFlags[eOptionFieldMax]; @@ -233,6 +241,7 @@ private: typedef vector TSuppressedFeatureSubtypes; TSuppressedFeatureSubtypes m_SuppressedFeatureSubtypes; string m_TargetedLocusName; + string m_CustomFeatureClause; TOrgMods m_OrgMods; TSubSources m_SubSources; @@ -255,6 +264,7 @@ private: CRef x_MakeMaxMods() const; CRef x_MakeTargetedLocusName() const; + CRef x_MakeCustomFeatureClause() const; #define AUTODEFENUMFIELD(Fieldname) \ CRef x_Make##Fieldname() const { \ diff --git a/c++/include/objtools/edit/cds_fix.hpp b/c++/include/objtools/edit/cds_fix.hpp index e781a4f3..cfcdf16a 100644 --- a/c++/include/objtools/edit/cds_fix.hpp +++ b/c++/include/objtools/edit/cds_fix.hpp @@ -1,4 +1,4 @@ -/* $Id: cds_fix.hpp 499447 2016-04-26 14:17:39Z ivanov $ +/* $Id: cds_fix.hpp 496460 2016-03-28 18:04:05Z gotvyans $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/objtools/edit/feattable_edit.hpp b/c++/include/objtools/edit/feattable_edit.hpp index 08542c12..914f1b6a 100644 --- a/c++/include/objtools/edit/feattable_edit.hpp +++ b/c++/include/objtools/edit/feattable_edit.hpp @@ -1,4 +1,4 @@ -/* $Id: feattable_edit.hpp 498135 2016-04-13 17:19:58Z ivanov $ +/* $Id: feattable_edit.hpp 503729 2016-06-07 18:22:50Z ludwigf $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -70,7 +70,10 @@ public: void GenerateMissingMrnaForCds(); void GenerateMissingGeneForMrna(); void GenerateMissingGeneForCds(); - + void GenerateMissingParentFeatures( + bool forEukaryote); + void GenerateMissingParentFeaturesForEukaryote(); + void GenerateMissingParentFeaturesForProkaryote(); unsigned int PendingLocusTagNumber() const { return mLocusTagNumber; } @@ -106,6 +109,12 @@ protected: const CMappedFeat&); void xGenerateMissingGeneForSubtype( CSeqFeatData::ESubtype); + void xGenerateMissingGeneForChoice( + CSeqFeatData::E_Choice); + bool xCreateMissingParentGene( + CMappedFeat); + bool xAdjustExistingParentGene( + CMappedFeat); CSeq_annot& mAnnot; CRef mpScope; diff --git a/c++/include/objtools/edit/gaps_edit.hpp b/c++/include/objtools/edit/gaps_edit.hpp index ddd18c15..89c5e4fd 100644 --- a/c++/include/objtools/edit/gaps_edit.hpp +++ b/c++/include/objtools/edit/gaps_edit.hpp @@ -1,7 +1,7 @@ #ifndef OBJTOOLS_EDIT_GAPS_EDITOR_HPP_INCLUDED #define OBJTOOLS_EDIT_GAPS_EDITOR_HPP_INCLUDED -/* $Id: gaps_edit.hpp 468747 2015-05-27 18:57:10Z gotvyans $ +/* $Id: gaps_edit.hpp 513301 2016-09-09 12:02:54Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -51,25 +51,28 @@ public: // optionally specify linkage evidence or leave it default //CLinkage_evidence::EType typedef set TEvidenceSet; - static - void ConvertNs2Gaps(CSeq_entry& entry, - TSeqPos gapNmin, TSeqPos gap_Unknown_length, - CSeq_gap::EType gap_type = (CSeq_gap::EType) - 1, - const TEvidenceSet& evidences = TEvidenceSet() ); + CGapsEditor(CSeq_gap::EType gap_type, const TEvidenceSet& evidences, + TSeqPos gapNmin, TSeqPos gap_Unknown_length); - static - void ConvertNs2Gaps(CBioseq& bioseq, - TSeqPos gapNmin, TSeqPos gap_Unknown_length, - CSeq_gap::EType gap_type, - const TEvidenceSet& evidences); + void ConvertNs2Gaps(CSeq_entry& entry); - static - void ConvertNs2Gaps(CBioseq::TInst& inst, TSeqPos gap_min); - static - void ConvertNs2Gaps(const CSeq_data& data, TSeqPos len, CDelta_ext& ext, TSeqPos gap_min); - static - CRef CreateGap(CBioseq& bioseq, TSeqPos gap_start, TSeqPos gap_length, - CSeq_gap::EType gap_type, const TEvidenceSet& evidences); + void ConvertNs2Gaps(CBioseq& bioseq); + + void ConvertNs2Gaps(CBioseq::TInst& inst); + void ConvertNs2Gaps(const CSeq_data& data, TSeqPos len, CDelta_ext& ext); + CRef CreateGap(CBioseq& bioseq, TSeqPos gap_start, TSeqPos gap_length); + + void ConvertBioseqToDelta(CBioseq& bioseq); + void AppendGap(CBioseq& bioseq); + void AddBioseqAsLiteral(CBioseq& parent, CBioseq& bioseq); + +private: + void x_SetGapParameters(CDelta_seq& gap); + + CSeq_gap::EType m_gap_type; + TEvidenceSet m_evidences; + TSeqPos m_gapNmin; + TSeqPos m_gap_Unknown_length; }; END_SCOPE(objects) diff --git a/c++/include/objtools/edit/mail_report.hpp b/c++/include/objtools/edit/mail_report.hpp index 55d20bcc..4ed2769b 100644 --- a/c++/include/objtools/edit/mail_report.hpp +++ b/c++/include/objtools/edit/mail_report.hpp @@ -1,4 +1,4 @@ -/* $Id: mail_report.hpp 435187 2014-05-14 14:28:00Z bollin $ +/* $Id: mail_report.hpp 519250 2016-11-14 18:26:30Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -41,7 +41,7 @@ BEGIN_SCOPE(edit) NCBI_XOBJEDIT_EXPORT CRef MakeMailReportPreReport(CSeq_entry_Handle seh); NCBI_XOBJEDIT_EXPORT void MakeMailReportPostReport(CSeq_table& table, CScope& scope); -NCBI_XOBJEDIT_EXPORT string GetReportFromMailReportTable(const CSeq_table& table); +NCBI_XOBJEDIT_EXPORT string GetReportFromMailReportTable(const CSeq_table& table, CScope* scope = NULL); END_SCOPE(edit) diff --git a/c++/include/objtools/edit/publication_edit.hpp b/c++/include/objtools/edit/publication_edit.hpp index 653e36a4..90c6c1a4 100644 --- a/c++/include/objtools/edit/publication_edit.hpp +++ b/c++/include/objtools/edit/publication_edit.hpp @@ -1,6 +1,6 @@ #ifndef OBJTOOLS_EDIT__PUBLICATION_EDIT__HPP #define OBJTOOLS_EDIT__PUBLICATION_EDIT__HPP -/* $Id: publication_edit.hpp 493845 2016-03-02 14:05:29Z ivanov $ +/* $Id: publication_edit.hpp 491874 2016-02-09 20:13:49Z asztalos $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/objtools/edit/rna_edit.hpp b/c++/include/objtools/edit/rna_edit.hpp index bdb5b154..1d65b18a 100644 --- a/c++/include/objtools/edit/rna_edit.hpp +++ b/c++/include/objtools/edit/rna_edit.hpp @@ -1,4 +1,4 @@ -/* $Id: rna_edit.hpp 476471 2015-08-19 13:10:52Z asztalos $ +/* $Id: rna_edit.hpp 513140 2016-09-07 18:34:49Z fukanchi $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -57,7 +57,14 @@ private: CFindITSParser& operator=(const CFindITSParser& value); CRef x_ParseLine(const CTempString &line, CSeq_entry_Handle tse, CBioseq_Handle &bsh, bool &negative, string &msg); - CRef x_CreateMiscRna(const string &accession, const string &comment, CBioseq_Handle bsh); + CRef x_CreateMiscRna(const string &comment, CBioseq_Handle bsh); + CRef x_CreateRRna(const string &comment, CBioseq_Handle bsh); + bool IsLengthTooLarge(const string& str, int max_length, int i, + const vector& starts, + const vector& stops, + const vector& spans, + int bioseq_length); + void GetSpan(const string& str, vector& starts, vector& stops, vector& spans); CBioseq_Handle x_GetBioseqHandleFromIdGuesser(const string &id_str, objects::CSeq_entry_Handle tse); CNcbiIfstream m_istr; CRef m_lr; diff --git a/c++/include/objtools/edit/seq_entry_edit.hpp b/c++/include/objtools/edit/seq_entry_edit.hpp index 5bd74499..43f11c26 100644 --- a/c++/include/objtools/edit/seq_entry_edit.hpp +++ b/c++/include/objtools/edit/seq_entry_edit.hpp @@ -1,7 +1,7 @@ #ifndef OBJTOOLS_EDIT___SEQ_ENTRY_EDIT__HPP #define OBJTOOLS_EDIT___SEQ_ENTRY_EDIT__HPP -/* $Id: seq_entry_edit.hpp 500101 2016-05-02 15:35:32Z ivanov $ +/* $Id: seq_entry_edit.hpp 499249 2016-04-25 12:22:22Z bollin $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/objtools/edit/seqid_guesser.hpp b/c++/include/objtools/edit/seqid_guesser.hpp index 7e171c31..c2fbb227 100644 --- a/c++/include/objtools/edit/seqid_guesser.hpp +++ b/c++/include/objtools/edit/seqid_guesser.hpp @@ -1,4 +1,4 @@ -/* $Id: seqid_guesser.hpp 438363 2014-06-16 13:35:48Z bollin $ +/* $Id: seqid_guesser.hpp 501263 2016-05-12 18:07:30Z bollin $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -29,7 +29,7 @@ #define _SEQID_GUESSER_H_ #include -#include +#include #include #include #include @@ -50,7 +50,7 @@ public: static bool DoesSeqMatchConstraint(CBioseq_Handle bsh, CRef string_constraint); static vector GetIdStrings(CBioseq_Handle bsh); - typedef hash_map > TStringIdHash; + typedef unordered_map > TStringIdHash; private: CSeq_entry_Handle m_SeqEntry; diff --git a/c++/include/objtools/edit/string_constraint.hpp b/c++/include/objtools/edit/string_constraint.hpp index 56e20f9f..39ad85e0 100644 --- a/c++/include/objtools/edit/string_constraint.hpp +++ b/c++/include/objtools/edit/string_constraint.hpp @@ -1,4 +1,4 @@ -/* $Id: string_constraint.hpp 423869 2014-01-09 12:49:24Z bollin $ +/* $Id: string_constraint.hpp 515131 2016-09-28 15:33:44Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -102,7 +102,7 @@ public: const string& GetMatchText() { return m_MatchText; } void SetMatchText(const string& match_text) { m_MatchText = match_text; } void Assign(const CStringConstraint& other); - + bool IsInRange(const string& str, const string &tmp); private: string m_MatchText; EMatchType m_MatchType; diff --git a/c++/include/objtools/edit/struc_comm_field.hpp b/c++/include/objtools/edit/struc_comm_field.hpp index 57a74a68..2eb68c79 100644 --- a/c++/include/objtools/edit/struc_comm_field.hpp +++ b/c++/include/objtools/edit/struc_comm_field.hpp @@ -1,4 +1,4 @@ -/* $Id: struc_comm_field.hpp 493879 2016-03-02 14:17:26Z ivanov $ +/* $Id: struc_comm_field.hpp 492413 2016-02-17 15:49:17Z bollin $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/objtools/error_codes.hpp b/c++/include/objtools/error_codes.hpp index 07d848d5..a38a3e8b 100644 --- a/c++/include/objtools/error_codes.hpp +++ b/c++/include/objtools/error_codes.hpp @@ -1,7 +1,7 @@ #ifndef OBJTOOLS___ERROR_CODES__HPP #define OBJTOOLS___ERROR_CODES__HPP -/* $Id: error_codes.hpp 480266 2015-09-29 15:09:58Z vasilche $ +/* $Id: error_codes.hpp 504655 2016-06-16 21:18:41Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/objtools/format/context.hpp b/c++/include/objtools/format/context.hpp index 1ff0351f..f5246029 100644 --- a/c++/include/objtools/format/context.hpp +++ b/c++/include/objtools/format/context.hpp @@ -1,7 +1,7 @@ #ifndef OBJTOOLS_FORMAT___CONTEXT__HPP #define OBJTOOLS_FORMAT___CONTEXT__HPP -/* $Id: context.hpp 495720 2016-03-21 14:22:27Z ivanov $ +/* $Id: context.hpp 511385 2016-08-22 13:31:32Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -236,6 +236,7 @@ public: const SAnnotSelector* GetAnnotSelector(void) const; SAnnotSelector& SetAnnotSelector(void); const CSeq_loc* GetMasterLocation(void) const; + const bool GetSGS(void) const; bool IsGenbankFormat(void) const; bool HasOperon(void) const; @@ -429,7 +430,8 @@ public: const CSubmit_block* GetSubmitBlock(void) const { return m_Submit; } void SetSubmit(const CSubmit_block& sub) { m_Submit = ⊂ } - CFlatFileConfig& GetConfig(void) { return m_Cfg; } + const CFlatFileConfig& GetConfig(void) const { return m_Cfg; } + CFlatFileConfig& SetConfig(void) { return m_Cfg; } const SAnnotSelector* GetAnnotSelector(void) const; SAnnotSelector& SetAnnotSelector(void); @@ -442,6 +444,9 @@ public: feature::CFeatTree* GetFeatTree(void) { return m_FeatTree; } void SetFeatTree(feature::CFeatTree* tree) { m_FeatTree.Reset(tree); } + const bool GetSGS(void) const { return m_SmallGenomeSet; } + void SetSGS(const bool sgs) { m_SmallGenomeSet = sgs; } + void AddSection(TSection& section) { m_Sections.push_back(section); } void Reset(void); @@ -455,6 +460,7 @@ private: auto_ptr m_Selector; CConstRef m_Loc; CRef m_FeatTree; + bool m_SmallGenomeSet; }; ///////////////////////////////////////////////////////////////////////////// @@ -673,6 +679,12 @@ const CSeq_loc* CBioseqContext::GetMasterLocation(void) const } +inline +const bool CBioseqContext::GetSGS(void) const +{ + return m_FFCtx.GetSGS(); +} + inline CMolInfo::TTech CBioseqContext::GetTech(void) const { @@ -748,6 +760,7 @@ void CFlatFileContext::Reset(void) m_Submit.Reset(); m_Selector.reset(); m_Loc.Reset(); + m_SmallGenomeSet = false; } diff --git a/c++/include/objtools/format/flat_file_config.hpp b/c++/include/objtools/format/flat_file_config.hpp index 913aec09..3942f53d 100644 --- a/c++/include/objtools/format/flat_file_config.hpp +++ b/c++/include/objtools/format/flat_file_config.hpp @@ -1,7 +1,7 @@ #ifndef OBJTOOLS_FORMAT___FLAT_FILE_CONFIG__HPP #define OBJTOOLS_FORMAT___FLAT_FILE_CONFIG__HPP -/* $Id: flat_file_config.hpp 500529 2016-05-05 14:28:05Z ivanov $ +/* $Id: flat_file_config.hpp 507549 2016-07-19 22:29:29Z kans $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -70,9 +70,48 @@ class CWGSItem; class CTSAItem; class CEndSectionItem; class IFlatItem; +class CSeq_id; +class CSeq_loc; +struct SModelEvidance; // --- Flat File configuration class +// NEW_HTML_FMT define enables new interceptor interface for HTML links generation +//#define NEW_HTML_FMT + +#ifdef NEW_HTML_FMT + +class IHTMLFormatter: public CObject +{ +public: + virtual ~IHTMLFormatter() {}; + + virtual void FormatProteinId(string& str, const CSeq_id& seq_id, const string& prot_id) const = 0; + virtual void FormatNucSearch(CNcbiOstream& os, const string& id) const = 0; + virtual void FormatNucId(string& str, const CSeq_id& seq_id, TIntId gi, const string& acc_id) const = 0; + virtual void FormatTaxid(string& str, const int taxid, const string& taxname) const = 0; + virtual void FormatLocation(string& str, const CSeq_loc& loc, TIntId gi, const string& visible_text) const = 0; + virtual void FormatModelEvidence(string& str, const SModelEvidance& me) const = 0; + virtual void FormatTranscript(string& str, const string& name) const = 0; + virtual void FormatGeneralId(CNcbiOstream& os, const string& id) const = 0; +}; + +class CHTMLEmptyFormatter : public IHTMLFormatter +{ +public: + virtual ~CHTMLEmptyFormatter() {}; + + void FormatProteinId(string& str, const CSeq_id& seq_id, const string& prot_id) const; + void FormatNucSearch(CNcbiOstream& os, const string& id) const; + void FormatNucId(string& str, const CSeq_id& seq_id, TIntId gi, const string& acc_id) const; + void FormatTaxid(string& str, const int taxid, const string& taxname) const; + void FormatLocation(string& str, const CSeq_loc& loc, TIntId gi, const string& visible_text) const; + void FormatModelEvidence(string& str, const SModelEvidance& me) const; + void FormatTranscript(string& str, const string& name) const; + void FormatGeneralId(CNcbiOstream& os, const string& id) const; +}; +#endif + class NCBI_FORMAT_EXPORT CFlatFileConfig { public: @@ -146,7 +185,8 @@ public: enum ECustom { // additional customization flags - fHideProteinID = 1 + fHideProteinID = 1, + fHideGI = 1 << 1 }; enum EView { @@ -350,6 +390,17 @@ public: // destructor ~CFlatFileConfig(void); +#ifdef NEW_HTML_FMT + void SetHTMLFormatter(CRef html_fmt) + { + m_html_formatter = html_fmt; + } + const IHTMLFormatter& GetHTMLFormatter() const + { + return *m_html_formatter; + } +#endif + // -- Format // getters const TFormat& GetFormat(void) const { return m_Format; } @@ -537,10 +588,12 @@ public: // getters const TCustom& GetCustom(void) const { return m_Custom; } bool HideProteinID (void) const; + bool HideGI (void) const; // setters void SetCustom(const TCustom& custom) { m_Custom = custom; } CFlatFileConfig& SetHideProteinID (bool val = true); + CFlatFileConfig& SetHideGI (bool val = true); // adjust mode dependant flags for RefSeq void SetRefSeqConventions(void); @@ -678,6 +731,9 @@ private: const ICanceled * m_pCanceledCallback; // instance does NOT own it bool m_BasicCleanup; TCustom m_Custom; +#ifdef NEW_HTML_FMT + CRef m_html_formatter; +#endif }; @@ -763,6 +819,7 @@ CUSTOM_ARG_GET(x) \ CUSTOM_ARG_SET(x) CUSTOM_ARG_IMP(HideProteinID) +CUSTOM_ARG_IMP(HideGI) #undef FLAG_ARG_IMP #undef FLAG_ARG_GET diff --git a/c++/include/objtools/format/gather_items.hpp b/c++/include/objtools/format/gather_items.hpp index 6d52fb06..47397db4 100644 --- a/c++/include/objtools/format/gather_items.hpp +++ b/c++/include/objtools/format/gather_items.hpp @@ -1,7 +1,7 @@ #ifndef OBJTOOLS_FORMAT___GATHER_ITEMS__HPP #define OBJTOOLS_FORMAT___GATHER_ITEMS__HPP -/* $Id: gather_items.hpp 495720 2016-03-21 14:22:27Z ivanov $ +/* $Id: gather_items.hpp 494523 2016-03-08 01:22:14Z kans $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/objtools/format/genbank_gather.hpp b/c++/include/objtools/format/genbank_gather.hpp index 28d27695..d115df88 100644 --- a/c++/include/objtools/format/genbank_gather.hpp +++ b/c++/include/objtools/format/genbank_gather.hpp @@ -1,7 +1,7 @@ #ifndef OBJTOOLS_FORMAT___GENBANK_GATHER__HPP #define OBJTOOLS_FORMAT___GENBANK_GATHER__HPP -/* $Id: genbank_gather.hpp 495730 2016-03-21 14:26:04Z ivanov $ +/* $Id: genbank_gather.hpp 495539 2016-03-17 23:42:34Z kans $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/objtools/format/item_formatter.hpp b/c++/include/objtools/format/item_formatter.hpp index 9c899147..91eafbaa 100644 --- a/c++/include/objtools/format/item_formatter.hpp +++ b/c++/include/objtools/format/item_formatter.hpp @@ -1,7 +1,7 @@ #ifndef OBJTOOLS_FORMAT___ITEM_FORMATTER_HPP #define OBJTOOLS_FORMAT___ITEM_FORMATTER_HPP -/* $Id: item_formatter.hpp 360035 2012-04-19 13:43:48Z kornbluh $ +/* $Id: item_formatter.hpp 506085 2016-07-01 14:25:26Z gotvyans $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -116,7 +116,8 @@ public: // Context void SetContext(CFlatFileContext& ctx); - CFlatFileContext& GetContext(void) { return *m_Ctx; } + const CFlatFileContext& GetContext(void) const + { return *m_Ctx; } protected: typedef NStr::TWrapFlags TWrapFlags; diff --git a/c++/include/objtools/format/items/comment_item.hpp b/c++/include/objtools/format/items/comment_item.hpp index 82f3fedf..97045309 100644 --- a/c++/include/objtools/format/items/comment_item.hpp +++ b/c++/include/objtools/format/items/comment_item.hpp @@ -1,7 +1,7 @@ #ifndef OBJTOOLS_FORMAT_ITEMS___COMMENT_ITEM__HPP #define OBJTOOLS_FORMAT_ITEMS___COMMENT_ITEM__HPP -/* $Id: comment_item.hpp 495720 2016-03-21 14:22:27Z ivanov $ +/* $Id: comment_item.hpp 506085 2016-07-01 14:25:26Z gotvyans $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -127,8 +127,8 @@ public: eGenomeBuildComment_No = 0, eGenomeBuildComment_Yes }; - static string GetStringForRefTrack(const CUser_object& uo, - const CBioseq_Handle& seq, ECommentFormat format = eFormat_Text, + static string GetStringForRefTrack(const CBioseqContext& ctx, const CUser_object& uo, + const CBioseq_Handle& seq, EGenomeBuildComment eGenomeBuildComment = eGenomeBuildComment_Yes ); static string GetStringForRefSeqGenome(const CUser_object& uo); @@ -138,8 +138,7 @@ public: static string GetStringForMolinfo(const CMolInfo& mi, CBioseqContext& ctx); static string GetStringForHTGS(CBioseqContext& ctx); static string GetStringForUnordered(CBioseqContext& ctx); - static string GetStringForModelEvidance(const SModelEvidance& me, - ECommentFormat format = eFormat_Text); + static string GetStringForModelEvidance(const CBioseqContext& ctx, const SModelEvidance& me); static TRefTrackStatus GetRefTrackStatus(const CUser_object& uo, string* st = 0); static string GetStringForEncode(CBioseqContext& ctx); diff --git a/c++/include/objtools/format/items/feature_item.hpp b/c++/include/objtools/format/items/feature_item.hpp index 89bf5310..078e044f 100644 --- a/c++/include/objtools/format/items/feature_item.hpp +++ b/c++/include/objtools/format/items/feature_item.hpp @@ -1,7 +1,7 @@ #ifndef OBJTOOLS_FORMAT_ITEMS___FLAT_FEATURE__HPP #define OBJTOOLS_FORMAT_ITEMS___FLAT_FEATURE__HPP -/* $Id: feature_item.hpp 463068 2015-03-24 16:16:20Z gotvyans $ +/* $Id: feature_item.hpp 512461 2016-08-31 11:22:40Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -257,13 +257,24 @@ protected: void x_AddFTableBiosrcQuals(const CBioSource& src); void x_AddFTableDbxref(const CSeq_feat::TDbxref& dbxref); void x_AddFTableExtQuals(const CSeq_feat::TExt& ext); - void x_AddFTableQual(const string& name, const string& val = kEmptyStr, - CFormatQual::ETrim trim = CFormatQual::eTrim_Normal) + const string kProteinId = "protein_id"; + const string kTranscriptId = "transcript_id"; + const string& x_GetFtableNameAlias(const string& name) + { + if (NStr::Equal(name, "orig_protein_id")) { + return kProteinId; + } else if (NStr::Equal(name, "orig_transcript_id")) { + return kTranscriptId; + } else { + return name; + } + } + void x_AddFTableQual(const string& name, const string& val = kEmptyStr, + CFormatQual::ETrim trim = CFormatQual::eTrim_Normal) { CFormatQual::EStyle style = val.empty() ? CFormatQual::eEmpty : CFormatQual::eQuoted; - m_FTableQuals.push_back(CRef(new CFormatQual(name, val, style, 0, trim))); + m_FTableQuals.push_back(CRef(new CFormatQual(x_GetFtableNameAlias(name), val, style, 0, trim))); } - // typdef typedef CQualContainer TQuals; typedef TQuals::iterator TQI; diff --git a/c++/include/objtools/format/items/flat_qual_slots.hpp b/c++/include/objtools/format/items/flat_qual_slots.hpp index 744e284a..1574fa00 100644 --- a/c++/include/objtools/format/items/flat_qual_slots.hpp +++ b/c++/include/objtools/format/items/flat_qual_slots.hpp @@ -1,7 +1,7 @@ #ifndef OBJTOOLS_FLAT___FLAT_QUAL_SLOTS__HPP #define OBJTOOLS_FLAT___FLAT_QUAL_SLOTS__HPP -/* $Id: flat_qual_slots.hpp 449759 2014-10-20 19:44:53Z kans $ +/* $Id: flat_qual_slots.hpp 514604 2016-09-22 18:31:56Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -135,6 +135,7 @@ enum EFeatureQualifier { eFQ_rad_map, eFQ_region, eFQ_region_name, + eFQ_recombination_class, eFQ_regulatory_class, eFQ_replace, eFQ_ribosomal_slippage, diff --git a/c++/include/objtools/format/items/gene_finder.hpp b/c++/include/objtools/format/items/gene_finder.hpp index af6bd70a..825653c6 100644 --- a/c++/include/objtools/format/items/gene_finder.hpp +++ b/c++/include/objtools/format/items/gene_finder.hpp @@ -1,4 +1,4 @@ -/* $Id: gene_finder.hpp 493806 2016-03-02 13:53:13Z ivanov $ +/* $Id: gene_finder.hpp 491036 2016-02-01 16:07:35Z bollin $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/objtools/format/items/locus_item.hpp b/c++/include/objtools/format/items/locus_item.hpp index ee987385..6aec4db7 100644 --- a/c++/include/objtools/format/items/locus_item.hpp +++ b/c++/include/objtools/format/items/locus_item.hpp @@ -1,7 +1,7 @@ #ifndef OBJTOOLS_FORMAT_ITEMS___LOCUS_ITEM__HPP #define OBJTOOLS_FORMAT_ITEMS___LOCUS_ITEM__HPP -/* $Id: locus_item.hpp 413681 2013-09-17 17:28:11Z kans $ +/* $Id: locus_item.hpp 501627 2016-05-17 17:47:33Z kans $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -65,6 +65,7 @@ public: void Format(IFormatter& formatter, IFlatTextOStream& text_os) const; const string& GetName (void) const; + const string& GetFullName (void) const; size_t GetLength (void) const; TStrand GetStrand (void) const; TBiomol GetBiomol (void) const; @@ -92,6 +93,7 @@ private: // data string m_Name; + string m_FullName; size_t m_Length; TStrand m_Strand; TBiomol m_Biomol; @@ -112,6 +114,13 @@ const string& CLocusItem::GetName(void) const } +inline +const string& CLocusItem::GetFullName(void) const +{ + return m_FullName; +} + + inline size_t CLocusItem::GetLength(void) const { diff --git a/c++/include/objtools/format/items/tsa_item.hpp b/c++/include/objtools/format/items/tsa_item.hpp index f9f4236f..cbd7be51 100644 --- a/c++/include/objtools/format/items/tsa_item.hpp +++ b/c++/include/objtools/format/items/tsa_item.hpp @@ -1,7 +1,7 @@ #ifndef OBJTOOLS_FORMAT_ITEMS___TSA_ITEM__HPP #define OBJTOOLS_FORMAT_ITEMS___TSA_ITEM__HPP -/* $Id: tsa_item.hpp 495730 2016-03-21 14:26:04Z ivanov $ +/* $Id: tsa_item.hpp 495539 2016-03-17 23:42:34Z kans $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/objtools/readers/aln_reader.hpp b/c++/include/objtools/readers/aln_reader.hpp index 9fad2574..0050f34a 100644 --- a/c++/include/objtools/readers/aln_reader.hpp +++ b/c++/include/objtools/readers/aln_reader.hpp @@ -1,7 +1,7 @@ #ifndef OBJTOOLS_READERS___ALN_READER__HPP #define OBJTOOLS_READERS___ALN_READER__HPP -/* $Id: aln_reader.hpp 438196 2014-06-13 13:41:41Z bollin $ +/* $Id: aln_reader.hpp 505117 2016-06-22 15:06:00Z foleyjp $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -49,7 +49,8 @@ public: eAlnErr_NoError = 0, eAlnErr_Fatal, eAlnErr_BadData, - eAlnErr_BadFormat + eAlnErr_BadFormat, + eAlnErr_BadChar } EAlnErr; // constructor @@ -82,7 +83,6 @@ private: /// class CAlnReader supports importing a large variety of text-based /// alignment formats into standard data structures. /// - class NCBI_XOBJREAD_EXPORT CAlnReader { public: @@ -93,11 +93,51 @@ public: eAlpha_Protein }; + class CAlnErrorContainer + { + + private: + list errors; + map error_count; + + public: + size_t GetErrorCount(CAlnError::EAlnErr category) const + { + auto it = error_count.find(category); + if (it != error_count.end()) { + return it->second; + } + return 0; + } + + void clear(void) { + errors.clear(); + error_count.clear(); + } + + void push_back(const CAlnError& error) { + errors.push_back(error); + ++error_count[error.GetCategory()]; + } + + size_t size(void) const { + return errors.size(); + } + + typedef list TErrors; + typedef TErrors::const_iterator const_iterator; + const_iterator begin(void) const { return errors.begin(); } + const_iterator end(void) const { return errors.end(); } + }; + // error messages - typedef vector TErrorList; + typedef CAlnErrorContainer TErrorList; // constructor - CAlnReader(CNcbiIstream& is) : m_IS(is), m_ReadDone(false) { m_Errors.clear(); }; + // defaults to protein alphabet and A2M gap characters + CAlnReader(CNcbiIstream& is) : m_IS(is), m_ReadDone(false) { m_Errors.clear(); + SetAlphabet(eAlpha_Protein); + SetAllGap(".-"); }; // destructor ~CAlnReader(void); @@ -110,6 +150,7 @@ public: string& SetAlphabet(void); void SetAlphabet(const string& value); void SetAlphabet(EAlphabet alpha); + bool IsAlphabet(EAlphabet alpha) const; const string& GetBeginningGap(void) const; string& SetBeginningGap(void); @@ -165,7 +206,6 @@ public: private: - /// Prohibit copy constructor and assignment operator CAlnReader(const CAlnReader& value); CAlnReader& operator=(const CAlnReader& value); @@ -310,6 +350,26 @@ void CAlnReader::SetAlphabet(EAlphabet alpha) } +inline +bool CAlnReader::IsAlphabet(EAlphabet alpha) const +{ + switch (alpha) { + case eAlpha_Nucleotide: + return (m_Alphabet == "ABCDGHKMNRSTUVWXYabcdghkmnrstuvwxy"); + + case eAlpha_Protein: + return (m_Alphabet == "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); + + default: + return false; + } + return false; +} + + + + + inline void CAlnReader::SetAllGap(const string& value) { diff --git a/c++/include/objtools/readers/bed_reader.hpp b/c++/include/objtools/readers/bed_reader.hpp index e0351ea9..6f56d800 100644 --- a/c++/include/objtools/readers/bed_reader.hpp +++ b/c++/include/objtools/readers/bed_reader.hpp @@ -1,4 +1,4 @@ -/* $Id: bed_reader.hpp 472138 2015-07-07 16:07:55Z grichenk $ +/* $Id: bed_reader.hpp 515629 2016-10-04 17:46:33Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -167,6 +167,7 @@ public: public: enum EBedFlags { fThreeFeatFormat = 1<<8, + fDirectedFeatureModel = 1<<9, }; typedef int TFlags; @@ -209,11 +210,15 @@ protected: virtual bool xParseTrackLine( const string&, ILineErrorListener*); - + + bool xParseFeature( + const string&, + CRef&, + ILineErrorListener*); + bool xParseFeature( const vector&, CRef&, - unsigned int, ILineErrorListener*); bool xParseFeatureUserFormat( @@ -224,7 +229,6 @@ protected: bool xParseFeatureThreeFeatFormat( const vector&, CRef&, - unsigned int, ILineErrorListener*); bool xAppendFeatureChrom( @@ -245,6 +249,29 @@ protected: unsigned int, ILineErrorListener*); + bool xParseFeatureGeneModelFormat( + const vector&, + CRef&, + ILineErrorListener*); + + bool xAppendFeatureGene( + const vector&, + CRef&, + unsigned int, + ILineErrorListener*); + + bool xAppendFeatureRna( + const vector&, + CRef&, + unsigned int, + ILineErrorListener*); + + bool xAppendFeatureCds( + const vector&, + CRef&, + unsigned int, + ILineErrorListener*); + void x_SetFeatureLocation( CRef&, const vector&); @@ -252,29 +279,50 @@ protected: void xSetFeatureLocationChrom( CRef&, const vector&); + void xSetFeatureLocationGene( + CRef&, + const vector&); void xSetFeatureLocationThick( CRef&, const vector&); + void xSetFeatureLocationCds( + CRef&, + const vector&); void xSetFeatureLocationBlock( CRef&, const vector&); + void xSetFeatureLocationRna( + CRef&, + const vector&); void xSetFeatureIdsChrom( CRef&, const vector&, unsigned int); + void xSetFeatureIdsGene( + CRef&, + const vector&, + unsigned int); void xSetFeatureIdsThick( CRef&, const vector&, unsigned int); + void xSetFeatureIdsCds( + CRef&, + const vector&, + unsigned int); void xSetFeatureIdsBlock( CRef&, const vector&, unsigned int); + void xSetFeatureIdsRna( + CRef&, + const vector&, + unsigned int); void xSetFeatureBedData( CRef&, @@ -284,24 +332,51 @@ protected: CRef&, const vector&); + void xSetFeatureScore( + CRef, + const vector&); + void xSetFeatureColor( + CRef, + const vector&); + + void xSetFeatureColorFromItemRgb( + CRef, + const string&); + void xSetFeatureColorFromScore( + CRef, + const string&); + void xSetFeatureColorByStrand( + CRef, + const string&, + ENa_strand); + void xSetFeatureColorDefault( + CRef); + bool xContainsThickFeature( const vector&) const; bool xContainsBlockFeature( const vector&) const; + bool xContainsRnaFeature( + const vector&) const; + + bool xContainsCdsFeature( + const vector&) const; + ENa_strand xGetStrand( const vector&) const; + virtual void xAssignBedColumnCount( + CSeq_annot&); + void x_SetFeatureDisplayData( CRef&, const vector&); - virtual void xSetTrackData( + virtual void xPostProcessAnnot( CRef&, - CRef&, - const string&, - const string&); + ILineErrorListener*); CRef< CSeq_annot > x_AppendAnnot( vector< CRef< CSeq_annot > >& ); @@ -328,6 +403,7 @@ protected: string m_currentId; vector::size_type m_columncount; + unsigned int m_CurrentFeatureCount; bool m_usescore; unsigned int m_CurBatchSize; const unsigned int m_MaxBatchSize; diff --git a/c++/include/objtools/readers/fasta.hpp b/c++/include/objtools/readers/fasta.hpp index 9fc3aaf7..72e2d90b 100644 --- a/c++/include/objtools/readers/fasta.hpp +++ b/c++/include/objtools/readers/fasta.hpp @@ -1,7 +1,7 @@ #ifndef OBJTOOLS_READERS___FASTA__HPP #define OBJTOOLS_READERS___FASTA__HPP -/* $Id: fasta.hpp 499434 2016-04-26 14:13:36Z ivanov $ +/* $Id: fasta.hpp 515641 2016-10-04 17:51:17Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -190,13 +190,6 @@ public: void IgnoreProblem(ILineError::EProblem problem); -protected: - enum EInternalFlags { - fAligning = 0x40000000, - fInSegSet = 0x20000000 - }; - - typedef CTempString TStr; struct SLineTextAndLoc { SLineTextAndLoc( const string & sLineText, @@ -208,13 +201,50 @@ protected: TSeqPos m_iLineNum; }; + using TIgnoredProblems = vector; + using TSeqTitles = vector; + typedef CTempString TStr; + + struct SDefLineParseInfo { + TReaderFlags fBaseFlags; + TFlags fFastaFlags; + size_t maxIdLength; + size_t lineNumber; + }; + + static void ParseDefLine(const TStr& defLine, + const SDefLineParseInfo& info, + const TIgnoredProblems& ignoredErrors, + list>& ids, + bool& hasRange, + TSeqPos& rangeStart, + TSeqPos& rangeEnd, + TSeqTitles& seqTitles, + ILineErrorListener* pMessageListener); + +protected: + enum EInternalFlags { + fAligning = 0x40000000, + fInSegSet = 0x20000000 + }; + + virtual CRef x_ReadSegSet(ILineErrorListener * pMessageListener); virtual void ParseDefLine (const TStr& s, ILineErrorListener * pMessageListener); - virtual bool ParseIDs (const TStr& s, ILineErrorListener * pMessageListener); - virtual size_t ParseRange (const TStr& s, TSeqPos& start, TSeqPos& end, ILineErrorListener * pMessageListener); + + virtual bool ParseIDs(const TStr& s, ILineErrorListener * pMessageListener); + + static bool ParseIDs (const TStr& s, + const SDefLineParseInfo& info, + const TIgnoredProblems& ignoredErrors, + list>& ids, + ILineErrorListener* pMessageListener); + + static size_t ParseRange (const TStr& s, TSeqPos& start, TSeqPos& end, ILineErrorListener * pMessageListener); virtual void ParseTitle (const SLineTextAndLoc & lineInfo, ILineErrorListener * pMessageListener); - virtual bool IsValidLocalID(const TStr& s); + virtual bool IsValidLocalID(const TStr& s) const; + static bool IsValidLocalID(const TStr& idString, TFlags fFastaFlags); virtual void GenerateID (void); virtual void ParseDataLine (const TStr& s, ILineErrorListener * pMessageListener); virtual void CheckDataLine (const TStr& s, ILineErrorListener * pMessageListener); @@ -227,12 +257,24 @@ protected: virtual bool CreateWarningsForSeqDataInTitle( const TStr& sLineText, TSeqPos iLineNum, - ILineErrorListener * pMessageListener); + ILineErrorListener * pMessageListener) const; + static bool ExcessiveSeqDataInTitle(const string& title, + TFlags fFastaFlags); virtual void PostWarning(ILineErrorListener * pMessageListener, EDiagSev _eSeverity, size_t _uLineNum, CTempString _MessageStrmOps, CObjReaderParseException::EErrCode _eErrCode, ILineError::EProblem _eProblem, - CTempString _sFeature, CTempString _sQualName, CTempString _sQualValue); + CTempString _sFeature, CTempString _sQualName, CTempString _sQualValue) const; + + static void PostWarning(ILineErrorListener* pMessageListener, + const size_t lineNumber, + const string& errMessage, + CObjReaderParseException::EErrCode errCode); + + static void PostError(ILineErrorListener* pMessageListener, + const size_t lineNumber, + const string& errMessage, + CObjReaderParseException::EErrCode errCode); typedef int TRowNum; typedef map TSubMap; @@ -277,7 +319,7 @@ protected: std::string x_NucOrProt(void) const; -private: +protected: struct SGap : public CObject { enum EKnownSize { eKnownSize_No, @@ -321,6 +363,7 @@ private: typedef CRef TGapRef; typedef vector TGaps; typedef set TIDTracker; + CRef m_LineReader; stack m_Flags; @@ -352,7 +395,7 @@ private: SGap::TLinkEvidSet m_gap_linkage_evidence; SGap::TNullableGapType m_gap_type; - vector m_CurrentSeqTitles; + TSeqTitles m_CurrentSeqTitles; CRef m_pModFilter; std::vector m_ignorable; }; @@ -381,7 +424,7 @@ public: void SetCounter(TInt n) { m_Counter.Set(n); } void SetSuffix (const string& s) { m_Suffix = s; } -private: +protected: string m_Prefix, m_Suffix; CAtomicCounter_WithAutoInit m_Counter; }; diff --git a/c++/include/objtools/readers/gff2_data.hpp b/c++/include/objtools/readers/gff2_data.hpp index 85483a3f..1c4b42c8 100644 --- a/c++/include/objtools/readers/gff2_data.hpp +++ b/c++/include/objtools/readers/gff2_data.hpp @@ -1,4 +1,4 @@ -/* $Id: gff2_data.hpp 489339 2016-01-12 15:46:54Z ludwigf $ +/* $Id: gff2_data.hpp 512392 2016-08-30 17:42:36Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -100,7 +100,8 @@ public: return m_pePhase != 0; }; bool IsAlignmentRecord() const { - if (NStr::StartsWith(Type(), "match")) { + if (NStr::StartsWith(Type(), "match") || + NStr::EndsWith(Type(), "_match")) { return true; } return false; @@ -166,6 +167,15 @@ protected: virtual bool xInitFeatureData( int, CRef ) const; + virtual bool xInitFeatureDataBond( + int, + CRef ) const; + virtual bool xInitFeatureDataNcrna( + int, + CRef ) const; + virtual bool xInitFeatureDataSpecialImp( + int, + CRef ) const; virtual bool xUpdateFeatureData( int, diff --git a/c++/include/objtools/readers/gff2_reader.hpp b/c++/include/objtools/readers/gff2_reader.hpp index 29049b93..53f4248b 100644 --- a/c++/include/objtools/readers/gff2_reader.hpp +++ b/c++/include/objtools/readers/gff2_reader.hpp @@ -1,4 +1,4 @@ - /* $Id: gff2_reader.hpp 497078 2016-04-04 14:59:49Z ivanov $ + /* $Id: gff2_reader.hpp 520506 2016-11-29 16:03:04Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include #include @@ -65,6 +67,8 @@ public: } TFlags; typedef map > IdToFeatureMap; + + using TScoreValueMap = map>; public: @@ -86,6 +90,11 @@ public: unsigned int ObjectType() const { return OT_SEQENTRY; }; + virtual CRef< CSeq_annot > + ReadSeqAnnot( + ILineReader& lr, + ILineErrorListener* pErrors=0 ); + CRef< CSeq_entry > ReadSeqEntry( ILineReader&, @@ -132,10 +141,30 @@ public: const string&, CRef< CAnnotdesc >& ); - virtual bool x_ParseStructuredCommentGff( - const string&, - CRef< CAnnotdesc >& ); + virtual bool xParseStructuredComment( + const string&); + virtual bool xParseFeature( + const string&, + CRef&, + ILineErrorListener*); + + virtual bool xParseAlignment( + const string&, + CRef&, + ILineErrorListener*); + + virtual bool xIsCurrentDataType( + const string&); + + virtual void xPostProcessAnnot( + CRef&, + ILineErrorListener*); + + virtual void xAssignAnnotId( + CRef&, + const string& = ""); + virtual bool x_ParseDataGff( const string&, TAnnots&, @@ -146,6 +175,35 @@ public: TAnnots&, ILineErrorListener*); + virtual bool x_ParseAlignmentGff( + const string& strLine, + list& id_list, + map>>& alignments); + + void x_GetAlignmentScores( + const CSeq_align& alignment, + TScoreValueMap& score_values); + // map>& score_values); + + void x_FindMatchingScores( + const TScoreValueMap& scores_1, + const TScoreValueMap& scores_2, + set& matching_scores); + + virtual bool x_CreateAlignment( + const CGff2Record& gff, + CRef& pAlign); + + bool x_MergeAlignments( + const list>& alignment_list, + CRef& processed); + + void x_ProcessAlignmentsGff( + const list& id_list, + const map>>& alignments, + CRef pAnnot); + + virtual bool x_ParseAlignmentGff( const string&, TAnnots&); @@ -162,7 +220,8 @@ public: virtual bool x_UpdateAnnotAlignment( const CGff2Record&, - CRef< CSeq_annot > ); + CRef< CSeq_annot >, + ILineErrorListener* =0); virtual bool xAddFeatureToAnnot( CRef< CSeq_feat >, @@ -226,7 +285,7 @@ public: const string&, CRef< CSeq_feat >& ); - bool x_GetParentFeature( + bool xGetParentFeature( const CSeq_feat&, CRef< CSeq_feat >& ); @@ -247,6 +306,13 @@ public: const CGff2Record&, CRef ); + bool xSetDensegStarts( + const vector& gapParts, + bool oppositeStrands, + size_t targetStart, + const CGff2Record& gff, + CSeq_align::C_Segs::TDenseg& denseg); + virtual bool xReadInit(); virtual bool xAnnotPostProcess( @@ -254,6 +320,21 @@ public: virtual bool xGenerateParentChildXrefs( CRef); + + bool xUpdateSplicedAlignment(const CGff2Record& gff, + CRef pAlign) const; + + bool xUpdateSplicedSegment(const CGff2Record& gff, + CSpliced_seg& segment) const; + + bool xSetSplicedExon( + const CGff2Record& gff, + CRef pExon) const; + + bool xGetTargetParts(const CGff2Record& gff, + vector& targetParts) const; + + bool xAlignmentSetSegment( const CGff2Record&, CRef ); @@ -310,10 +391,11 @@ protected: // data: // protected: -// TFlags m_iFlags; ILineErrorListener* m_pErrors; - CRef m_CurrentTrackInfo; + unsigned int mCurrentFeatureCount; + bool mParsingAlignment; CRef m_CurrentBrowserInfo; + CRef m_CurrentTrackInfo; }; END_SCOPE(objects) diff --git a/c++/include/objtools/readers/gff3_reader.hpp b/c++/include/objtools/readers/gff3_reader.hpp index 3c5df52d..233258e0 100644 --- a/c++/include/objtools/readers/gff3_reader.hpp +++ b/c++/include/objtools/readers/gff3_reader.hpp @@ -1,4 +1,4 @@ - /* $Id: gff3_reader.hpp 497078 2016-04-04 14:59:49Z ivanov $ + /* $Id: gff3_reader.hpp 506819 2016-07-12 14:49:11Z ludwigf $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -59,6 +59,9 @@ public: CGff3ReadRecord() {}; ~CGff3ReadRecord() {}; + virtual bool AssignFromGff( + const string& ); + protected: string x_NormalizedAttributeKey( const string& ); @@ -150,7 +153,7 @@ protected: string xNextGenericId(); - void xVerifyExonLocation( + bool xVerifyExonLocation( const string&, const CGff2Record&, ILineErrorListener*); diff --git a/c++/include/objtools/readers/gff3_sofa.hpp b/c++/include/objtools/readers/gff3_sofa.hpp index f5d83b75..771fdf2a 100644 --- a/c++/include/objtools/readers/gff3_sofa.hpp +++ b/c++/include/objtools/readers/gff3_sofa.hpp @@ -1,4 +1,4 @@ -/* $Id: gff3_sofa.hpp 403742 2013-06-18 15:26:09Z grichenk $ +/* $Id: gff3_sofa.hpp 520685 2016-11-30 18:53:22Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -40,8 +40,33 @@ BEGIN_NCBI_SCOPE BEGIN_SCOPE(objects) // namespace ncbi::objects:: -typedef map< string, CFeatListItem > TLookupSofaToGenbank; +// ---------------------------------------------------------------------------- +class CompareNoCase +// ---------------------------------------------------------------------------- +{ +public: + bool operator()(string x, const string& y) const { + string::const_iterator pX = x.begin(); + string::const_iterator pY = y.begin(); + while (pX != x.end() && pY != y.end() && + tolower(*pX) == tolower(*pY)) { + ++pX; + ++pY; + } + if (pX == x.end()) { + return (pY != y.end()); + } + if (pY == y.end()) { + return false; + } + return (tolower(*pX) < tolower(*pY)); + } +}; + +typedef map< string, CFeatListItem, CompareNoCase > TLookupSofaToGenbank; typedef TLookupSofaToGenbank::const_iterator TLookupSofaToGenbankCit; +typedef map< string, string, CompareNoCase > TAliasToTerm; +typedef TAliasToTerm::const_iterator TAliasToTermCit; // ---------------------------------------------------------------------------- class NCBI_XOBJREAD_EXPORT CGff3SofaTypes @@ -54,13 +79,20 @@ public: ~CGff3SofaTypes(); CSeqFeatData::ESubtype MapSofaTermToGenbankType( - const string& ); + const string&); CFeatListItem MapSofaTermToFeatListItem( - const string& ); + const string&); + + string MapSofaAliasToSofaTerm( + const string&); + + bool IsStringSofaAlias( + const string&); protected: static CSafeStatic m_Lookup; + static CSafeStatic m_Aliases; }; // ---------------------------------------------------------------------------- diff --git a/c++/include/objtools/readers/gtf_reader.hpp b/c++/include/objtools/readers/gtf_reader.hpp index 56dc9db5..d1bcbcbf 100644 --- a/c++/include/objtools/readers/gtf_reader.hpp +++ b/c++/include/objtools/readers/gtf_reader.hpp @@ -1,4 +1,4 @@ - /* $Id: gtf_reader.hpp 493620 2016-03-01 13:41:06Z ivanov $ + /* $Id: gtf_reader.hpp 506324 2016-07-06 17:22:57Z ludwigf $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -162,6 +162,10 @@ protected: const CGff2Record&, CRef< CSeq_feat > ); + bool xFeatureSetQualifiersGene( + const CGff2Record& record, + CRef); + bool x_CreateParentCds( const CGff2Record&, CRef< CSeq_annot > ); @@ -199,10 +203,6 @@ protected: const CGff2Record&, CRef< CSeq_feat >& ); - bool x_FeatureSetQualifiers( - const CGff2Record&, - CRef< CSeq_feat >); - virtual bool x_ProcessQualifierSpecialCase( CGff2Record::TAttrCit, CRef< CSeq_feat > ); @@ -210,10 +210,6 @@ protected: bool x_CdsIsPartial( const CGff2Record& ); - bool x_SkipAttribute( - const CGff2Record&, - const string& ) const; - typedef map< string, CRef< CSeq_feat > > TIdToFeature; TIdToFeature m_GeneMap; TIdToFeature m_CdsMap; diff --git a/c++/include/objtools/readers/gvf_reader.hpp b/c++/include/objtools/readers/gvf_reader.hpp index c37540d9..085d13dc 100644 --- a/c++/include/objtools/readers/gvf_reader.hpp +++ b/c++/include/objtools/readers/gvf_reader.hpp @@ -1,4 +1,4 @@ - /* $Id: gvf_reader.hpp 489339 2016-01-12 15:46:54Z ludwigf $ + /* $Id: gvf_reader.hpp 515629 2016-10-04 17:46:33Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -95,13 +95,16 @@ public: virtual ~CGvfReader(); protected: - virtual bool x_ParseStructuredCommentGff( - const string&, - CRef< CAnnotdesc >& ); + virtual bool xParseStructuredComment( + const string&); - virtual bool x_ParseFeatureGff( + bool xParseFeature( const string&, - TAnnots&, + CRef&, + ILineErrorListener*); + + virtual void xPostProcessAnnot( + CRef&, ILineErrorListener*); CRef x_GetAnnotById( @@ -124,6 +127,18 @@ protected: bool xFeatureSetLocationPoint( const CGff2Record&, CRef< CSeq_feat > ); + + bool x_SetLocation( + const CGff2Record&, + CRef ); + + bool x_SetLocationInterval( + const CGff2Record&, + CRef ); + + bool x_SetLocationPoint( + const CGff2Record&, + CRef ); bool x_FeatureSetVariation( const CGvfReadRecord&, @@ -150,36 +165,68 @@ protected: const CGvfReadRecord&, CRef ); + bool xVariationMakeIndels( + const CGvfReadRecord&, + CRef); + + bool xVariationMakeInversions( + const CGvfReadRecord&, + CRef ); + + bool xVariationMakeEversions( + const CGvfReadRecord&, + CRef ); + + bool xVariationMakeTranslocations( + const CGvfReadRecord&, + CRef ); + + bool xVariationMakeComplex( + const CGvfReadRecord&, + CRef ); + + bool xVariationMakeUnknown( + const CGvfReadRecord&, + CRef ); + bool xVariationSetInsertions( const CGvfReadRecord&, - CRef< CVariation_ref > ); + CRef ); bool xVariationSetDeletions( const CGvfReadRecord&, - CRef< CVariation_ref > ); + CRef ); + + bool xVariationSetCommon( + const CGvfReadRecord&, + CRef ); virtual bool xVariationSetId( const CGvfReadRecord&, - CRef< CVariation_ref > ); + CRef ); virtual bool xVariationSetParent( const CGvfReadRecord&, - CRef< CVariation_ref > ); + CRef ); virtual bool xVariationSetName( const CGvfReadRecord&, - CRef< CVariation_ref > ); + CRef ); virtual bool xVariationSetSnvs( const CGvfReadRecord&, - CRef< CVariation_ref > ); + CRef ); virtual bool xVariationSetProperties( const CGvfReadRecord&, - CRef< CVariation_ref > ); + CRef ); virtual CGff2Record* x_CreateRecord() { return new CGvfReadRecord(m_uLineNumber); }; + bool x_IsDbvarCall(const string& nameAttr) const; + + bool x_GetNameAttribute(const CGvfReadRecord& record, string& name) const; + protected: CRef< CAnnotdesc > m_Pragmas; diff --git a/c++/include/objtools/readers/microarray_reader.hpp b/c++/include/objtools/readers/microarray_reader.hpp index 7a81a170..0814751a 100644 --- a/c++/include/objtools/readers/microarray_reader.hpp +++ b/c++/include/objtools/readers/microarray_reader.hpp @@ -1,4 +1,4 @@ -/* $Id: microarray_reader.hpp 472138 2015-07-07 16:07:55Z grichenk $ +/* $Id: microarray_reader.hpp 515629 2016-10-04 17:46:33Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -96,12 +96,6 @@ protected: CRef&, const vector& ); - virtual void xSetTrackData( - CRef&, - CRef&, - const string&, - const string& ); - static void xCleanColumnValues( vector&); diff --git a/c++/include/objtools/readers/reader_base.hpp b/c++/include/objtools/readers/reader_base.hpp index 4742a67a..c78a0a90 100644 --- a/c++/include/objtools/readers/reader_base.hpp +++ b/c++/include/objtools/readers/reader_base.hpp @@ -1,4 +1,4 @@ -/* $Id: reader_base.hpp 479221 2015-09-17 15:56:21Z gotvyans $ +/* $Id: reader_base.hpp 515629 2016-10-04 17:46:33Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -38,6 +38,7 @@ #include #include #include +#include #include BEGIN_NCBI_SCOPE @@ -237,6 +238,9 @@ protected: virtual bool xIsBrowserLine( const CTempString& ); + virtual bool xIsTrackTerminator( + const CTempString& ); + virtual void xAssignTrackData( CRef& ); @@ -258,12 +262,10 @@ protected: CAnnot_descr&, ILineErrorListener*); - virtual void xSetTrackData( + virtual void xPostProcessAnnot( CRef&, - CRef&, - const string&, - const string&); - + ILineErrorListener*); + virtual void xAddConversionInfo( CRef< CSeq_annot >&, ILineErrorListener* ); diff --git a/c++/include/objtools/readers/readfeat.hpp b/c++/include/objtools/readers/readfeat.hpp index 6d37cfe8..ba431877 100644 --- a/c++/include/objtools/readers/readfeat.hpp +++ b/c++/include/objtools/readers/readfeat.hpp @@ -157,23 +157,8 @@ public: string & out_annotname ); private: - // this class uses a singleton internally to manage the specifics - // of the feature table reader implementation - // these are the variables / functions that control the singleton - static auto_ptr sm_Implementation; - - static void x_InitImplementation(void); - static CFeature_table_reader_imp& x_GetImplementation (void); }; -inline -CFeature_table_reader_imp& CFeature_table_reader::x_GetImplementation(void) -{ - if ( !sm_Implementation.get() ) { - x_InitImplementation(); - } - return *sm_Implementation; -} END_objects_SCOPE diff --git a/c++/include/objtools/readers/source_mod_parser.hpp b/c++/include/objtools/readers/source_mod_parser.hpp index 8ef6f9ca..b1ab343e 100644 --- a/c++/include/objtools/readers/source_mod_parser.hpp +++ b/c++/include/objtools/readers/source_mod_parser.hpp @@ -1,7 +1,7 @@ #ifndef OBJTOOLS_READERS___SOURCE_MOD_PARSER__HPP #define OBJTOOLS_READERS___SOURCE_MOD_PARSER__HPP -/* $Id: source_mod_parser.hpp 499427 2016-04-26 14:11:26Z ivanov $ +/* $Id: source_mod_parser.hpp 493669 2016-03-01 16:52:34Z gotvyans $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/objtools/readers/struct_cmt_reader.hpp b/c++/include/objtools/readers/struct_cmt_reader.hpp new file mode 100644 index 00000000..7537ef0b --- /dev/null +++ b/c++/include/objtools/readers/struct_cmt_reader.hpp @@ -0,0 +1,96 @@ +#ifndef __STRUCT_CMT_READER_HPP_INCLUDED__ +#define __STRUCT_CMT_READER_HPP_INCLUDED__ + +#include +#include + +BEGIN_NCBI_SCOPE + +// forward declarations +namespace objects +{ + class CSeq_descr; + class CSeqdesc; + class CSeq_id; + class CUser_object; + class ILineErrorListener; +}; + +class CSerialObject; +class ILineReader; + +/* + Usage examples + + CStructuredCommentsReader reader(error_logger); + + std::list comments; + + ILineReader reader1(ILineReader::New(filename); + reader.LoadComments(reader1, comments); + + for (const CStructuredCommentsReader::TStructComment& cmt: comments) + { + // do something + } +*/ + +class CStructuredCommentsReader +{ +public: + // If you need messages and error to be logged + // supply an optional ILineErrorListener instance + CStructuredCommentsReader(objects::ILineErrorListener* logger); + ~CStructuredCommentsReader(); + + typedef struct { + CRef m_id; + vector > m_descs; + } TStructComment; + +#if 0 + template + size_t LoadComments(ILineReader& reader, _container& cont) + { + vector cols; + _LoadHeaderLine(reader, cols); + if (cols.empty()) + return 0; + + size_t loader = 0; + + while (!reader.AtEOF()) + { + reader.ReadLine(); + // First line is a collumn definitions + CTempString current = reader.GetCurrentLine(); + if (current.empty()) + continue; + + // Each line except first is a set of values, first collumn is a sequence id + vector values; + NStr::Split(current, "\t", values); + if (!values[0].empty()) + { + // try to find destination sequence + cont.push_back(TStructComment()); + TStructComment& cmt = cont.back(); + cmt.m_id.Reset(new objects::CSeq_id(values[0], objects::CSeq_id::fParse_AnyLocal)); + _BuildStructuredComment(cmt, cols, values); + } + } + } +#endif + + objects::CUser_object* FindStructuredComment(objects::CSeq_descr& descr); +protected: + void _LoadHeaderLine(ILineReader& reader, vector& cols); + void _BuildStructuredComment(TStructComment& cmt, const vector& cols, const vector& values); + objects::CUser_object* _AddStructuredComment(objects::CUser_object* user_obj, TStructComment& cmt, const CTempString& name, const CTempString& value); + objects::ILineErrorListener* m_logger; +}; + +END_NCBI_SCOPE + + +#endif diff --git a/c++/include/objtools/readers/track_data.hpp b/c++/include/objtools/readers/track_data.hpp new file mode 100644 index 00000000..51d64263 --- /dev/null +++ b/c++/include/objtools/readers/track_data.hpp @@ -0,0 +1,77 @@ +/* $Id: track_data.hpp 515629 2016-10-04 17:46:33Z ivanov $ + * =========================================================================== + * + * PUBLIC DOMAIN NOTICE + * National Center for Biotechnology Information + * + * This software/database is a "United States Government Work" under the + * terms of the United States Copyright Act. It was written as part of + * the author's official duties as a United States Government employee and + * thus cannot be copyrighted. This software/database is freely available + * to the public for use. The National Library of Medicine and the U.S. + * Government have not placed any restriction on its use or reproduction. + * + * Although all reasonable efforts have been taken to ensure the accuracy + * and reliability of the software and data, the NLM and the U.S. + * Government do not and cannot warrant the performance or results that + * may be obtained by using this software or data. The NLM and the U.S. + * Government disclaim all warranties, express or implied, including + * warranties of performance, merchantability or fitness for any particular + * purpose. + * + * Please cite the author in any work or product based on this material. + * + * =========================================================================== + * + * Author: Frank Ludwig + * + * File Description: + * data structures of interest to multiple readers + * + */ + +#ifndef OBJTOOLS_READERS___TRACKDATA__HPP +#define OBJTOOLS_READERS___TRACKDATA__HPP + +BEGIN_NCBI_SCOPE +BEGIN_SCOPE(objects) // namespace ncbi::objects:: + +// ============================================================================ +class NCBI_XOBJREAD_EXPORT CTrackData +// ============================================================================ +{ +public: + typedef std::vector LineData; + typedef std::map TrackData; +public: + CTrackData(); + ~CTrackData() {}; + bool ParseLine( + const LineData& ); + static bool IsTrackData( + const LineData& ); + const TrackData& Values() const {return mData;}; + bool WriteToAnnot( + CSeq_annot&); + bool ContainsData() const {return !mData.empty();}; + + //convenience accessors + string Type() const {return ValueOf("type");}; + string Description() const {return ValueOf("description");}; + string Name() const {return ValueOf("name");}; + int Offset() const; + + string ValueOf( + const std::string&) const; + +protected: + TrackData mData; + //string m_strType; + //string m_strDescription; + //string m_strName; +}; + +END_SCOPE(objects) +END_NCBI_SCOPE + +#endif // OBJTOOLS_READERS___TRACKDATA__HPP diff --git a/c++/include/objtools/readers/vcf_reader.hpp b/c++/include/objtools/readers/vcf_reader.hpp index ab906c55..b09940bb 100644 --- a/c++/include/objtools/readers/vcf_reader.hpp +++ b/c++/include/objtools/readers/vcf_reader.hpp @@ -1,4 +1,4 @@ -/* $Id: vcf_reader.hpp 472138 2015-07-07 16:07:55Z grichenk $ +/* $Id: vcf_reader.hpp 503934 2016-06-09 14:44:15Z foleyjp $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -218,7 +218,8 @@ protected: virtual bool xAssignVcfMeta( - CRef ); + CRef, + ILineErrorListener* ); virtual bool xAssignVariationAlleleSet( @@ -314,6 +315,7 @@ protected: vector m_MetaDirectives; vector m_GenotypeHeaders; CMessageListenerLenient m_ErrorsPrivate; + bool m_MetaHandled; }; END_SCOPE(objects) diff --git a/c++/include/objtools/readers/wiggle_reader.hpp b/c++/include/objtools/readers/wiggle_reader.hpp index 42845ec2..b39a8751 100644 --- a/c++/include/objtools/readers/wiggle_reader.hpp +++ b/c++/include/objtools/readers/wiggle_reader.hpp @@ -1,4 +1,4 @@ -/* $Id: wiggle_reader.hpp 472138 2015-07-07 16:07:55Z grichenk $ +/* $Id: wiggle_reader.hpp 511582 2016-08-23 15:29:38Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -168,7 +168,7 @@ public: m_pInterval.Reset(new CSeq_interval()); m_pInterval->SetId(id); m_pInterval->SetFrom(start-1); - m_pInterval->SetTo(start+span-1); + m_pInterval->SetTo(start-1+span-1); m_value = value; }; diff --git a/c++/include/serial/impl/enumerated.hpp b/c++/include/serial/impl/enumerated.hpp index fc39293f..a0e89119 100644 --- a/c++/include/serial/impl/enumerated.hpp +++ b/c++/include/serial/impl/enumerated.hpp @@ -1,7 +1,7 @@ #ifndef ENUMERATED__HPP #define ENUMERATED__HPP -/* $Id: enumerated.hpp 103491 2007-05-04 17:18:18Z kazimird $ +/* $Id: enumerated.hpp 515165 2016-09-28 17:51:10Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -34,6 +34,7 @@ #include #include +#include /** @addtogroup TypeInfoCPP @@ -44,6 +45,7 @@ BEGIN_NCBI_SCOPE + class NCBI_XSERIAL_EXPORT CEnumeratedTypeInfo : public CPrimitiveTypeInfo { typedef CPrimitiveTypeInfo CParent; @@ -101,9 +103,20 @@ inline CEnumeratedTypeInfo* CreateEnumeratedTypeInfo(const T& , const CEnumeratedTypeValues* values) { - return new CEnumeratedTypeInfo(sizeof(T), values, T(-1) < 0); +// C++ enums are not signed and not unsigned + bool is_signed = std::is_signed::value; + if (std::is_enum::value) { + for (const auto& v : values->GetValues()) { + if (v.second < 0) { + is_signed = true; + break; + } + } + } + return new CEnumeratedTypeInfo(sizeof(T), values, is_signed); } + END_NCBI_SCOPE /* @} */ diff --git a/c++/include/serial/impl/objectiter.inl b/c++/include/serial/impl/objectiter.inl index f11a79e3..69d1c99c 100644 --- a/c++/include/serial/impl/objectiter.inl +++ b/c++/include/serial/impl/objectiter.inl @@ -1,7 +1,7 @@ #if defined(OBJECTITER__HPP) && !defined(OBJECTITER__INL) #define OBJECTITER__INL -/* $Id: objectiter.inl 103491 2007-05-04 17:18:18Z kazimird $ +/* $Id: objectiter.inl 502193 2016-05-23 12:28:12Z gouriano $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -655,6 +655,11 @@ CObjectTypeInfo CObjectTypeInfoCV::GetChoiceType(void) const return GetChoiceTypeInfo(); } +inline +CObjectTypeInfoCV::operator CObjectTypeInfo(void) const +{ + return GetVariantInfo()->GetTypeInfo(); +} inline CObjectTypeInfo CObjectTypeInfoCV::GetVariantType(void) const { diff --git a/c++/include/serial/impl/objistrasnb.inl b/c++/include/serial/impl/objistrasnb.inl index 1982df34..da5e6767 100644 --- a/c++/include/serial/impl/objistrasnb.inl +++ b/c++/include/serial/impl/objistrasnb.inl @@ -1,7 +1,7 @@ #if defined(OBJISTRASNB__HPP) && !defined(OBJISTRASNB__INL) #define OBJISTRASNB__INL -/* $Id: objistrasnb.inl 412224 2013-09-05 15:30:00Z gouriano $ +/* $Id: objistrasnb.inl 507795 2016-07-21 17:24:14Z gouriano $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -142,6 +142,27 @@ void CObjectIStreamAsnBinary::ExpectSysTag(ETagValue tag_value) ExpectSysTagByte(MakeTagByte(eUniversal, ePrimitive, tag_value)); } +inline +void CObjectIStreamAsnBinary::ExpectIntegerTag(void) +{ + if (m_SkipNextTag) { + m_SkipNextTag = false; + return; + } + Uint1 tag = StartTag(PeekTagByte()); + Uint1 exp = MakeTagByte( eUniversal, ePrimitive, eInteger); + if (tag != exp) { + if (tag != MakeTagByte(eApplication, ePrimitive, eInteger)) { + UnexpectedSysTagByte(exp); + } + SetSpecialCaseUsed(CObjectIStream::eReadAsBigInt); + } + m_CurrentTagLength = 1; +#if CHECK_INSTREAM_STATE + m_CurrentTagState = eTagParsed; +#endif +} + inline void CObjectIStreamAsnBinary::ExpectTagClassByte(TByte first_tag_byte, TByte expected_class_byte) diff --git a/c++/include/serial/impl/objstack.hpp b/c++/include/serial/impl/objstack.hpp index 64cc4256..49869952 100644 --- a/c++/include/serial/impl/objstack.hpp +++ b/c++/include/serial/impl/objstack.hpp @@ -1,7 +1,7 @@ #ifndef OBJSTACK__HPP #define OBJSTACK__HPP -/* $Id: objstack.hpp 461337 2015-03-09 18:00:58Z gouriano $ +/* $Id: objstack.hpp 507795 2016-07-21 17:24:14Z gouriano $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -61,7 +61,7 @@ class NCBI_XSERIAL_EXPORT CObjectStackFrame { public: enum EFrameType { - eFrameOther, + eFrameOther = 0, eFrameNamed, eFrameArray, eFrameArrayElement, @@ -101,13 +101,13 @@ protected: private: friend class CObjectStack; - EFrameType m_FrameType; - bool m_Notag; // means no XML tag - bool m_NoEOC; // no binary ASN end-of-content mark - ENsQualifiedMode m_NsqMode; TTypeInfo m_TypeInfo; const CMemberId* m_MemberId; TConstObjectPtr m_ObjectPtr; + EFrameType m_FrameType; + ENsQualifiedMode m_NsqMode; + bool m_Notag; // means no XML tag + bool m_NoEOC; // no binary ASN end-of-content mark }; #define ThrowError(flag, mess) \ @@ -156,6 +156,7 @@ public: TFrame& FetchFrameFromTop(size_t index); const TFrame& FetchFrameFromTop(size_t index) const; const TFrame& FetchFrameFromBottom(size_t index) const; + TTypeInfo GetRecentTypeInfo(void) const; virtual void UnendedFrame(void); const string& GetStackPath(void); diff --git a/c++/include/serial/impl/objstack.inl b/c++/include/serial/impl/objstack.inl index 026b34a8..ea3b13c9 100644 --- a/c++/include/serial/impl/objstack.inl +++ b/c++/include/serial/impl/objstack.inl @@ -1,7 +1,7 @@ #if defined(OBJSTACK__HPP) && !defined(OBJSTACK__INL) #define OBJSTACK__INL -/* $Id: objstack.inl 412224 2013-09-05 15:30:00Z gouriano $ +/* $Id: objstack.inl 507795 2016-07-21 17:24:14Z gouriano $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -35,13 +35,13 @@ inline void CObjectStackFrame::Reset(void) { - m_FrameType = eFrameOther; - m_Notag = false; - m_NoEOC = false; - m_NsqMode = eNSQNotSet; m_TypeInfo = 0; m_MemberId = 0; m_ObjectPtr = 0; + m_FrameType = eFrameOther; + m_NsqMode = eNSQNotSet; + m_Notag = false; + m_NoEOC = false; } inline @@ -264,6 +264,17 @@ const CObjectStack::TFrame& CObjectStack::FetchFrameFromBottom(size_t index) con return *ptr; } +inline +TTypeInfo CObjectStack::GetRecentTypeInfo(void) const +{ + for (TFrame* ptr = m_StackPtr; ptr >= m_Stack; --ptr) { + if (ptr->HasTypeInfo()) { + return ptr->GetTypeInfo(); + } + } + return nullptr; +} + inline void CObjectStack::WatchPathHooks(bool set) { diff --git a/c++/include/serial/impl/objstrasnb.inl b/c++/include/serial/impl/objstrasnb.inl index fb93bfd2..b29c16eb 100644 --- a/c++/include/serial/impl/objstrasnb.inl +++ b/c++/include/serial/impl/objstrasnb.inl @@ -1,7 +1,7 @@ #if defined(OBJSTRASNB__HPP) && !defined(OBJSTRASNB__INL) #define OBJSTRASNB__INL -/* $Id: objstrasnb.inl 412224 2013-09-05 15:30:00Z gouriano $ +/* $Id: objstrasnb.inl 500790 2016-05-09 11:30:33Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -61,7 +61,7 @@ CAsnBinaryDefs::MakeContainerTagByte(bool random_order) inline CAsnBinaryDefs::ETagValue -CAsnBinaryDefs::StringTag(EStringType type) +CAsnBinaryDefs::StringTag(EStringType /*type*/) { return eVisibleString; //return type == eStringTypeVisible? eVisibleString: eUTF8String; diff --git a/c++/include/serial/impl/stdtypes.hpp b/c++/include/serial/impl/stdtypes.hpp index 69fe1211..365cd73b 100644 --- a/c++/include/serial/impl/stdtypes.hpp +++ b/c++/include/serial/impl/stdtypes.hpp @@ -1,7 +1,7 @@ #ifndef STDTYPES__HPP #define STDTYPES__HPP -/* $Id: stdtypes.hpp 405847 2013-07-09 13:56:53Z gouriano $ +/* $Id: stdtypes.hpp 507795 2016-07-21 17:24:14Z gouriano $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -325,6 +325,16 @@ public: static CTypeInfo* CreateTypeInfo(void); }; +class bigint_type { +}; +EMPTY_TEMPLATE +class NCBI_XSERIAL_EXPORT CStdTypeInfo +{ +public: + static TTypeInfo GetTypeInfo(void); + static CTypeInfo* CreateTypeInfo(void); +}; + EMPTY_TEMPLATE class NCBI_XSERIAL_EXPORT CStdTypeInfo { diff --git a/c++/include/serial/objectiter.hpp b/c++/include/serial/objectiter.hpp index f799755e..8a2c0e40 100644 --- a/c++/include/serial/objectiter.hpp +++ b/c++/include/serial/objectiter.hpp @@ -1,7 +1,7 @@ #ifndef OBJECTITER__HPP #define OBJECTITER__HPP -/* $Id: objectiter.hpp 358154 2012-03-29 15:05:12Z gouriano $ +/* $Id: objectiter.hpp 502193 2016-05-23 12:28:12Z gouriano $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -493,6 +493,7 @@ public: /// Get containing choice CObjectTypeInfo GetChoiceType(void) const; + operator CObjectTypeInfo(void) const; /// Get variant data type CObjectTypeInfo GetVariantType(void) const; /// Get variant data type diff --git a/c++/include/serial/objhook.hpp b/c++/include/serial/objhook.hpp index c3b98a19..2dc5288d 100644 --- a/c++/include/serial/objhook.hpp +++ b/c++/include/serial/objhook.hpp @@ -1,7 +1,7 @@ #ifndef OBJHOOK__HPP #define OBJHOOK__HPP -/* $Id: objhook.hpp 367319 2012-06-22 18:19:19Z gouriano $ +/* $Id: objhook.hpp 502193 2016-05-23 12:28:12Z gouriano $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -70,7 +70,7 @@ public: const CObjectInfo& object); /// Default skip void DefaultSkip(CObjectIStream& in, - const CObjectInfo& object); + const CObjectTypeInfo& object); }; /// Read hook for data member of a containing object (eg, SEQUENCE) @@ -88,7 +88,7 @@ public: void DefaultRead(CObjectIStream& in, const CObjectInfoMI& object); void DefaultSkip(CObjectIStream& in, - const CObjectInfoMI& object); + const CObjectTypeInfoMI& object); void ResetMember(const CObjectInfoMI& object, CObjectInfoMI::EEraseFlag flag = CObjectInfoMI::eErase_Optional); @@ -124,7 +124,8 @@ public: const CObjectInfoCV& variant) = 0; void DefaultRead(CObjectIStream& in, const CObjectInfoCV& object); - // No default skip method - can not skip variants + void DefaultSkip(CObjectIStream& in, + const CObjectTypeInfoCV& object); }; /// Read hook for a choice variant (CHOICE) @@ -179,6 +180,9 @@ public: const CConstObjectInfoMI& member) = 0; void DefaultWrite(CObjectOStream& out, const CConstObjectInfoMI& member); + void CustomWrite(CObjectOStream& out, + const CConstObjectInfoMI& member, + const CConstObjectInfo& custom_object); }; /// Write hook for a choice variant (CHOICE) @@ -191,6 +195,9 @@ public: const CConstObjectInfoCV& variant) = 0; void DefaultWrite(CObjectOStream& out, const CConstObjectInfoCV& variant); + void CustomWrite(CObjectOStream& out, + const CConstObjectInfoCV& variant, + const CConstObjectInfo& custom_object); }; /// Skip hook for a standalone object @@ -221,6 +228,8 @@ public: const CObjectTypeInfoMI& member) = 0; virtual void SkipMissingClassMember(CObjectIStream& stream, const CObjectTypeInfoMI& member); + void DefaultRead(CObjectIStream& in, + const CObjectInfo& object); void DefaultSkip(CObjectIStream& stream, const CObjectTypeInfoMI& member); }; @@ -233,8 +242,10 @@ public: virtual void SkipChoiceVariant(CObjectIStream& stream, const CObjectTypeInfoCV& variant) = 0; -// void DefaultSkip(CObjectIStream& stream, -// const CObjectTypeInfoCV& variant); + void DefaultRead(CObjectIStream& in, + const CObjectInfo& object); + void DefaultSkip(CObjectIStream& stream, + const CObjectTypeInfoCV& variant); }; diff --git a/c++/include/serial/objistr.hpp b/c++/include/serial/objistr.hpp index e607845a..87a5e85a 100644 --- a/c++/include/serial/objistr.hpp +++ b/c++/include/serial/objistr.hpp @@ -1,7 +1,7 @@ #ifndef SERIAL___OBJISTR__HPP #define SERIAL___OBJISTR__HPP -/* $Id: objistr.hpp 421693 2013-12-13 14:11:00Z gouriano $ +/* $Id: objistr.hpp 507795 2016-07-21 17:24:14Z gouriano $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -1071,7 +1071,8 @@ public: enum ESpecialCaseRead { eReadAsNormal = 0, eReadAsDefault = 1, - eReadAsNil = 2 + eReadAsNil = 2, + eReadAsBigInt = 3 }; private: TConstObjectPtr m_MemberDefault; diff --git a/c++/include/serial/objistrasnb.hpp b/c++/include/serial/objistrasnb.hpp index 773619c4..bc952ff0 100644 --- a/c++/include/serial/objistrasnb.hpp +++ b/c++/include/serial/objistrasnb.hpp @@ -1,7 +1,7 @@ #ifndef OBJISTRASNB__HPP #define OBJISTRASNB__HPP -/* $Id: objistrasnb.hpp 421594 2013-12-12 19:03:07Z gouriano $ +/* $Id: objistrasnb.hpp 507795 2016-07-21 17:24:14Z gouriano $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -298,6 +298,7 @@ private: ETagConstructed tag_constructed, ETagValue tag_value); void ExpectSysTag(ETagValue tag_value); + void ExpectIntegerTag(void); void ExpectTag(ETagClass tag_class, ETagConstructed tag_constructed, diff --git a/c++/include/serial/objostr.hpp b/c++/include/serial/objostr.hpp index 205d0a3f..878c60b2 100644 --- a/c++/include/serial/objostr.hpp +++ b/c++/include/serial/objostr.hpp @@ -1,7 +1,7 @@ #ifndef OBJOSTR__HPP #define OBJOSTR__HPP -/* $Id: objostr.hpp 484578 2015-11-12 19:13:20Z vasilche $ +/* $Id: objostr.hpp 507795 2016-07-21 17:24:14Z gouriano $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -754,7 +754,8 @@ public: enum ESpecialCaseWrite { eWriteAsNormal = 0, eWriteAsDefault = 1, - eWriteAsNil = 2 + eWriteAsNil = 2, + eWriteAsBigInt = 3 }; void SetSpecialCaseWrite( ESpecialCaseWrite how) { m_SpecialCaseWrite = how; @@ -793,12 +794,12 @@ protected: TFlags m_Flags; AutoPtr m_Objects; string m_Separator; - bool m_AutoSeparator; ESerialDataFormat m_DataFormat; - bool m_WriteNamedIntegersByValue; EDelayBufferParsing m_ParseDelayBuffers; - bool m_FastWriteDouble; ESpecialCaseWrite m_SpecialCaseWrite; + bool m_AutoSeparator; + bool m_WriteNamedIntegersByValue; + bool m_FastWriteDouble; bool m_EnforceWritingDefaults; private: diff --git a/c++/include/serial/objostrxml.hpp b/c++/include/serial/objostrxml.hpp index b061ab57..87b5b6f8 100644 --- a/c++/include/serial/objostrxml.hpp +++ b/c++/include/serial/objostrxml.hpp @@ -1,7 +1,7 @@ #ifndef OBJOSTRXML__HPP #define OBJOSTRXML__HPP -/* $Id: objostrxml.hpp 459636 2015-02-20 14:45:49Z gouriano $ +/* $Id: objostrxml.hpp 507795 2016-07-21 17:24:14Z gouriano $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -415,7 +415,7 @@ private: void x_EndTypeNamespace(void); bool x_BeginNamespace(const string& ns_name, const string& ns_prefix); void x_EndNamespace(const string& ns_name); - void x_SpecialCaseWrite(void); + bool x_SpecialCaseWrite(void); char x_VerifyChar(char); enum ETagAction { diff --git a/c++/include/serial/rpcbase.hpp b/c++/include/serial/rpcbase.hpp index b6d28485..4f81eb27 100644 --- a/c++/include/serial/rpcbase.hpp +++ b/c++/include/serial/rpcbase.hpp @@ -1,7 +1,7 @@ #ifndef SERIAL___RPCBASE__HPP #define SERIAL___RPCBASE__HPP -/* $Id: rpcbase.hpp 489897 2016-01-19 18:58:14Z grichenk $ +/* $Id: rpcbase.hpp 514363 2016-09-21 15:20:35Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -89,9 +89,9 @@ public: const STimeout* GetTimeout(EIO_Event direction = eIO_Read) const; protected: - virtual string GetAffinity(const TRequest& request) const + virtual string GetAffinity(const TRequest& /*request*/) const { - return ""; + return string(); } virtual void x_WriteRequest(CObjectOStream& out, const CSerialObject& request) @@ -164,6 +164,7 @@ void CRPCClient::x_Connect(void) memset(&x_extra, 0, sizeof(x_extra)); x_extra.data = &m_RetryCtx; x_extra.parse_header = sx_ParseHeader; + x_extra.flags = fHTTP_NoAutoRetry; x_SetStream(new CConn_ServiceStream(m_Service, fSERV_Any, net_info, &x_extra, m_Timeout)); @@ -195,7 +196,7 @@ void CRPCClient::x_ConnectURL(const string& url) &m_RetryCtx, // user data for the callback 0, // adjust callback 0, // cleanup callback - fHTTP_AutoReconnect, + fHTTP_AutoReconnect | fHTTP_NoAutoRetry, m_Timeout)); } @@ -251,9 +252,11 @@ inline EHTTP_HeaderParse CRPCClient::sx_ParseHeader(const char* http_header, void* user_data, - int server_error) + int /*server_error*/) { - if ( !user_data ) return eHTTP_HeaderContinue; + if ( !user_data ) { + return eHTTP_HeaderContinue; + } CHttpRetryContext* retry_ctx = reinterpret_cast(user_data); _ASSERT(retry_ctx); retry_ctx->ParseHeader(http_header); diff --git a/c++/include/serial/rpcbase_impl.hpp b/c++/include/serial/rpcbase_impl.hpp index e03b3ecd..df6ca695 100644 --- a/c++/include/serial/rpcbase_impl.hpp +++ b/c++/include/serial/rpcbase_impl.hpp @@ -1,7 +1,7 @@ #ifndef SERIAL___RPCBASE_IMPL__HPP #define SERIAL___RPCBASE_IMPL__HPP -/* $Id: rpcbase_impl.hpp 499300 2016-04-25 15:23:35Z ivanov $ +/* $Id: rpcbase_impl.hpp 498886 2016-04-20 13:48:22Z grichenk $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/serial/serialbase.hpp b/c++/include/serial/serialbase.hpp index f792421f..84f8db36 100644 --- a/c++/include/serial/serialbase.hpp +++ b/c++/include/serial/serialbase.hpp @@ -1,7 +1,7 @@ #ifndef SERIALBASE__HPP #define SERIALBASE__HPP -/* $Id: serialbase.hpp 389685 2013-02-20 14:11:37Z gouriano $ +/* $Id: serialbase.hpp 498023 2016-04-12 18:53:26Z grichenk $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -329,19 +329,19 @@ public: return this; } - bool operator<(const TPrim& value) const + template bool operator<(const T& value) const { return m_Data < value; } - bool operator>(const TPrim& value) const + template bool operator>(const T& value) const { return m_Data > value; } - bool operator==(const TPrim& value) const + template bool operator==(const T& value) const { return m_Data == value; } - bool operator!=(const TPrim& value) const + template bool operator!=(const T& value) const { return m_Data != value; } @@ -382,6 +382,21 @@ public: }; +#ifdef NCBI_STRICT_GI +template <> +class NCBI_XSERIAL_EXPORT CStdAliasBase : public CAliasBase +{ + typedef CAliasBase TParent; + typedef CStdAliasBase TThis; +public: + CStdAliasBase(void) + : TParent(CStrictId64()) {} + explicit CStdAliasBase(const CStrictId64& value) + : TParent(value) {} +}; +#endif + + template class CUnionBuffer { // char buffer support, used in choices diff --git a/c++/include/serial/serialdef.hpp b/c++/include/serial/serialdef.hpp index 8c6a3f3a..b616378f 100644 --- a/c++/include/serial/serialdef.hpp +++ b/c++/include/serial/serialdef.hpp @@ -1,7 +1,7 @@ #ifndef SERIALDEF__HPP #define SERIALDEF__HPP -/* $Id: serialdef.hpp 395287 2013-04-10 17:58:30Z grichenk $ +/* $Id: serialdef.hpp 507795 2016-07-21 17:24:14Z gouriano $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -195,7 +195,7 @@ enum ESerialRecursionMode { /// Defines namespace qualification of XML tags enum ENsQualifiedMode { - eNSQNotSet, + eNSQNotSet = 0, eNSUnqualified, eNSQualified }; diff --git a/c++/include/serial/serialimpl.hpp b/c++/include/serial/serialimpl.hpp index c1b963b0..d91b95fa 100644 --- a/c++/include/serial/serialimpl.hpp +++ b/c++/include/serial/serialimpl.hpp @@ -1,7 +1,7 @@ #ifndef SERIALIMPL__HPP #define SERIALIMPL__HPP -/* $Id: serialimpl.hpp 471224 2015-06-24 17:35:04Z gouriano $ +/* $Id: serialimpl.hpp 507795 2016-07-21 17:24:14Z gouriano $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -111,6 +111,10 @@ TTypeInfoGetter GetStdTypeInfoGetter(const char* const* ) #define SERIAL_REF_CStringUTF8() \ &NCBI_NS_NCBI::CStdTypeInfo::GetTypeInfo +#define SERIAL_TYPE_BigInt() Int8 +#define SERIAL_REF_BigInt() \ + &NCBI_NS_NCBI::CStdTypeInfo::GetTypeInfo + #define SERIAL_TYPE_ENUM(CType, EnumName) CType #define SERIAL_REF_ENUM(CType, EnumName) \ NCBI_NS_NCBI::CreateEnumeratedTypeInfo(CType(0), ENUM_METHOD_NAME(EnumName)()) diff --git a/c++/include/serial/typeinfo.hpp b/c++/include/serial/typeinfo.hpp index f0a724b4..9427ef33 100644 --- a/c++/include/serial/typeinfo.hpp +++ b/c++/include/serial/typeinfo.hpp @@ -1,7 +1,7 @@ #ifndef TYPEINFO__HPP #define TYPEINFO__HPP -/* $Id: typeinfo.hpp 412224 2013-09-05 15:30:00Z gouriano $ +/* $Id: typeinfo.hpp 507795 2016-07-21 17:24:14Z gouriano $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -264,6 +264,12 @@ public: bool IsTagConstructed(void) const { return m_TagConstructed == CAsnBinaryDefs::eConstructed; } + void CodeVersion(size_t codever) { + m_CodeVer = codever; + } + size_t GetCodeVersion(void) const { + return m_CodeVer; + } private: // private constructors to avoid copying CTypeInfo(const CTypeInfo&); @@ -275,6 +281,7 @@ private: string m_Name; string m_ModuleName; mutable CNamespaceInfoItem* m_InfoItem; + size_t m_CodeVer; protected: void SetCreateFunction(TTypeCreate func); diff --git a/c++/include/util/align_range_coll.hpp b/c++/include/util/align_range_coll.hpp index 5bf6afb4..09101362 100644 --- a/c++/include/util/align_range_coll.hpp +++ b/c++/include/util/align_range_coll.hpp @@ -1,7 +1,7 @@ #ifndef UTIL___ALIGN_RANGE_COLL__HPP #define UTIL___ALIGN_RANGE_COLL__HPP -/* $Id: align_range_coll.hpp 355704 2012-03-07 19:44:47Z grichenk $ +/* $Id: align_range_coll.hpp 500279 2016-05-03 17:12:04Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -493,13 +493,13 @@ public: } vector* dead = NULL; // vector of indexes for elements that need to be removed - size_t size = m_Ranges.size(); + size_t range_size = m_Ranges.size(); - for (size_t i = size - 1; i > 0; --i) { + for (size_t i = range_size - 1; i > 0; --i) { if (m_Ranges[i - 1].IsAbutting(m_Ranges[i])) { if (dead == NULL) { // allocate temp vector - dead = new vector(size, false); - dead->reserve(size); + dead = new vector(range_size, false); + dead->reserve(range_size); } m_Ranges[i - 1].CombineWithAbutting(m_Ranges[i]); // merge i into i-1 (*dead)[i] = true; @@ -507,7 +507,7 @@ public: } if (dead) { // there are deal elements - need to compress size_t shift = 0; - for (size_t i = 0; i < size; i++ ) { + for (size_t i = 0; i < range_size; i++ ) { if ((*dead)[i]) { ++shift; } @@ -516,7 +516,7 @@ public: } } delete dead; - m_Ranges.resize(size - shift); + m_Ranges.resize(range_size - shift); } x_ResetFlags(fAbutting); x_SetFlags(fNotValidated); diff --git a/c++/include/util/bitset/bm.h b/c++/include/util/bitset/bm.h index 02f3a388..7c45f166 100644 --- a/c++/include/util/bitset/bm.h +++ b/c++/include/util/bitset/bm.h @@ -349,6 +349,12 @@ public: { } + insert_iterator(const insert_iterator& iit) + : bvect_(iit.bvect_), + max_bit_(iit.max_bit_) + { + } + insert_iterator& operator=(bm::id_t n) { BM_ASSERT(n < bm::id_max); @@ -372,9 +378,8 @@ public: insert_iterator& operator++() { return *this; } /*! Returns *this. This iterator does not move (no-op)*/ insert_iterator& operator++(int) { return *this; } - //private: - //insert_iterator(const insert_iterator&); - //insert_iterator& operator=(const insert_iterator& ); + private: + insert_iterator& operator=(const insert_iterator& ); protected: bm::bvector& bvect_; @@ -398,10 +403,10 @@ public: public: enumerator() : iterator_base() {} - enumerator(const bvector* bvect, int position) + enumerator(const bvector* bv, int position) : iterator_base() { - this->bv_ = const_cast*>(bvect); + this->bv_ = const_cast*>(bv); if (position == 0) { go_first(); @@ -869,11 +874,11 @@ public: #endif - bvector& operator=(const bvector& bvect) + bvector& operator=(const bvector& bv) { clear(true); // memory free cleaning - resize(bvect.size()); - bit_or(bvect); + resize(bv.size()); + bit_or(bv); return *this; } @@ -890,54 +895,54 @@ public: return get_bit(n); } - void operator &= (const bvector& bvect) + void operator &= (const bvector& bv) { - bit_and(bvect); + bit_and(bv); } - void operator ^= (const bvector& bvect) + void operator ^= (const bvector& bv) { - bit_xor(bvect); + bit_xor(bv); } - void operator |= (const bvector& bvect) + void operator |= (const bvector& bv) { - bit_or(bvect); + bit_or(bv); } - void operator -= (const bvector& bvect) + void operator -= (const bvector& bv) { - bit_sub(bvect); + bit_sub(bv); } - bool operator < (const bvector& bvect) const + bool operator < (const bvector& bv) const { - return compare(bvect) < 0; + return compare(bv) < 0; } - bool operator <= (const bvector& bvect) const + bool operator <= (const bvector& bv) const { - return compare(bvect) <= 0; + return compare(bv) <= 0; } - bool operator > (const bvector& bvect) const + bool operator > (const bvector& bv) const { - return compare(bvect) > 0; + return compare(bv) > 0; } - bool operator >= (const bvector& bvect) const + bool operator >= (const bvector& bv) const { - return compare(bvect) >= 0; + return compare(bv) >= 0; } - bool operator == (const bvector& bvect) const + bool operator == (const bvector& bv) const { - return compare(bvect) == 0; + return compare(bv) == 0; } - bool operator != (const bvector& bvect) const + bool operator != (const bvector& bv) const { - return compare(bvect) != 0; + return compare(bv) != 0; } bvector operator~() const @@ -1180,7 +1185,7 @@ public: if (count_is_valid_) return count_ != 0; #endif - + word_t*** blk_root = blockman_.get_rootblock(); if (!blk_root) return false; @@ -1501,10 +1506,10 @@ public: combine_operation_with_block(nb, gap, blk, arg_blk, arg_gap, opcode); } private: -#if 0 // unused, needs non-existent 6-arg variant +#if 0 void combine_count_operation_with_block(unsigned nb, const bm::word_t* arg_blk, - int arg_gap, + bool arg_gap, bm::operation opcode) { const bm::word_t* blk = get_block(nb); @@ -1696,7 +1701,7 @@ bm::id_t bvector::count_range(bm::id_t left, { BM_ASSERT(left <= right); - unsigned count = 0; + unsigned cnt = 0; // calculate logical number of start and destination blocks unsigned nblock_left = unsigned(left >> bm::set_block_shift); @@ -1719,7 +1724,7 @@ bm::id_t bvector::count_range(bm::id_t left, { if (block_count_arr) { - count += block_count_arr[nblock_left]; + cnt += block_count_arr[nblock_left]; } else { @@ -1730,20 +1735,20 @@ bm::id_t bvector::count_range(bm::id_t left, { if (left_gap) { - count += gap_bit_count_range(BMGAP_PTR(block), + cnt += gap_bit_count_range(BMGAP_PTR(block), (gap_word_t)nbit_left, (gap_word_t)r); } else { - count += bit_block_calc_count_range(block, nbit_left, r); + cnt += bit_block_calc_count_range(block, nbit_left, r); } } } if (nblock_left == nblock_right) // in one block { - return count + func.count(); + return cnt + func.count(); } for (unsigned nb = nblock_left+1; nb < nblock_right; ++nb) @@ -1751,15 +1756,15 @@ bm::id_t bvector::count_range(bm::id_t left, block = blockman_.get_block(nb); if (block_count_arr) { - count += block_count_arr[nb]; + cnt += block_count_arr[nb]; } else { if (block) - func(block); + func(block);//, nb); } } - count += func.count(); + cnt += func.count(); block = blockman_.get_block(nblock_right); bool right_gap = BM_IS_GAP(block); @@ -1768,17 +1773,17 @@ bm::id_t bvector::count_range(bm::id_t left, { if (right_gap) { - count += gap_bit_count_range(BMGAP_PTR(block), + cnt += gap_bit_count_range(BMGAP_PTR(block), (gap_word_t)0, (gap_word_t)nbit_right); } else { - count += bit_block_calc_count_range(block, 0, nbit_right); + cnt += bit_block_calc_count_range(block, 0, nbit_right); } } - return count; + return cnt; } // ----------------------------------------------------------------------- @@ -1863,7 +1868,7 @@ void bvector::optimize(bm::word_t* temp_block, = 0; ::memcpy(stat->gap_levels, blockman_.glen(), sizeof(gap_word_t) * bm::gap_levels); - stat->max_serialize_mem = sizeof(id_t) * 4; + stat->max_serialize_mem = (unsigned)sizeof(id_t) * 4; } @@ -1875,7 +1880,7 @@ void bvector::optimize(bm::word_t* temp_block, unsigned safe_inc = stat->max_serialize_mem / 10; // 10% increment if (!safe_inc) safe_inc = 256; stat->max_serialize_mem += safe_inc; - stat->memory_used += sizeof(*this) - sizeof(blockman_); + stat->memory_used += (unsigned)(sizeof(*this) - sizeof(blockman_)); stat->memory_used += blockman_.mem_used(); } } @@ -1917,13 +1922,13 @@ void bvector::set_gap_levels(const gap_word_t* glevel_len) // ----------------------------------------------------------------------- template -int bvector::compare(const bvector& bvect) const +int bvector::compare(const bvector& bv) const { int res; unsigned bn = 0; unsigned top_blocks = blockman_.effective_top_block_size(); - unsigned bvect_top_blocks = bvect.blockman_.effective_top_block_size(); + unsigned bvect_top_blocks = bv.blockman_.effective_top_block_size(); if (bvect_top_blocks > top_blocks) top_blocks = bvect_top_blocks; @@ -1931,7 +1936,7 @@ int bvector::compare(const bvector& bvect) const { const bm::word_t* const* blk_blk = blockman_.get_topblock(i); const bm::word_t* const* arg_blk_blk = - bvect.blockman_.get_topblock(i); + bv.blockman_.get_topblock(i); if (blk_blk == arg_blk_blk) { @@ -2060,7 +2065,7 @@ void bvector::calc_stat(struct bvector::statistics* st) const unsigned blocks_memory = 0; gap_word_t* gapl_ptr = st->gap_length; - st->max_serialize_mem = sizeof(id_t) * 4; + st->max_serialize_mem = unsigned(sizeof(id_t) * 4); unsigned block_idx = 0; @@ -2073,7 +2078,7 @@ void bvector::calc_stat(struct bvector::statistics* st) const if (!blk_blk) { block_idx += bm::set_array_size; - st->max_serialize_mem += sizeof(unsigned) + 1; + st->max_serialize_mem += unsigned(sizeof(unsigned) + 1); continue; } @@ -2082,7 +2087,7 @@ void bvector::calc_stat(struct bvector::statistics* st) const const bm::word_t* blk = blk_blk[j]; if (IS_VALID_ADDR(blk)) { - st->max_serialize_mem += empty_blocks << 2; + st->max_serialize_mem += unsigned(empty_blocks << 2); empty_blocks = 0; if (BM_IS_GAP(blk)) @@ -2092,12 +2097,12 @@ void bvector::calc_stat(struct bvector::statistics* st) const bm::gap_word_t* gap_blk = BMGAP_PTR(blk); unsigned mem_used = - bm::gap_capacity(gap_blk, blockman_.glen()) - * sizeof(gap_word_t); + unsigned(bm::gap_capacity(gap_blk, blockman_.glen()) + * sizeof(gap_word_t)); *gapl_ptr = gap_length(gap_blk); - st->max_serialize_mem += *gapl_ptr * sizeof(gap_word_t); + st->max_serialize_mem += unsigned(*gapl_ptr * sizeof(gap_word_t)); blocks_memory += mem_used; ++gapl_ptr; @@ -2105,7 +2110,7 @@ void bvector::calc_stat(struct bvector::statistics* st) const else // bit block { ++(st->bit_blocks); - unsigned mem_used = sizeof(bm::word_t) * bm::set_block_size; + unsigned mem_used = unsigned(sizeof(bm::word_t) * bm::set_block_size); st->max_serialize_mem += mem_used; blocks_memory += mem_used; } @@ -2123,7 +2128,7 @@ void bvector::calc_stat(struct bvector::statistics* st) const // Calc size of different odd and temporary things. - st->memory_used += sizeof(*this) - sizeof(blockman_); + st->memory_used += unsigned(sizeof(*this) - sizeof(blockman_)); st->memory_used += blockman_.mem_used(); st->memory_used += blocks_memory; } @@ -2485,13 +2490,13 @@ bm::id_t bvector::check_or_next_extract(bm::id_t prev) { BMCOUNT_DEC - unsigned nbit = + unsigned nbit1 = unsigned(prev & bm::set_block_mask); unsigned nword = - unsigned(nbit >> bm::set_word_shift); - nbit &= bm::set_word_mask; + unsigned(nbit1 >> bm::set_word_shift); + nbit1 &= bm::set_word_mask; bm::word_t* word = block + nword; - bm::word_t mask = ((bm::word_t)1) << nbit; + bm::word_t mask = ((bm::word_t)1) << nbit1; *word &= ~mask; return prev; @@ -2515,31 +2520,36 @@ bm::id_t bvector::check_or_next_extract(bm::id_t prev) template void bvector::combine_operation( - const bm::bvector& bvect, + const bm::bvector& bv, bm::operation opcode) { + /*typedef void (*block_bit_op)(bm::word_t*, const bm::word_t*); + typedef void (*block_bit_op_next)(bm::word_t*, + const bm::word_t*, + bm::word_t*, + const bm::word_t*);*/ unsigned top_blocks = blockman_.top_block_size(); - unsigned bvect_top_blocks = bvect.blockman_.top_block_size(); + unsigned bvect_top_blocks = bv.blockman_.top_block_size(); - if (size_ == bvect.size_) + if (size_ == bv.size_) { BM_ASSERT(top_blocks >= bvect_top_blocks); } else - if (size_ < bvect.size_) // this vect shorter than the arg. + if (size_ < bv.size_) // this vect shorter than the arg. { - size_ = bvect.size_; + size_ = bv.size_; // stretch our capacity blockman_.reserve_top_blocks(bvect_top_blocks); top_blocks = blockman_.top_block_size(); } else - if (size_ > bvect.size_) // this vector larger + if (size_ > bv.size_) // this vector larger { if (opcode == BM_AND) // clear the tail with zeros { - set_range(bvect.size_, size_ - 1, false); + set_range(bv.size_, size_ - 1, false); if (bvect_top_blocks < top_blocks) { // not to scan blocks we already swiped @@ -2556,11 +2566,11 @@ void bvector::combine_operation( // calculate effective top size to avoid overscan top_blocks = blockman_.effective_top_block_size(); - if (top_blocks < bvect.blockman_.effective_top_block_size()) + if (top_blocks < bv.blockman_.effective_top_block_size()) { if (opcode != BM_AND) { - top_blocks = bvect.blockman_.effective_top_block_size(); + top_blocks = bv.blockman_.effective_top_block_size(); } } @@ -2574,7 +2584,7 @@ void bvector::combine_operation( block_idx += bm::set_array_size; continue; } - const bm::word_t* const* bvbb = bvect.blockman_.get_topblock(i); + const bm::word_t* const* bvbb = bv.blockman_.get_topblock(i); if (bvbb == 0) // skip it because 0 OP 0 == 0 { block_idx += bm::set_array_size; @@ -2582,11 +2592,11 @@ void bvector::combine_operation( } // 0 - self, non-zero argument unsigned r = i * bm::set_array_size; - for (j = 0; j < bm::set_array_size; ++j) + for (j = 0; j < bm::set_array_size; ++j)//,++block_idx) { - const bm::word_t* arg_blk = bvect.blockman_.get_block(i, j); + const bm::word_t* arg_blk = bv.blockman_.get_block(i, j); if (arg_blk ) - combine_operation_with_block(r + j, + combine_operation_with_block(r + j,//block_idx, 0, 0, arg_blk, BM_IS_GAP(arg_blk), opcode); @@ -2602,7 +2612,7 @@ void bvector::combine_operation( bm::word_t* blk = blk_blk[j]; if (blk) { - const bm::word_t* arg_blk = bvect.blockman_.get_block(i, j); + const bm::word_t* arg_blk = bv.blockman_.get_block(i, j); if (arg_blk) combine_operation_with_block(r + j, BM_IS_GAP(blk), blk, @@ -2617,10 +2627,10 @@ void bvector::combine_operation( else // OR, SUB, XOR { unsigned r = i * bm::set_array_size; - for (j = 0; j < bm::set_array_size; ++j) + for (j = 0; j < bm::set_array_size; ++j)//, ++block_idx) { bm::word_t* blk = blk_blk[j]; - const bm::word_t* arg_blk = bvect.blockman_.get_block(i, j); + const bm::word_t* arg_blk = bv.blockman_.get_block(i, j); if (arg_blk || blk) combine_operation_with_block(r + j, BM_IS_GAP(blk), blk, arg_blk, BM_IS_GAP(arg_blk), @@ -2698,7 +2708,7 @@ bvector::combine_operation_with_block(unsigned nb, int new_level = gap_calc_level(res_len, blockman_.glen()); if (new_level == -1) { - blockman_.convert_gap2bitset(nb, res, res_len-1); + blockman_.convert_gap2bitset(nb, res); return; } @@ -2755,7 +2765,7 @@ bvector::combine_operation_with_block(unsigned nb, unsigned gap_cnt = gap_bit_count(gap_blk); if (gap_cnt < 128) { - gap_word_t tmp_buf[bm::gap_equiv_len * 3]; + gap_word_t arr_len = gap_convert_to_arr(tmp_buf, gap_blk, bm::gap_equiv_len-10); @@ -2772,7 +2782,7 @@ bvector::combine_operation_with_block(unsigned nb, ); BM_ASSERT(block_type==1); // GAP gap_blk = BMGAP_PTR(blk); - unsigned threshold = bm::gap_limit(gap_blk, blockman_.glen()); + threshold = bm::gap_limit(gap_blk, blockman_.glen()); for (; arr_i < arr_len; ++arr_i) { gap_word_t bit_idx = tmp_buf[arr_i]; @@ -3003,8 +3013,21 @@ void bvector::set_range_no_check(bm::id_t left, if (IS_FULL_BLOCK(block)) continue; + bool is_gap = BM_IS_GAP(block); + blockman_.set_block(nb, FULL_BLOCK_ADDR); - blockman_.free_block(block); + blockman_.set_block_bit(nb); + + if (is_gap) + { + blockman_.get_allocator().free_gap_block(BMGAP_PTR(block), + blockman_.glen()); + } + else + { + blockman_.get_allocator().free_bit_block(block); + } + } // for } else // value == 0 @@ -3014,8 +3037,19 @@ void bvector::set_range_no_check(bm::id_t left, block = blockman_.get_block(nb); if (block == 0) // nothing to do continue; + bool is_gap = BM_IS_GAP(block); blockman_.set_block(nb, 0, false /*bit*/); - blockman_.free_block(block); + //blockman_.set_block_bit(nb); + + if (is_gap) + { + blockman_.get_allocator().free_gap_block(BMGAP_PTR(block), + blockman_.glen()); + } + else + { + blockman_.get_allocator().free_bit_block(block); + } } // for } // if value else diff --git a/c++/include/util/bitset/bmalgo_impl.h b/c++/include/util/bitset/bmalgo_impl.h index 18fc98b5..50d8f781 100644 --- a/c++/include/util/bitset/bmalgo_impl.h +++ b/c++/include/util/bitset/bmalgo_impl.h @@ -114,7 +114,9 @@ struct distance_metric_descriptor */ inline void combine_count_operation_with_block(const bm::word_t* blk, + //unsigned gap, const bm::word_t* arg_blk, + //int arg_gap, distance_metric_descriptor* dmit, distance_metric_descriptor* dmit_end) @@ -195,7 +197,9 @@ void combine_count_operation_with_block(const bm::word_t* blk, case bm::COUNT_SUB_BA: dmd.metric = bm::COUNT_SUB_AB; // recursive call to SUB_AB combine_count_operation_with_block(arg_blk, +// arg_gap, blk, +// gap, it, it+1); dmd.metric = bm::COUNT_SUB_BA; // restore status quo break; @@ -288,6 +292,12 @@ void combine_count_operation_with_block(const bm::word_t* blk, // // Here we combine two plain bitblocks + //const bm::word_t* blk_end; + //const bm::word_t* arg_end; + + //blk_end = blk + (bm::set_block_size); + //arg_end = arg_blk + (bm::set_block_size); + for (distance_metric_descriptor* it = dmit; it < dmit_end; ++it) { @@ -617,7 +627,10 @@ void combine_any_operation_with_block(const bm::word_t* blk, */ inline unsigned combine_count_operation_with_block(const bm::word_t* blk, +// unsigned gap, const bm::word_t* arg_blk, +// int arg_gap, + //bm::word_t* temp_blk, distance_metric metric) { distance_metric_descriptor dmd(metric); @@ -788,6 +801,7 @@ unsigned distance_and_operation(const BV& bv1, bm::word_t*** blk_root = bman1.get_rootblock(); bm::word_t*** blk_root_arg = bman2.get_rootblock(); +// unsigned i, j; unsigned count = 0; @@ -819,6 +833,29 @@ unsigned distance_and_operation(const BV& bv1, (blk_blk[j+3] && blk_blk_arg[j+3]) ? count += combine_count_and_operation_with_block(blk_blk[j+3],blk_blk_arg[j+3]) :0; +/* + if ((blk = blk_blk[j]) && (arg_blk = blk_blk_arg[j]) ) + { + count += + combine_count_and_operation_with_block(blk,arg_blk); + } + + if ((blk = blk_blk[j+1]) && (arg_blk = blk_blk_arg[j+1]) ) + { + count += + combine_count_and_operation_with_block(blk,arg_blk); + } + if ((blk = blk_blk[j+2]) && (arg_blk = blk_blk_arg[j+2]) ) + { + count += + combine_count_and_operation_with_block(blk, arg_blk); + } + if ((blk = blk_blk[j+3]) && (arg_blk = blk_blk_arg[j+3]) ) + { + count += + combine_count_and_operation_with_block(blk, arg_blk); + } +*/ } // for j } // for i diff --git a/c++/include/util/bitset/bmalloc.h b/c++/include/util/bitset/bmalloc.h index e7412816..6fc53d90 100644 --- a/c++/include/util/bitset/bmalloc.h +++ b/c++/include/util/bitset/bmalloc.h @@ -194,8 +194,8 @@ public: const gap_word_t* glevel_len) { BM_ASSERT(level < bm::gap_levels); - unsigned len = (unsigned)(glevel_len[level] / - (sizeof(bm::word_t) / sizeof(gap_word_t))); + unsigned len = + (unsigned)(glevel_len[level] / (sizeof(bm::word_t) / sizeof(gap_word_t))); return (bm::gap_word_t*)block_alloc_.allocate(len, 0); } diff --git a/c++/include/util/bitset/bmblocks.h b/c++/include/util/bitset/bmblocks.h old mode 100755 new mode 100644 index de40f590..e7978cdc --- a/c++/include/util/bitset/bmblocks.h +++ b/c++/include/util/bitset/bmblocks.h @@ -158,16 +158,16 @@ public: bm::id_t block_count(const bm::word_t* block, unsigned idx) { - bm::id_t count = 0; + bm::id_t cnt = 0; bm::id_t first_bit; if (IS_FULL_BLOCK(block) || (block == 0)) { - count = 1; + cnt = 1; if (idx) { first_bit = block ? 1 : 0; - count -= !(prev_block_border_bit_ ^ first_bit); + cnt -= !(prev_block_border_bit_ ^ first_bit); } prev_block_border_bit_ = block ? 1 : 0; } @@ -176,11 +176,11 @@ public: if (BM_IS_GAP(block)) { gap_word_t* gap_block = BMGAP_PTR(block); - count = gap_length(gap_block) - 1; + cnt = gap_length(gap_block) - 1; if (idx) { first_bit = gap_test(gap_block, 0); - count -= !(prev_block_border_bit_ ^ first_bit); + cnt -= !(prev_block_border_bit_ ^ first_bit); } prev_block_border_bit_ = @@ -189,20 +189,20 @@ public: else // bitset { unsigned bit_count; - count = bit_block_calc_count_change(block, + cnt = bit_block_calc_count_change(block, block + bm::set_block_size, &bit_count); if (idx) { first_bit = block[0] & 1; - count -= !(prev_block_border_bit_ ^ first_bit); + cnt -= !(prev_block_border_bit_ ^ first_bit); } prev_block_border_bit_ = block[set_block_size-1] >> ((sizeof(block[0]) * 8) - 1); } } - return count; + return cnt; } bm::id_t count() const { return count_; } @@ -226,7 +226,7 @@ public: : bm_func_base_const(bm) {} - bool operator()(const bm::word_t* block, unsigned idx) + bool operator()(const bm::word_t* block, unsigned /*idx*/) { if (IS_FULL_BLOCK(block)) return true; @@ -343,7 +343,7 @@ public: } if (stat_) { - stat_->max_serialize_mem += sizeof(unsigned) + 1; + stat_->max_serialize_mem += (unsigned)sizeof(unsigned) + 1; } } void on_empty_block(unsigned /* block_idx*/ ) { ++empty_; } @@ -617,6 +617,17 @@ public: new_blk = bman.get_allocator().alloc_bit_block(); bit_block_copy(new_blk, block); } +/* + if (IS_FULL_BLOCK(block)) + { + new_blk = block; + } + else + { + new_blk = bman.get_allocator().alloc_bit_block(); + bit_block_copy(new_blk, block); + } +*/ } bman.set_block(idx, new_blk, is_gap); } @@ -639,14 +650,20 @@ public: { ::memcpy(glevel_len_, glevel_len, sizeof(glevel_len_)); blocks_ = 0; - top_block_size_ = effective_top_block_size_ = 0; if (max_bits) { top_block_size_ = compute_top_block_size(max_bits); init_tree(); } + else + { + top_block_size_ = effective_top_block_size_ = 0; + } + /* volatile const char* vp = _copyright::_p; - cpr_ = *vp; + char c = *vp; + c = 0; + */ } blocks_manager(const blocks_manager& blockman) @@ -695,10 +712,11 @@ public: return bm::set_array_size; } - unsigned top_block_size = (unsigned) - (bits_to_store / (bm::set_block_size * sizeof(bm::word_t) * - bm::set_array_size * 8)); - return top_block_size + (top_block_size < bm::set_array_size); + unsigned top_block_sz = (unsigned) + (bits_to_store / (bm::set_block_size * sizeof(bm::word_t) * + bm::set_array_size * 8)); + if (top_block_sz < bm::set_array_size) ++top_block_sz; + return top_block_sz; } /** @@ -774,16 +792,19 @@ public: for (;i < effective_top_block_size_; ++i) { bm::word_t** blk_blk = blocks_[i]; - if (blk_blk) - { - unsigned r = i * bm::set_array_size; - do - { - if (blk_blk[j] && !is_block_zero(r + j, blk_blk[j], deep_scan)) - return r + j; - ++j; - } while (j < bm::set_array_size); + if (!blk_blk) + { + nb += bm::set_array_size - j; } + else + for (;j < bm::set_array_size; ++j, ++nb) + { + bm::word_t* blk = blk_blk[j]; + if (blk && !is_block_zero(nb, blk, deep_scan)) + { + return nb; + } + } // for j j = 0; } // for i @@ -823,8 +844,17 @@ public: return bm->blocks_root(); } - void free_block(bm::word_t* block) + void set_block_all_set(unsigned nb) { + bm::word_t* block = this->get_block(nb); + set_block(nb, const_cast(FULL_BLOCK_ADDR)); + + // If we keep block type flag in pointer itself we dp not need + // to clear gap bit + #ifdef BM_DISBALE_BIT_IN_PTR + set_block_bit(nb); + #endif + if (BM_IS_GAP(block)) { alloc_.free_gap_block(BMGAP_PTR(block), glevel_len_); @@ -835,13 +865,6 @@ public: } } - void set_block_all_set(unsigned nb) - { - bm::word_t* block = - set_block(nb, const_cast(FULL_BLOCK_ADDR)); - free_block(block); - } - /** Create(allocate) bit block. Old block (if exists) gets deleted. */ @@ -851,7 +874,14 @@ public: bm::word_t* old_block = set_block(nb, block); if (IS_VALID_ADDR(old_block)) { - free_block(old_block); + if (BM_IS_GAP(old_block)) + { + alloc_.free_gap_block(BMGAP_PTR(old_block), glen()); + } + else + { + alloc_.free_bit_block(old_block); + } } return block; } @@ -965,7 +995,7 @@ public: block = alloc_.alloc_bit_block(); // initialize block depending on its previous status bit_block_set(block, block_flag ? 0xFF : 0); - set_block(nb, block, false /*bit*/); + set_block(nb, block); } else // gap block requested { @@ -1013,10 +1043,13 @@ public: /** Places new block into descriptors table, returns old block's address. - NOTE:Old block is not deleted. + Old block is not deleted. */ bm::word_t* set_block(unsigned nb, bm::word_t* block) { + bm::word_t* old_block; + + // top block index register unsigned nblk_blk = nb >> bm::set_array_shift; // auto-resize the top block array @@ -1032,17 +1065,21 @@ public: blocks_[nblk_blk] = (bm::word_t**)alloc_.alloc_ptr(); ::memset(blocks_[nblk_blk], 0, bm::set_array_size * sizeof(bm::word_t*)); + + old_block = 0; + } + else + { + old_block = blocks_[nblk_blk][nb & bm::set_array_mask]; } - // NOTE: block will be replaced without freeing - unsigned j = nb & bm::set_array_mask; - bm::word_t* old_block = blocks_[nblk_blk][j]; - blocks_[nblk_blk][j] = block; + // NOTE: block will be replaced without freeing, + // potential memory leak may lay here.... + blocks_[nblk_blk][nb & bm::set_array_mask] = block; // equivalent to % return old_block; } - /** Allocate an place new GAP block (copy of provided block) */ @@ -1076,10 +1113,22 @@ public: */ bm::word_t* set_block(unsigned nb, bm::word_t* block, bool gap) { + bm::word_t* old_block; + if (block) { block = (bm::word_t*) (gap ? BMPTR_SETBIT0(block) : BMPTR_CLEARBIT0(block)); +/* + if (gap) + { + block = (bm::word_t*)BMPTR_SETBIT0(block); + } + else + { + block = (bm::word_t*)BMPTR_CLEARBIT0(block); + } +*/ } // top block index @@ -1098,12 +1147,17 @@ public: blocks_[nblk_blk] = (bm::word_t**)alloc_.alloc_ptr(); ::memset(blocks_[nblk_blk], 0, bm::set_array_size * sizeof(bm::word_t*)); + + old_block = 0; + } + else + { + old_block = blocks_[nblk_blk][nb & bm::set_array_mask]; } - // NOTE: block will be replaced without freeing - unsigned j = nb & bm::set_array_mask; - bm::word_t* old_block = blocks_[nblk_blk][j]; - blocks_[nblk_blk][j] = block; + // NOTE: block will be replaced without freeing, + // potential memory leak may lay here.... + blocks_[nblk_blk][nb & bm::set_array_mask] = block; // equivalent to % return old_block; } @@ -1122,12 +1176,9 @@ public: \param nb - Block's index. \param gap_block - Pointer to the gap block, if NULL block nb will be taken - \param gap_len - GAP block length (optional) \return new bit block's memory */ - bm::word_t* convert_gap2bitset(unsigned nb, - const gap_word_t* gap_block=0, - unsigned gap_len=0) + bm::word_t* convert_gap2bitset(unsigned nb, const gap_word_t* gap_block=0) { bm::word_t* block = this->get_block(nb); if (gap_block == 0) @@ -1138,7 +1189,7 @@ public: BM_ASSERT(IS_VALID_ADDR((bm::word_t*)gap_block)); bm::word_t* new_block = alloc_.alloc_bit_block(); - gap_convert_to_bitset_l(new_block, gap_block, gap_len); + gap_convert_to_bitset(new_block, gap_block); // new block will replace the old one(no deletion) //set_block_ptr(nb, new_block); @@ -1152,6 +1203,11 @@ public: set_block(nb, new_block); } + // If GAP flag is in block pointer no need to clean the gap bit twice + #ifdef BM_DISBALE_BIT_IN_PTR + set_block_bit(nb); + #endif + return new_block; } @@ -1182,7 +1238,15 @@ public: { bm::word_t* block = this->get_block(nb); if (!block) return block; - free_block(block); + if (BM_IS_GAP(block)) // gap block + { + get_allocator().free_gap_block(BMGAP_PTR(block), glen()); + } + else + { + // deallocates only valid pointers + get_allocator().free_bit_block(block); + } set_block(nb, 0); return 0; } @@ -1196,8 +1260,15 @@ public: bm::word_t* block = blk_blk[j]; blk_blk[j] = 0; - free_block(block); - + if (BM_IS_GAP(block)) + { + get_allocator().free_gap_block(BMGAP_PTR(block), glen()); + } + else + { + // deallocates only valid pointers + get_allocator().free_bit_block(block); + } return 0; } @@ -1219,6 +1290,23 @@ public: count = (IS_FULL_BLOCK(block)) ? bm::bits_in_block : bit_block_calc_count(block, block + bm::set_block_size); } +/* + if (IS_FULL_BLOCK(block)) + count = bm::bits_in_block; + else + { + if (BM_IS_GAP(block)) + { + count = gap_bit_count(BMGAP_PTR(block)); + } + else // bitset + { + count = + bit_block_calc_count(block, + block + bm::set_block_size); + } + } +*/ return count; } @@ -1254,22 +1342,34 @@ public: bool is_block_gap(unsigned nb) const { + #ifdef BM_DISBALE_BIT_IN_PTR + return gap_flags_.test(nb)!=0; + #else bm::word_t* block = get_block(nb); return BMPTR_TESTBIT0(block) != 0; + #endif } void set_block_bit(unsigned nb) { + #ifdef BM_DISBALE_BIT_IN_PTR + gap_flags_.set(nb, false); + #else bm::word_t* block = get_block(nb); block = (bm::word_t*) BMPTR_CLEARBIT0(block); set_block_ptr(nb, block); + #endif } void set_block_gap(unsigned nb) { + #ifdef BM_DISBALE_BIT_IN_PTR + gap_flags_.set(nb); + #else bm::word_t* block = get_block(nb); block = (bm::word_t*)BMPTR_SETBIT0(block); set_block_ptr(nb, block); + #endif } /** @@ -1281,7 +1381,7 @@ public: when deep scan is not requested result can be approximate \returns true if all bits are in the block are 0. */ - bool is_block_zero(unsigned nb, + bool is_block_zero(unsigned /*nb*/, const bm::word_t* blk, bool deep_scan = true) const { @@ -1313,7 +1413,7 @@ public: when deep scan is not requested result can be approximate \return true if block consists of 1 bits. */ - bool is_block_one(unsigned nb, + bool is_block_one(unsigned /*nb*/, const bm::word_t* blk, bool deep_scan = true) const { @@ -1374,16 +1474,21 @@ public: unsigned mem_used() const { - unsigned mem_used = sizeof(*this); - mem_used += temp_block_ ? sizeof(word_t) * bm::set_block_size : 0; - mem_used += sizeof(bm::word_t**) * top_block_size_; + unsigned used = (unsigned)sizeof(*this); + used += (unsigned)(temp_block_ ? sizeof(word_t) * bm::set_block_size : 0); + used += (unsigned)(sizeof(bm::word_t**) * top_block_size_); + + #ifdef BM_DISBALE_BIT_IN_PTR + used += (unsigned)(gap_flags_.mem_used() - sizeof(gap_flags_)); + #endif for (unsigned i = 0; i < top_block_size_; ++i) { - mem_used += blocks_[i] ? sizeof(void*) * bm::set_array_size : 0; + used += (unsigned) + (blocks_[i] ? sizeof(void*) * bm::set_array_size : 0); } - return mem_used; + return used; } /** Returns true if second level block pointer is 0. @@ -1425,6 +1530,10 @@ public: blocks_ = bm.blocks_; bm.blocks_ = btmp; + #ifdef BM_DISBALE_BIT_IN_PTR + gap_flags_.swap(bm.gap_flags_); + #endif + xor_swap(this->top_block_size_, bm.top_block_size_); xor_swap(this->effective_top_block_size_, bm.effective_top_block_size_); @@ -1549,7 +1658,6 @@ private: gap_word_t glevel_len_[bm::gap_levels]; /// allocator allocator_type alloc_; - char cpr_; }; /** diff --git a/c++/include/util/bitset/bmconst.h b/c++/include/util/bitset/bmconst.h index 4307a570..a56db57e 100644 --- a/c++/include/util/bitset/bmconst.h +++ b/c++/include/util/bitset/bmconst.h @@ -55,7 +55,7 @@ const unsigned set_block_mask = 0xFFFFu; const unsigned set_blkblk_mask = 0xFFFFFFu; const unsigned set_block_plain_size = set_block_size / 32u; -const unsigned set_block_plain_cnt = (unsigned)(sizeof(bm::word_t)) * 8u; +const unsigned set_block_plain_cnt = (unsigned)(sizeof(bm::word_t) * 8u); // Word parameters @@ -68,11 +68,9 @@ const unsigned set_word_mask = 0x1Fu; typedef unsigned short gap_word_t; const unsigned gap_max_buff_len = 1280; -const unsigned gap_length_threashold = set_block_size * 3; // should be 2-3 bits per word const unsigned gap_max_bits = 65536; -const unsigned gap_equiv_len = - (unsigned)((sizeof(bm::word_t) * bm::set_block_size) / - sizeof(gap_word_t)); +const unsigned gap_equiv_len = (unsigned) + ((sizeof(bm::word_t) * bm::set_block_size) / sizeof(gap_word_t)); const unsigned gap_levels = 4; const unsigned gap_max_level = bm::gap_levels - 1; @@ -84,7 +82,7 @@ const unsigned set_array_shift = 8u; const unsigned set_array_mask = 0xFFu; const unsigned set_total_blocks = (bm::set_array_size * bm::set_array_size); -const unsigned bits_in_block = bm::set_block_size * (unsigned)sizeof(bm::word_t) * 8; +const unsigned bits_in_block = bm::set_block_size * (unsigned)(sizeof(bm::word_t) * 8); const unsigned bits_in_array = bm::bits_in_block * bm::set_array_size; diff --git a/c++/include/util/bitset/bmdbg.h b/c++/include/util/bitset/bmdbg.h index a0f01977..2d8fbe3b 100644 --- a/c++/include/util/bitset/bmdbg.h +++ b/c++/include/util/bitset/bmdbg.h @@ -64,10 +64,8 @@ void PrintGap(const bm::gap_word_t* gap_buf) inline void PrintDGap(const bm::gap_word_t* gap_buf, unsigned gap_len=0) { - bm::gap_word_t h; - memcpy(&h, gap_buf, sizeof(h)); - unsigned len = gap_len ? gap_len : (h >> 3); + unsigned len = gap_len ? gap_len : (*gap_buf >> 3); cout << "[" " len=" << len << "] "; unsigned i = gap_len ? 0 : 1; for (; i < len; ++i) @@ -114,9 +112,7 @@ inline void PrintDGapGamma(const bm::gap_word_t* gap_buf, unsigned gap_len=0) { unsigned total = 0; - bm::gap_word_t h; - memcpy(&h, gap_buf, sizeof(h)); - unsigned len = gap_len ? gap_len : (h >> 3); + unsigned len = gap_len ? gap_len : (*gap_buf >> 3); cout << "[" " len=" << len << "] "; unsigned i = gap_len ? 0 : 1; for (; i < len; ++i) @@ -142,7 +138,7 @@ void LoadBVector(const char* fname, TBV& bvector, unsigned* file_size=0) exit(1); } bv_file.seekg(0, ios_base::end); - unsigned length = bv_file.tellg(); + unsigned length = (unsigned)bv_file.tellg(); if (length == 0) { cout << "Empty file:" << fname << endl; diff --git a/c++/include/util/bitset/bmdef.h b/c++/include/util/bitset/bmdef.h index 6b3a3ec0..332a27e7 100644 --- a/c++/include/util/bitset/bmdef.h +++ b/c++/include/util/bitset/bmdef.h @@ -4,7 +4,6 @@ // // Set all required preprocessor defines - #include // macro to define/undefine unaligned memory access (x86, PowerPC) @@ -86,7 +85,7 @@ # define BMGAP_PTR(ptr) ((bm::gap_word_t*)BMPTR_CLEARBIT0(ptr)) # define BMSET_PTRGAP(ptr) ptr = (bm::word_t*)BMPTR_SETBIT0(ptr) -# define BM_IS_GAP(ptr) bool(BMPTR_TESTBIT0(ptr) != 0) +# define BM_IS_GAP(ptr) bool(BMPTR_TESTBIT0(ptr)!=0) diff --git a/c++/include/util/bitset/bmfunc.h b/c++/include/util/bitset/bmfunc.h index 9d5045ad..a9b5e543 100644 --- a/c++/include/util/bitset/bmfunc.h +++ b/c++/include/util/bitset/bmfunc.h @@ -39,14 +39,17 @@ For more information please visit: http://bmagic.sourceforge.net namespace bm { -bm::id_t bit_block_any_range(const bm::word_t* block, - bm::word_t left, - bm::word_t right); +inline bm::id_t bit_block_calc_count_range(const bm::word_t* block, bm::word_t left, bm::word_t right); +inline +bm::id_t bit_block_any_range(const bm::word_t* block, + bm::word_t left, + bm::word_t right); + /*! @brief Structure with statistical information about bitset's memory allocation details. @@ -395,7 +398,7 @@ template struct _copyright }; template const char _copyright::_p[] = - "BitMagic C++ Library. v.3.6.5 (c) 2002-2010 Anatoliy Kuznetsov."; + "BitMagic C++ Library. v.3.7.2 (c) 2002-2017 Anatoliy Kuznetsov."; /*! @@ -772,11 +775,11 @@ void for_each_dgap(const T* gap_buf, Func& func) ++pcurr; T prev = *pcurr; - func(prev + 1); // first element incremented to avoid 0 + func((T)(prev + 1)); // first element incremented to avoid 0 ++pcurr; do { - func(*pcurr - prev); // all others are [N] - [N-1] + func((T)(*pcurr - prev)); // all others are [N] - [N-1] prev = *pcurr; } while (++pcurr < pend); } @@ -832,7 +835,7 @@ T* gap_2_dgap(const T* gap_buf, T* dgap_buf, bool copy_head=true) template void dgap_2_gap(const T* dgap_buf, T* gap_buf, T gap_header=0) { - const T* pcurr = dgap_buf; + register const T* pcurr = dgap_buf; unsigned len; if (!gap_header) // GAP header is already part of the stream { @@ -1190,7 +1193,7 @@ template unsigned gap_set_value(unsigned val, register T* pcurr = buf + curr; register T* pprev = pcurr - 1; - register T* pend = buf + end; + register T* pend = buf + end; // Special case, first bit GAP operation. There is no platform beside it. // initial flag must be inverted. @@ -1269,7 +1272,7 @@ unsigned gap_add_value(T* buf, unsigned pos) { BM_ASSERT(pos < bm::gap_max_bits); - register T end = (*buf >> 3); + register T end = (T)(*buf >> 3); T curr = end; register T* pcurr = buf + end; register T* pend = pcurr; @@ -1325,13 +1328,13 @@ unsigned gap_add_value(T* buf, unsigned pos) } else // Worst case we need to split current block. { - *pcurr++ = pos - 1; - *pcurr = pos; - end+=2; + *pcurr++ = (T)(pos - 1); + *pcurr = (T)pos; + end = (T)(end+2); } // Set correct length word. - *buf = (*buf & 7) + (end << 3); + *buf = (T)((*buf & 7) + (end << 3)); buf[end] = bm::gap_max_bits - 1; return end; @@ -1352,7 +1355,7 @@ unsigned gap_add_value(T* buf, unsigned pos) template unsigned gap_set_array(T* buf, const T* arr, unsigned len) { - *buf = (*buf & 6u) + (1u << 3); // gap header setup + *buf = (T)((*buf & 6u) + (1u << 3)); // gap header setup T* pcurr = buf + 1; @@ -1360,19 +1363,19 @@ unsigned gap_set_array(T* buf, const T* arr, unsigned len) T curr = arr[i]; if (curr != 0) // need to add the first gap: (0 to arr[0]-1) { - *pcurr = curr - 1; + *pcurr = (T)(curr - 1); ++pcurr; } else { - *buf += 1; // GAP starts with 1 + ++(*buf); // GAP starts with 1 } T prev = curr; T acc = prev; for (i = 1; i < len; ++i) { - T curr = arr[i]; + curr = arr[i]; if (curr == prev + 1) { ++acc; @@ -1382,7 +1385,7 @@ unsigned gap_set_array(T* buf, const T* arr, unsigned len) { *pcurr++ = acc; acc = curr; - *pcurr++ = curr-1; + *pcurr++ = (T)(curr-1); } prev = curr; } @@ -1681,22 +1684,26 @@ inline void xor_bit_block(unsigned* dest, @ingroup gapfunc */ template -void gap_sub_to_bitset(unsigned* BMRESTRICT dest, const T* BMRESTRICT buf) +void gap_sub_to_bitset(unsigned* dest, const T* buf) { - const T* pend = buf + (*buf >> 3); - T b = *buf & 1; - ++buf; + register const T* pcurr = buf; + register const T* pend = pcurr + (*pcurr >> 3); + ++pcurr; - if (b) // Starts with 1 + if (*buf & 1) // Starts with 1 { - sub_bit_block(dest, 0, *buf + 1); - ++buf; + sub_bit_block(dest, 0, *pcurr + 1); + ++pcurr; } - for (++buf; buf <= pend; buf += 2) + ++pcurr; // now we are in GAP "1" again + + while (pcurr <= pend) { - T prev = *(buf-1); - BM_ASSERT(*buf > prev); - sub_bit_block(dest, prev + 1, *buf - prev); + unsigned bitpos = *(pcurr-1) + 1; + BM_ASSERT(*pcurr > *(pcurr-1)); + unsigned gap_len = *pcurr - *(pcurr-1); + sub_bit_block(dest, bitpos, gap_len); + pcurr += 2; } } @@ -1709,56 +1716,30 @@ void gap_sub_to_bitset(unsigned* BMRESTRICT dest, const T* BMRESTRICT buf) @ingroup gapfunc */ template -void gap_xor_to_bitset(unsigned* BMRESTRICT dest, const T* BMRESTRICT buf) +void gap_xor_to_bitset(unsigned* dest, const T* buf) { - const T* pend = buf + (*buf >> 3); - T b = *buf & 1; - ++buf; + register const T* pcurr = buf; + register const T* pend = pcurr + (*pcurr >> 3); + ++pcurr; - if (b) // Starts with 1 - { - xor_bit_block(dest, 0, *buf + 1); - ++buf; - } - for (++buf; buf <= pend; buf += 2) + if (*buf & 1) // Starts with 1 { - T prev = *(buf-1); - BM_ASSERT(*buf > prev); - xor_bit_block(dest, prev + 1, *buf - prev); + xor_bit_block(dest, 0, *pcurr + 1); + ++pcurr; } -} - -/*! -\brief Adds(OR) GAP block to bitblock. -\param dest - bitblock buffer pointer. -\param buf - GAP buffer pointer. -\param buf_len - GAP buffer length - -@ingroup gapfunc -*/ -template -void gap_add_to_bitset_l(unsigned* dest, const T* buf, unsigned buf_len) -{ - BM_ASSERT(buf_len); - register const T* pend = buf + buf_len; - T b = *buf & 1; - ++buf; + ++pcurr; // now we are in GAP "1" again - if (b) // Starts with 1 - { - or_bit_block(dest, 0, *buf + 1); - ++buf; - } - for (++buf; buf <= pend; buf += 2) + while (pcurr <= pend) { - T prev = *(buf-1); - BM_ASSERT(*buf > prev); - or_bit_block(dest, prev + 1, *buf - prev); + unsigned bitpos = *(pcurr-1) + 1; + BM_ASSERT(*pcurr > *(pcurr-1)); + unsigned gap_len = *pcurr - *(pcurr-1); + xor_bit_block(dest, bitpos, gap_len); + pcurr += 2; } } - /*! \brief Adds(OR) GAP block to bitblock. \param dest - bitblock buffer pointer. @@ -1769,7 +1750,25 @@ void gap_add_to_bitset_l(unsigned* dest, const T* buf, unsigned buf_len) template void gap_add_to_bitset(unsigned* dest, const T* buf) { - gap_add_to_bitset_l(dest, buf, *buf >> 3); + register const T* pcurr = buf; + register const T* pend = pcurr + (*pcurr >> 3); + ++pcurr; + + if (*buf & 1) // Starts with 1 + { + or_bit_block(dest, 0, *pcurr + 1); + ++pcurr; + } + ++pcurr; // now we are in GAP "1" again + + while (pcurr <= pend) + { + unsigned bitpos = *(pcurr-1) + 1; + BM_ASSERT(*pcurr > *(pcurr-1)); + unsigned gap_len = *pcurr - *(pcurr-1); + or_bit_block(dest, bitpos, gap_len); + pcurr += 2; + } } @@ -1783,21 +1782,25 @@ void gap_add_to_bitset(unsigned* dest, const T* buf) template void gap_and_to_bitset(unsigned* dest, const T* buf) { - register const T* pend = buf + (*buf >> 3); - T b = *buf & 1; - ++buf; + register const T* pcurr = buf; + register const T* pend = pcurr + (*pcurr >> 3); + ++pcurr; - if (!b ) // Starts with 0 + if (! (*buf & 1) ) // Starts with 0 { // Instead of AND we can SUB 0 gaps here - sub_bit_block(dest, 0, *buf + 1); - ++buf; + sub_bit_block(dest, 0, *pcurr + 1); + ++pcurr; } - for (++buf; buf <= pend; buf += 2) + ++pcurr; // now we are in GAP "0" again + + while (pcurr <= pend) { - T prev = *(buf-1); - BM_ASSERT(*buf > prev); - sub_bit_block(dest, prev + 1, *buf - prev); + unsigned bitpos = *(pcurr-1) + 1; + BM_ASSERT(*pcurr > *(pcurr-1)); + unsigned gap_len = *pcurr - *(pcurr-1); + sub_bit_block(dest, bitpos, gap_len); + pcurr += 2; } } @@ -1969,7 +1972,7 @@ bm::id_t gap_bitset_xor_count(const unsigned* block, const T* buf) for (bitval^=1, ++pcurr; pcurr <= pend; bitval^=1, ++pcurr) { - T prev = *(pcurr-1)+1; + T prev = (T)(*(pcurr-1)+1); bm::id_t c = bit_block_calc_count_range(block, prev, *pcurr); if (bitval) // 1 gap; means Result = Total_Bits - BitCount; @@ -2007,7 +2010,7 @@ bm::id_t gap_bitset_xor_any(const unsigned* block, const T* buf) for (bitval^=1, ++pcurr; pcurr <= pend; bitval^=1, ++pcurr) { - T prev = *(pcurr-1)+1; + T prev = (T)(*(pcurr-1)+1); bm::id_t c = bit_block_any_range(block, prev, *pcurr); if (bitval) // 1 gap; means Result = Total_Bits - BitCount; @@ -2054,7 +2057,7 @@ bm::id_t gap_bitset_or_count(const unsigned* block, const T* buf) for (bitval^=1, ++pcurr; pcurr <= pend; bitval^=1, ++pcurr) { - T prev = *(pcurr-1)+1; + T prev = (T)(*(pcurr-1)+1); bm::id_t c; if (bitval) @@ -2101,7 +2104,7 @@ bm::id_t gap_bitset_or_any(const unsigned* block, const T* buf) for (bitval^=1, ++pcurr; pcurr <= pend; bitval^=1, ++pcurr) { - T prev = *(pcurr-1)+1; + T prev = (T)(*(pcurr-1)+1); bm::id_t c; if (bitval) @@ -2154,21 +2157,6 @@ void gap_convert_to_bitset(unsigned* dest, const T* buf) gap_add_to_bitset(dest, buf); } -/*! -\brief GAP block to bitblock conversion. -\param dest - bitblock buffer pointer. -\param buf - GAP buffer pointer. - -@ingroup gapfunc -*/ -template -void gap_convert_to_bitset_l(unsigned* dest, const T* buf, unsigned buf_len) -{ - bit_block_set(dest, 0); - gap_add_to_bitset_l(dest, buf, buf_len ? buf_len : *buf >> 3); -} - - /*! \brief GAP block to bitblock conversion. @@ -2292,7 +2280,7 @@ void gap_init_range_block(T* buf, else { gap_len = 2; - buf[1] = to; + buf[1] = (T)to; buf[2] = (T)(set_max - 1); buf[0] = (T)((*buf & 6u) + (gap_len << 3) + value); } @@ -2310,7 +2298,7 @@ void gap_init_range_block(T* buf, else { gap_len = 3; - buf[1] = from - 1; + buf[1] = (T) (from - 1); buf[2] = (T) to; buf[3] = (T)(set_max - 1); } @@ -2441,7 +2429,7 @@ template void set_gap_level(T* buf, unsigned level) { BM_ASSERT(level < bm::gap_levels); - *buf = ((level & 3) << 1) | (*buf & 1) | (*buf & ~7); + *buf = (T)(((level & 3) << 1) | (*buf & 1) | (*buf & ~7)); } @@ -2561,7 +2549,7 @@ template } bitval = bitval_next; } - bit_idx += sizeof(*src) * 8; + bit_idx += unsigned(sizeof(*src) * 8); if (bit_idx >= bits) { goto complete; @@ -2707,7 +2695,7 @@ D gap_convert_to_arr(D* BMRESTRICT dest, if (pending >= dest_len) return 0; dest_len -= pending; - T from = *(pcurr-1)+1; + T from = (T)(*(pcurr-1)+1); T to = *pcurr; for (T i = from; ;++i) { @@ -2823,7 +2811,7 @@ void bit_count_change32(const bm::word_t* block, BM_INCWORD_BITCOUNT(*bit_count, w); - const int w_shift = (int)sizeof(w) * 8 - 1; + const int w_shift = int(sizeof(w) * 8 - 1); w ^= (w >> 1); BM_INCWORD_BITCOUNT(*gap_count, w); *gap_count -= (w_prev = (w0 >> w_shift)); // negative value correction @@ -4407,7 +4395,7 @@ unsigned bit_count_nonzero_size(const T* blk, break; } blk = blk_j-1; - count += sizeof(gap_word_t); + count += (unsigned)sizeof(gap_word_t); } else { @@ -4427,16 +4415,16 @@ unsigned bit_count_nonzero_size(const T* blk, break; } } - count += sizeof(gap_word_t); + count += unsigned(sizeof(gap_word_t)); // count all bit-words now - count += unsigned((blk_j - blk) * sizeof(T)); + count += (unsigned)((blk_j - blk) * sizeof(T)); blk = blk_j; } ++blk; } while(blk < blk_end); - return count + (2 * sizeof(T)); + return count + unsigned(2 * sizeof(T)); } @@ -4722,12 +4710,9 @@ bm::set_representation best_representation(unsigned bit_count, unsigned gap_count, unsigned block_size) { - unsigned arr_size = - (unsigned)(sizeof(bm::gap_word_t) * bit_count + sizeof(bm::gap_word_t)); - unsigned gap_size = - (unsigned)(sizeof(bm::gap_word_t) * gap_count + sizeof(bm::gap_word_t)); - unsigned inv_arr_size = - (unsigned)(sizeof(bm::gap_word_t) * (total_possible_bitcount - bit_count) + sizeof(bm::gap_word_t)); + unsigned arr_size = unsigned(sizeof(bm::gap_word_t) * bit_count + sizeof(bm::gap_word_t)); + unsigned gap_size = unsigned(sizeof(bm::gap_word_t) * gap_count + sizeof(bm::gap_word_t)); + unsigned inv_arr_size = unsigned(sizeof(bm::gap_word_t) * (total_possible_bitcount - bit_count) + sizeof(bm::gap_word_t)); if ((gap_size < block_size) && (gap_size < arr_size) && (gap_size < inv_arr_size)) { @@ -4762,7 +4747,7 @@ template T bit_convert_to_arr(T* BMRESTRICT dest, unsigned mask = 0) { T* BMRESTRICT pcurr = dest; - for(unsigned bit_idx=0; bit_idx < bits; ++src,bit_idx += sizeof(*src) * 8) + for (unsigned bit_idx=0; bit_idx < bits; ++src,bit_idx += unsigned(sizeof(*src) * 8)) { unsigned val = *src ^ mask; // possible to invert value by XOR 0xFF.. if (val == 0) @@ -4776,7 +4761,7 @@ template T bit_convert_to_arr(T* BMRESTRICT dest, copy_to_array_functor_inc func(pcurr, bit_idx); bit_for_each_4(val, func); - unsigned word_bit_cnt = unsigned(func.ptr() - pcurr); + unsigned word_bit_cnt = (unsigned)(func.ptr() - pcurr); pcurr += word_bit_cnt; } // for @@ -5101,7 +5086,7 @@ template struct bit_XOR /// Bit ASSIGN functor template struct bit_ASSIGN { - W operator()(W w1, W w2) { return w2; } + W operator()(W, W w2) { return w2; } }; /// Bit COUNT functor @@ -5174,7 +5159,7 @@ template struct bit_COUNT_SUB_BA /// Bit COUNT A functor template struct bit_COUNT_A { - W operator()(W w1, W w2) + W operator()(W w1, W ) { W r = 0; BM_INCWORD_BITCOUNT(r, w1); @@ -5185,7 +5170,7 @@ template struct bit_COUNT_A /// Bit COUNT B functor template struct bit_COUNT_B { - W operator()(W w1, W w2) + W operator()(W, W w2) { W r = 0; BM_INCWORD_BITCOUNT(r, w2); diff --git a/c++/include/util/bitset/bmrandom.h b/c++/include/util/bitset/bmrandom.h index 6024d697..4ecd6f72 100644 --- a/c++/include/util/bitset/bmrandom.h +++ b/c++/include/util/bitset/bmrandom.h @@ -156,7 +156,6 @@ void random_subset::sample(BV& bv_out, get_subset(tmp_bv, bv_in, bcnt, delta_count); bv_out = bv_in; bv_out -= tmp_bv; - bv_out.forget_count(); return; } diff --git a/c++/include/util/bitset/bmserial.h b/c++/include/util/bitset/bmserial.h index d0bd6af7..f2cdc2af 100644 --- a/c++/include/util/bitset/bmserial.h +++ b/c++/include/util/bitset/bmserial.h @@ -27,7 +27,7 @@ For more information please visit: http://bmagic.sourceforge.net */ -/*! \defgroup bvserial bvector serialization +/*! \defgroup bvserial bvector serialization * bvector serialization * \ingroup bmagic * @@ -256,13 +256,10 @@ protected: deseriaizer_base(){} /// Read GAP block from the stream - /// - /// @return GAP length - /// - unsigned read_gap_block(decoder_type& decoder, - unsigned block_type, - bm::gap_word_t* dst_block, - bm::gap_word_t& gap_head); + void read_gap_block(decoder_type& decoder, + unsigned block_type, + bm::gap_word_t* dst_block, + bm::gap_word_t& gap_head); /// Read list of bit ids /// @@ -324,7 +321,8 @@ public: unsigned deserialize(bvector_type& bv, serial_iterator_type& sit, bm::word_t* temp_block, - set_operation op = bm::set_OR); + set_operation op = bm::set_OR, + bool exit_on_one = false); /// experimental 3 way deserialization /// target = mask %OPERATION% BLOB @@ -512,7 +510,9 @@ public: unsigned deserialize(bvector_type& bv, const unsigned char* buf, bm::word_t* temp_block, - set_operation op = bm::set_OR); + set_operation op = bm::set_OR, + bool exit_on_one = false ///::gamma_gap_block(bm::gap_word_t* gap_block, bm::encoder& enc // evaluate gamma coding efficiency encoder::position_type enc_pos1 = enc.get_pos(); - size_t gamma_size = enc_pos1 - enc_pos0; + unsigned gamma_size = (unsigned)(enc_pos1 - enc_pos0); if (gamma_size > (len-1)*sizeof(gap_word_t)) { enc.set_pos(enc_pos0); @@ -688,7 +688,7 @@ void serializer::gamma_gap_array(const bm::gap_word_t* gap_array, } encoder::position_type enc_pos1 = enc.get_pos(); - size_t gamma_size = enc_pos1 - enc_pos0; + unsigned gamma_size = (unsigned)(enc_pos1 - enc_pos0); if (gamma_size > (arr_len)*sizeof(gap_word_t)) { enc.set_pos(enc_pos0); @@ -933,9 +933,9 @@ unsigned serializer::serialize(const BV& bv, // compute alternative representation sizes // - unsigned arr_block_size = sizeof(gap_word_t) + (block_bc * sizeof(gap_word_t)); - unsigned arr_block_size_inv = sizeof(gap_word_t) + (block_bc_inv * sizeof(gap_word_t)); - unsigned gap_block_size = sizeof(gap_word_t) + ((bit_gaps+1) * sizeof(gap_word_t)); + unsigned arr_block_size = unsigned(sizeof(gap_word_t) + (block_bc * sizeof(gap_word_t))); + unsigned arr_block_size_inv = unsigned(sizeof(gap_word_t) + (block_bc_inv * sizeof(gap_word_t))); + unsigned gap_block_size = unsigned(sizeof(gap_word_t) + ((bit_gaps+1) * sizeof(gap_word_t))); unsigned interval_block_size; interval_block_size = bit_count_nonzero_size(blk, bm::set_block_size); bool inverted = false; @@ -1083,7 +1083,7 @@ enum serialization_flags { template unsigned serialize(const BV& bv, unsigned char* buf, - bm::word_t* temp_block, + bm::word_t* /*temp_block*/, unsigned serialization_flags = 0) { bm::serializer bv_serial; @@ -1205,14 +1205,14 @@ unsigned deseriaizer_base::read_id_list(decoder_type& decoder, { bit_in_type bin(decoder); len = (gap_word_t)bin.gamma(); - gap_word_t prev, bit_idx; - prev = 0; + gap_word_t prev = 0; for (gap_word_t k = 0; k < len; ++k) { - bit_idx = (gap_word_t)bin.gamma(); - bit_idx -= (k == 0); - bit_idx += prev; - dst_arr[k] = prev = bit_idx; + gap_word_t bit_idx = (gap_word_t)bin.gamma(); + if (k == 0) --bit_idx; // TODO: optimization + bit_idx = (gap_word_t)(bit_idx + prev); + prev = bit_idx; + dst_arr[k] = bit_idx; } // for } break; @@ -1224,32 +1224,29 @@ unsigned deseriaizer_base::read_id_list(decoder_type& decoder, template -unsigned deseriaizer_base::read_gap_block(decoder_type& decoder, - unsigned block_type, - bm::gap_word_t* dst_block, - bm::gap_word_t& gap_head) +void deseriaizer_base::read_gap_block(decoder_type& decoder, + unsigned block_type, + bm::gap_word_t* dst_block, + bm::gap_word_t& gap_head) { typedef bit_in bit_in_type; - unsigned gap_len = 0; switch (block_type) { case set_block_gap: { - gap_len = gap_length(&gap_head); - --gap_len; + unsigned len = gap_length(&gap_head); + --len; *dst_block = gap_head; - decoder.get_16(dst_block+1, gap_len - 1); - dst_block[gap_len] = gap_max_bits - 1; - ++gap_len; + decoder.get_16(dst_block+1, len - 1); + dst_block[len] = gap_max_bits - 1; } break; case set_block_bit_1bit: { gap_set_all(dst_block, bm::gap_max_bits, 0); gap_word_t bit_idx = decoder.get_16(); - gap_len = gap_add_value(dst_block, bit_idx); - ++gap_len; + gap_add_value(dst_block, bit_idx); } break; case set_block_arrgap: @@ -1261,9 +1258,8 @@ unsigned deseriaizer_base::read_gap_block(decoder_type& decoder, for (gap_word_t k = 0; k < len; ++k) { gap_word_t bit_idx = decoder.get_16(); - gap_len = gap_add_value(dst_block, bit_idx); + gap_add_value(dst_block, bit_idx); } // for - ++gap_len; } break; case set_block_arrgap_egamma: @@ -1271,13 +1267,14 @@ unsigned deseriaizer_base::read_gap_block(decoder_type& decoder, { unsigned arr_len = read_id_list(decoder, block_type, id_array_); dst_block[0] = 0; - gap_len = gap_set_array(dst_block, id_array_, arr_len); + //unsigned gap_len = + gap_set_array(dst_block, id_array_, arr_len); } break; case set_block_gap_egamma: { - gap_len = (gap_head >> 3); - --gap_len; + unsigned len = (gap_head >> 3); + --len; // read gamma GAP block into a dest block { *dst_block = gap_head; @@ -1286,13 +1283,14 @@ unsigned deseriaizer_base::read_gap_block(decoder_type& decoder, bit_in_type bin(decoder); { gap_word_t v = (gap_word_t)bin.gamma(); - gap_word_t gap_sum = *gap_data_ptr = v - 1; - for (unsigned i = 1; i < gap_len; ++i) + gap_word_t gap_sum = *gap_data_ptr = (gap_word_t)(v - 1); + for (unsigned i = 1; i < len; ++i) { v = (gap_word_t)bin.gamma(); - *(++gap_data_ptr) = gap_sum += v; - } - dst_block[++gap_len] = bm::gap_max_bits - 1; + gap_sum = (gap_word_t)(gap_sum + v); + *(++gap_data_ptr) = gap_sum; + } + dst_block[len+1] = bm::gap_max_bits - 1; } } @@ -1307,7 +1305,6 @@ unsigned deseriaizer_base::read_gap_block(decoder_type& decoder, { gap_invert(dst_block); } - return gap_len; } @@ -1318,36 +1315,40 @@ deserializer::deserialize_gap(unsigned char btype, decoder_type& dec, unsigned i, bm::word_t* blk) { + //typedef bit_in bit_in_type; gap_word_t gap_head; - gap_word_t gap_len = 0; switch (btype) { case set_block_gap: case set_block_gapbit: { - gap_word_t gap_head = (gap_word_t) + gap_head = (gap_word_t) (sizeof(gap_word_t) == 2 ? dec.get_16() : dec.get_32()); - gap_len = gap_length(&gap_head); - int level = gap_calc_level(gap_len, bman.glen()); - --gap_len; + unsigned len = gap_length(&gap_head); + int level = gap_calc_level(len, bman.glen()); + --len; if (level == -1) // Too big to be GAP: convert to BIT block { *gap_temp_block_ = gap_head; - dec.get_16(gap_temp_block_+1, gap_len - 1); - gap_temp_block_[gap_len] = gap_max_bits - 1; + dec.get_16(gap_temp_block_+1, len - 1); + gap_temp_block_[len] = gap_max_bits - 1; if (blk == 0) // block does not exist yet { blk = bman.get_allocator().alloc_bit_block(); bman.set_block(i, blk); - gap_convert_to_bitset(blk, gap_temp_block_); + gap_convert_to_bitset(blk, gap_temp_block_); } else // We have some data already here. Apply OR operation. { - blk = bman.deoptimize_block(i); - gap_add_to_bitset(blk, gap_temp_block_); + gap_convert_to_bitset(temp_block_, + gap_temp_block_); + bv.combine_operation_with_block(i, + temp_block_, + 0, + BM_OR); } return; } // level == -1 @@ -1363,16 +1364,15 @@ deserializer::deserialize_gap(unsigned char btype, decoder_type& dec, set_gap_level(gap_blk_ptr, level); bman.set_block(i, (bm::word_t*)gap_blk); bman.set_block_gap(i); - dec.get_16(gap_blk + 1, gap_len - 1); - gap_blk[gap_len] = bm::gap_max_bits - 1; + dec.get_16(gap_blk + 1, len - 1); + gap_blk[len] = bm::gap_max_bits - 1; } else // target block exists { // read GAP block into a temp memory and perform OR *gap_temp_block_ = gap_head; - dec.get_16(gap_temp_block_ + 1, gap_len - 1); - gap_temp_block_[gap_len] = bm::gap_max_bits - 1; - ++gap_len; + dec.get_16(gap_temp_block_ + 1, len - 1); + gap_temp_block_[len] = bm::gap_max_bits - 1; break; } return; @@ -1380,9 +1380,10 @@ deserializer::deserialize_gap(unsigned char btype, decoder_type& dec, case set_block_arrgap: case set_block_arrgap_egamma: { - unsigned arr_len = this->read_id_list(dec, btype, this->id_array_); + unsigned arr_len = this->read_id_list(dec, btype, this->id_array_); gap_temp_block_[0] = 0; // reset unused bits in gap header - gap_len = gap_set_array(gap_temp_block_, this->id_array_, arr_len); + //unsigned gap_len = + gap_set_array(gap_temp_block_, this->id_array_, arr_len); break; } case set_block_gap_egamma: @@ -1390,32 +1391,16 @@ deserializer::deserialize_gap(unsigned char btype, decoder_type& dec, (sizeof(gap_word_t) == 2 ? dec.get_16() : dec.get_32()); case set_block_arrgap_egamma_inv: case set_block_arrgap_inv: - gap_len = this->read_gap_block(dec, btype, gap_temp_block_, gap_head); + this->read_gap_block(dec, btype, gap_temp_block_, gap_head); break; default: BM_ASSERT(0); } - // check if encoded GAP block length is too high and use bit-block instead - - if (gap_len > bm::gap_length_threashold) - { - blk = bman.deoptimize_block(i); - if (!blk) - { - blk = bman.get_allocator().alloc_bit_block(); - bman.set_block(i, blk); - bit_block_set(blk, 0); - } - gap_add_to_bitset_l(blk, gap_temp_block_, gap_len-1); - } - else - { - bv.combine_operation_with_block(i, - (bm::word_t*)gap_temp_block_, - 1, - BM_OR); - } + bv.combine_operation_with_block(i, + (bm::word_t*)gap_temp_block_, + 1, + BM_OR); } @@ -1472,12 +1457,11 @@ unsigned deserializer::deserialize(bvector_type& bv, if (!(header_flag & BM_HM_NO_GAPL)) { - // levels in serialized file are obsolete - /*gap_word_t glevels[bm::gap_levels];*/ + //gap_word_t glevels[bm::gap_levels]; // read GAP levels information for (i = 0; i < bm::gap_levels; ++i) { - /*glevels[i] = */dec.get_16(); + /*glevels[i] =*/ dec.get_16(); } } @@ -1607,9 +1591,9 @@ unsigned deserializer::deserialize(bvector_type& bv, { blk = bman.get_allocator().alloc_bit_block(); bman.set_block(i, blk); - for (unsigned i = 0; i < head_idx; ++i) + for (unsigned k = 0; k < head_idx; ++k) { - blk[i] = 0; + blk[k] = 0; } dec.get_32(blk + head_idx, tail_idx - head_idx + 1); for (unsigned j = tail_idx + 1; j < bm::set_block_size; ++j) @@ -2236,7 +2220,7 @@ serial_stream_iterator::get_bit_block_COUNT(bm::word_t* /*dst_block*/, break; case set_block_bit_0runs: { - unsigned count = 0; + //count = 0; unsigned char run_type = decoder_.get_8(); for (unsigned j = 0; j < bm::set_block_size;run_type = !run_type) { @@ -2357,7 +2341,7 @@ serial_stream_iterator::get_bit_block_COUNT_AND(bm::word_t* dst_block, break; case set_block_bit_0runs: { - unsigned count = 0; + //count = 0; unsigned char run_type = decoder_.get_8(); for (unsigned j = 0; j < bm::set_block_size;run_type = !run_type) { @@ -2765,9 +2749,9 @@ serial_stream_iterator::get_gap_block(bm::gap_word_t* dst_block) BM_ASSERT(dst_block); this->read_gap_block(this->decoder_, - this->block_type_, - dst_block, - this->gap_head_); + this->block_type_, + dst_block, + this->gap_head_); ++(this->block_idx_); this->state_ = e_blocks; @@ -2796,7 +2780,9 @@ unsigned operation_deserializer::deserialize( bvector_type& bv, const unsigned char* buf, bm::word_t* temp_block, - set_operation op) + set_operation op, + bool exit_on_one + ) { ByteOrder bo_current = globals::byte_order(); @@ -2820,7 +2806,7 @@ unsigned operation_deserializer::deserialize( serial_stream_current ss(buf); return iterator_deserializer:: - deserialize(bv, ss, temp_block, op); + deserialize(bv, ss, temp_block, op, exit_on_one); } switch (bo_current) { @@ -2829,14 +2815,14 @@ unsigned operation_deserializer::deserialize( serial_stream_be ss(buf); return iterator_deserializer:: - deserialize(bv, ss, temp_block, op); + deserialize(bv, ss, temp_block, op, exit_on_one); } case LittleEndian: { serial_stream_le ss(buf); return iterator_deserializer:: - deserialize(bv, ss, temp_block, op); + deserialize(bv, ss, temp_block, op, exit_on_one); } default: BM_ASSERT(0); @@ -3321,7 +3307,8 @@ iterator_deserializer::deserialize( bvector_type& bv, serial_iterator_type& sit, bm::word_t* temp_block, - set_operation op) + set_operation op, + bool exit_on_one) { BM_ASSERT(temp_block); @@ -3415,6 +3402,9 @@ iterator_deserializer::deserialize( // 2 bit blocks recombination unsigned c = sit.get_bit_block(blk, temp_block, sop); count += c; + if (exit_on_one && count) // early exit + return count; + } break; @@ -3446,6 +3436,8 @@ iterator_deserializer::deserialize( { unsigned c = bman.block_bitcount(blk);//, bv_block_idx); count += c; + if (exit_on_one && count) // early exit + return count; } break; case set_END: @@ -3531,6 +3523,8 @@ iterator_deserializer::deserialize( } // switch } // else } // switch + if (exit_on_one && count) // early exit + return count; } break; @@ -3558,6 +3552,9 @@ iterator_deserializer::deserialize( gptr, metric); count += c; + if (exit_on_one && count) // early exit + return count; + } else // non-const set operation { @@ -3601,7 +3598,18 @@ iterator_deserializer::deserialize( bop); } } - } + if (exit_on_one) + { + blk = bman.get_block(bv_block_idx); + if (blk) + { + bool z = bman.is_block_zero(bv_block_idx, blk); + if (!z) + return 1; + } + } // if exit_on_one + + } // if else non-const op } break; diff --git a/c++/include/util/bitset/bmsse2.h b/c++/include/util/bitset/bmsse2.h index e866c0b1..193abc7a 100644 --- a/c++/include/util/bitset/bmsse2.h +++ b/c++/include/util/bitset/bmsse2.h @@ -285,6 +285,7 @@ bm::id_t sse2_bit_block_calc_count_change(const __m128i* BMRESTRICT block, // compare with zero + // SSE4: _mm_test_all_zero() { // b = (b & 0x55555555) + (b >> 1 & 0x55555555); //tmp1 = _mm_srli_epi32(b, 1); // tmp1 = (b >> 1 & 0x55555555) @@ -319,6 +320,8 @@ bm::id_t sse2_bit_block_calc_count_change(const __m128i* BMRESTRICT block, // --------------------------------------------------------------------- { //__m128i b = _mm_load_si128(block); + // TODO: SSE4... + //w = _mm_extract_epi32(b, i); const bm::word_t* BMRESTRICT blk = (const bm::word_t*) block; diff --git a/c++/include/util/bitset/bmsse4.h b/c++/include/util/bitset/bmsse4.h index 443344ea..1c343360 100644 --- a/c++/include/util/bitset/bmsse4.h +++ b/c++/include/util/bitset/bmsse4.h @@ -46,7 +46,6 @@ namespace bm - /*! SSE4.2 optimized bitcounting . @ingroup SSE4 @@ -55,20 +54,15 @@ inline bm::id_t sse4_bit_count(const __m128i* block, const __m128i* block_end) { bm::id_t count = 0; - #ifdef BM64_SSE4 + const bm::id64_t* b = (bm::id64_t*) block; + const bm::id64_t* b_end = (bm::id64_t*) block_end; do { - __m128i tmp0 = _mm_load_si128(block); - count += _mm_popcnt_u64(_mm_extract_epi64(tmp0, 0)) + - _mm_popcnt_u64(_mm_extract_epi64(tmp0, 1)); - __m128i tmp1 = _mm_load_si128(block+1); - count += _mm_popcnt_u64(_mm_extract_epi64(tmp1, 0)) + - _mm_popcnt_u64(_mm_extract_epi64(tmp1, 1)); - - block +=2; - } while (block < block_end); - + count += _mm_popcnt_u64(b[0]) + + _mm_popcnt_u64(b[1]); + b += 2; + } while (b < b_end); #else do { diff --git a/c++/include/util/bitset/bmtrans.h b/c++/include/util/bitset/bmtrans.h index 966eff40..d7fcb0f8 100644 --- a/c++/include/util/bitset/bmtrans.h +++ b/c++/include/util/bitset/bmtrans.h @@ -502,7 +502,6 @@ void bit_iblock_reduce( unsigned tmatrix_out[bm::set_block_plain_cnt][bm::set_block_plain_size]) { ::memset(tmatrix_out, 0, bm::set_block_plain_cnt * sizeof(*tmatrix_out)); - unsigned row = 0; do { @@ -656,19 +655,19 @@ void tmatrix_restore(TMatrix& tmatrix, \brief Copy GAP block body to bit block with DGap transformation \internal */ -template//, typename BT> +template void gap_2_bitblock(const GT* BMRESTRICT gap_buf, - GT* BMRESTRICT block, + BT* BMRESTRICT block, unsigned block_size) { - GT* dgap_buf = block; - GT* block_end = block + block_size; + GT* dgap_buf = (GT*) block; + BT* block_end = block + block_size; GT* dgap_end = gap_2_dgap(gap_buf, dgap_buf, false); -// GT* block_end2 = (GT*) block_end; + GT* block_end2 = (GT*) block_end; // zero the tail memory - for ( ;dgap_end < block_end; ++dgap_end) + for ( ;dgap_end < block_end2; ++dgap_end) { *dgap_end = 0; } @@ -788,18 +787,20 @@ public: /// Transpose GAP block through a temp. block of aligned(!) memory /// - void transpose(const GT* BMRESTRICT gap_buf) + void transpose(const GT* BMRESTRICT gap_buf, + BT* BMRESTRICT tmp_block) { const unsigned arr_size = BLOCK_SIZE * sizeof(unsigned) / sizeof(GT); BM_ASSERT(sizeof(tmatrix_.value) == tmatrix_type::n_columns * tmatrix_type::n_rows * sizeof(GT)); + // load all GAP as D-GAP(but not head word) into aligned bit-block - gap_2_bitblock(gap_buf, tmp_gap_block_, BLOCK_SIZE * 2); + gap_2_bitblock(gap_buf, tmp_block, BLOCK_SIZE); // transpose vect_bit_transpose - (tmp_gap_block_, arr_size, tmatrix_.value); + ((GT*)tmp_block, arr_size, tmatrix_.value); // calculate number of non-zero columns eff_cols_ = find_effective_columns(tmatrix_); @@ -808,19 +809,20 @@ public: /// Transpose array of shorts /// void transpose(const GT* BMRESTRICT garr, - unsigned garr_size) + unsigned garr_size, + BT* BMRESTRICT tmp_block) { BM_ASSERT(garr_size); - bit_block_set(tmp_gap_block_, 0); - ::memcpy(tmp_gap_block_, garr, sizeof(GT)*garr_size); + bit_block_set(tmp_block, 0); + ::memcpy(tmp_block, garr, sizeof(GT)*garr_size); const unsigned arr_size = BLOCK_SIZE * sizeof(unsigned) / sizeof(GT); BM_ASSERT(sizeof(tmatrix_.value) == tmatrix_type::n_columns * tmatrix_type::n_rows * sizeof(GT)); // transpose vect_bit_transpose - (tmp_gap_block_, arr_size, tmatrix_.value); + ((GT*)tmp_block, arr_size, tmatrix_.value); // calculate number of non-zero columns eff_cols_ = find_effective_columns(tmatrix_); @@ -858,18 +860,20 @@ public: /// Restore GAP block from the transposed matrix /// void trestore(GT gap_head, - GT* BMRESTRICT gap_buf) + GT* BMRESTRICT gap_buf, + BT* BMRESTRICT tmp_block) { BM_ASSERT(sizeof(tmatrix_.value) == tmatrix_type::n_columns * tmatrix_type::n_rows * sizeof(GT)); // restore into a temp buffer - GT* gap_tmp = tmp_gap_block_; + GT* gap_tmp = (GT*)tmp_block; + //*gap_tmp++ = gap_head; vect_bit_trestore(tmatrix_.value, gap_tmp); // D-Gap to GAP block recalculation - gap_tmp = tmp_gap_block_; + gap_tmp = (GT*)tmp_block; dgap_2_gap(gap_tmp, gap_buf, gap_head); } @@ -881,8 +885,6 @@ public: unsigned char pc_vector_[tmatrix_type::n_rows]; unsigned pc_vector_stat_[bm::ibpc_end]; typename tmatrix_type::rstat rstat_vector_[tmatrix_type::n_rows]; - - GT BM_ALIGN16 tmp_gap_block_[BLOCK_SIZE*2] BM_ALIGN16ATTR; }; diff --git a/c++/include/util/bitset/bmutil.h b/c++/include/util/bitset/bmutil.h index 4ce5a81c..ef777055 100644 --- a/c++/include/util/bitset/bmutil.h +++ b/c++/include/util/bitset/bmutil.h @@ -78,6 +78,7 @@ template T ilog2(T x) { unsigned int l = 0; + if (x >= 1<<16) { x = (T)(x >> 16); l |= 16; } if (x >= 1<<8) { x = (T)(x >> 8); l |= 8; } if (x >= 1<<4) { x = (T)(x >> 4); l |= 4; } @@ -140,7 +141,8 @@ template<> inline bm::gap_word_t ilog2_LUT(bm::gap_word_t x) { unsigned l = 0; - if (x & 0xff00) { + if (x & 0xff00) + { l += 8; x = (bm::gap_word_t)(x >> 8); } diff --git a/c++/include/util/bitset/bmvmin.h b/c++/include/util/bitset/bmvmin.h index 742eb652..3f22d793 100644 --- a/c++/include/util/bitset/bmvmin.h +++ b/c++/include/util/bitset/bmvmin.h @@ -140,10 +140,10 @@ public: unsigned mem_used() const { return sizeof(*this) + - m_buf ? + (m_buf ? (m_type ? (BM_MINISET_GAPLEN * sizeof(gap_word_t)) : (BM_MINISET_ARRSIZE(N) * sizeof(bm::word_t))) - : 0; + : 0); } void swap(miniset& mset) @@ -222,7 +222,7 @@ template class bvmini { public: - bvmini(int start_strategy = 0) + bvmini(int = 0) { ::memset(m_buf, 0, sizeof(m_buf)); } diff --git a/c++/include/util/bitset/encoding.h b/c++/include/util/bitset/encoding.h index 4cf655da..58d25656 100644 --- a/c++/include/util/bitset/encoding.h +++ b/c++/include/util/bitset/encoding.h @@ -335,7 +335,7 @@ class bit_in public: bit_in(TDecoder& decoder) : src_(decoder), - used_bits_(sizeof(accum_) * 8), + used_bits_(unsigned(sizeof(accum_) * 8)), accum_(0) { } @@ -355,7 +355,7 @@ public: { if (acc == 0) { - zero_bits += (sizeof(acc) * 8) - used; + zero_bits = unsigned(zero_bits +(sizeof(acc) * 8) - used); used = 0; acc = src_.get_32(); continue; @@ -388,7 +388,7 @@ public: // get the value unsigned current; - unsigned free_bits = (sizeof(acc) * 8) - used; + unsigned free_bits = unsigned((sizeof(acc) * 8) - used); if (zero_bits <= free_bits) { take_accum: @@ -507,8 +507,9 @@ private: \param size - size of the buffer */ inline encoder::encoder(unsigned char* buf, unsigned /* size */) -: buf_(buf), start_(buf) //, size_(size) +: buf_(buf), start_(buf) { + // size_ = size; } /*! \grief Encode 8-bit prefix + an array @@ -796,7 +797,7 @@ inline decoder_little_endian::decoder_little_endian(const unsigned char* buf) BMFORCEINLINE bm::short_t decoder_little_endian::get_16() { - bm::short_t a = bm::short_t(((bm::short_t)buf_[0] << 8) + ((bm::short_t)buf_[1])); + bm::short_t a = bm::short_t(((bm::short_t)buf_[0] << 8) + (bm::short_t)buf_[1]); buf_ += sizeof(a); return a; } @@ -841,7 +842,7 @@ inline void decoder_little_endian::get_16(bm::short_t* s, unsigned count) const bm::short_t* s_end = s + count; do { - bm::short_t a = bm::short_t(((bm::short_t)buf[0] << 8) + ((bm::short_t)buf[1])); + bm::short_t a = bm::short_t(((bm::short_t)buf[0] << 8) + (bm::short_t)buf[1]); *s++ = a; buf += sizeof(a); } while (s < s_end); diff --git a/c++/include/util/bitset/ncbi_bitset_util.hpp b/c++/include/util/bitset/ncbi_bitset_util.hpp old mode 100755 new mode 100644 index 817551ef..56b50030 --- a/c++/include/util/bitset/ncbi_bitset_util.hpp +++ b/c++/include/util/bitset/ncbi_bitset_util.hpp @@ -1,7 +1,7 @@ #ifndef UTIL___BITSET_UTIL__HPP #define UTIL___BITSET_UTIL__HPP -/* $Id: ncbi_bitset_util.hpp 300829 2011-06-03 17:28:09Z kuznets $ +/* $Id: ncbi_bitset_util.hpp 498895 2016-04-20 14:46:07Z whlavina $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/util/cache/icache_cf.hpp b/c++/include/util/cache/icache_cf.hpp index eb48f754..56317848 100644 --- a/c++/include/util/cache/icache_cf.hpp +++ b/c++/include/util/cache/icache_cf.hpp @@ -1,7 +1,7 @@ #ifndef UTIL_ICACHE_CF__HPP #define UTIL_ICACHE_CF__HPP -/* $Id: icache_cf.hpp 497436 2016-04-06 17:56:51Z ivanov $ +/* $Id: icache_cf.hpp 497217 2016-04-05 11:37:33Z ivanov $ * =========================================================================== * * public DOMAIN NOTICE diff --git a/c++/include/util/compress/bzip2/bzlib.h b/c++/include/util/compress/bzip2/bzlib.h index 9ac43a16..8277123d 100644 --- a/c++/include/util/compress/bzip2/bzlib.h +++ b/c++/include/util/compress/bzip2/bzlib.h @@ -4,59 +4,19 @@ /*--- bzlib.h ---*/ /*-------------------------------------------------------------*/ -/*-- - This file is a part of bzip2 and/or libbzip2, a program and - library for lossless, block-sorting data compression. - - Copyright (C) 1996-2002 Julian R Seward. All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. The origin of this software must not be misrepresented; you must - not claim that you wrote the original software. If you use this - software in a product, an acknowledgment in the product - documentation would be appreciated but is not required. - - 3. Altered source versions must be plainly marked as such, and must - not be misrepresented as being the original software. - - 4. The name of the author may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - Julian Seward, Cambridge, UK. - jseward@acm.org - bzip2/libbzip2 version 1.0 of 21 March 2000 - - This program is based on (at least) the work of: - Mike Burrows - David Wheeler - Peter Fenwick - Alistair Moffat - Radford Neal - Ian H. Witten - Robert Sedgewick - Jon L. Bentley - - For more information on these sources, see the manual. ---*/ +/* ------------------------------------------------------------------ + This file is part of bzip2/libbzip2, a program and library for + lossless, block-sorting data compression. + + bzip2/libbzip2 version 1.0.6 of 6 September 2010 + Copyright (C) 1996-2010 Julian Seward + + Please read the WARNING, DISCLAIMER and PATENTS sections in the + README file. + + This program is released under the terms of the license contained + in the file LICENSE. + ------------------------------------------------------------------ */ #ifndef _BZLIB_H @@ -110,8 +70,10 @@ typedef #define BZ_EXPORT #endif +#ifndef BZ_NO_STDIO /* Need a definitition for FILE */ #include +#endif #ifdef _WIN32 # include @@ -260,8 +222,7 @@ BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffDecompress) ( /*-- - Code contributed by Yoshioka Tsuneo - (QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp), + Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp) to support better zlib compatibility. This code is not _officially_ part of libbzip2 (yet); I haven't tested it, documented it, or considered the diff --git a/c++/include/util/file_manifest.hpp b/c++/include/util/file_manifest.hpp index 232bbb5a..cb8a85a3 100644 --- a/c++/include/util/file_manifest.hpp +++ b/c++/include/util/file_manifest.hpp @@ -1,7 +1,7 @@ #ifndef UTIL___FILE_MANIFEST_HPP__ #define UTIL___FILE_MANIFEST_HPP__ -/* $Id: file_manifest.hpp 494188 2016-03-04 12:23:34Z ivanov $ +/* $Id: file_manifest.hpp 492854 2016-02-22 16:33:44Z elisovdn $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/util/format_guess.hpp b/c++/include/util/format_guess.hpp index 2c726984..3eae209e 100644 --- a/c++/include/util/format_guess.hpp +++ b/c++/include/util/format_guess.hpp @@ -1,7 +1,7 @@ #ifndef FORMATGUESS__HPP #define FORMATGUESS__HPP -/* $Id: format_guess.hpp 488617 2016-01-04 12:42:47Z ludwigf $ +/* $Id: format_guess.hpp 513836 2016-09-15 17:32:16Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -89,6 +89,8 @@ public: eBam = 31, ///< Binary alignment/map file eVcf = 32, ///< VCF, CVcfReader eUCSCRegion = 33, ///< USCS Region file format + eGffAugustus = 34, ///< GFFish output of Augustus Gene Prediction + eJSON = 35, ///< JSON /// Max value of EFormat eFormat_max }; @@ -282,6 +284,10 @@ protected: EMode mode ); bool TestFormatVcf( EMode mode ); + bool TestFormatAugustus( + EMode mode ); + bool TestFormatJson( + EMode mode ); bool IsInputRepeatMaskerWithoutHeader(); bool IsInputRepeatMaskerWithHeader(); @@ -304,6 +310,8 @@ protected: const std::string& ); static bool IsLineGff2( const std::string& ); + static bool IsLineAugustus( + const std::string& ); static bool IsLinePhrapId( const std::string& ); static bool IsLineRmo( @@ -322,16 +330,51 @@ private: // ' ' ' \t' '\t' ',' '|' bool x_TestTableDelimiter(const string& delims); + // Check that the beginning of testString looks like JSON + bool x_CheckJsonStart(const string& testString) const; + + // In-place deletion of JSON strings + void x_StripJsonStrings(string& testString) const; + + // Starting at from_pos, find the next set of double quotes + // indicating the end of a JSON string + size_t x_FindNextJsonStringStop(const string& input, const size_t from_pos) const; + + void x_FindJsonStringLimits(const string& testString, list& limits) const; + + // Checks and removes punctuation from testString + bool x_CheckStripJsonPunctuation(string& testString) const; + + // In-place deletion of JSON punctuation + // Returns the number of characters deleted. + size_t x_StripJsonPunctuation(string& testString) const; + + // In-place deletion of JSON keywords: true, false, null + void x_StripJsonKeywords(string& testString) const; + + bool x_CheckStripJsonNumbers(string& testString) const; + + bool x_IsTruncatedJsonNumber(const string& testString) const; + + // Is a truncation of true, false, or null + bool x_IsTruncatedJsonKeyword(const string& testString) const; + + bool x_IsNumber(const string& testString) const; + + // Return true if the string is blank or a list of space-delimited numbers + bool x_IsBlankOrNumbers(const string& testString) const; + // data: static const char* const sm_FormatNames[eFormat_max]; protected: static int s_CheckOrder[]; - static const streamsize s_iTestBufferSize = 8096; + static const streamsize s_iTestBufferGranularity = 8096; CNcbiIstream& m_Stream; bool m_bOwnsStream; char* m_pTestBuffer; + streamsize m_iTestBufferSize; streamsize m_iTestDataSize; bool m_bStatsAreValid; diff --git a/c++/include/util/id_mux.hpp b/c++/include/util/id_mux.hpp index 90886414..37f44314 100644 --- a/c++/include/util/id_mux.hpp +++ b/c++/include/util/id_mux.hpp @@ -1,7 +1,7 @@ #ifndef UTIL___ID_MUX__HPP #define UTIL___ID_MUX__HPP -/* $Id: id_mux.hpp 489095 2016-01-08 13:02:41Z ivanov $ +/* $Id: id_mux.hpp 501456 2016-05-16 15:12:46Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -372,8 +372,8 @@ void CIdDeMux::InitDim(size_t i, size_t dim_size) size_t old_size = dv.size(); dv.resize(dim_size); - for (size_t i = old_size; i < dim_size; ++i) { - dv[i] = TBVFactory::Create(); + for (size_t j = old_size; j < dim_size; ++j) { + dv[j] = TBVFactory::Create(); } } diff --git a/c++/include/util/rangemap.hpp b/c++/include/util/rangemap.hpp index 2d08cf3e..3d2b06f1 100644 --- a/c++/include/util/rangemap.hpp +++ b/c++/include/util/rangemap.hpp @@ -1,7 +1,7 @@ #ifndef RANGEMAP__HPP #define RANGEMAP__HPP -/* $Id: rangemap.hpp 354590 2012-02-28 16:30:13Z ucko $ +/* $Id: rangemap.hpp 501456 2016-05-16 15:12:46Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -433,12 +433,12 @@ public: { typedef typename TSelectMap::const_iterator TSelectMapCI; - size_type size = 0; + size_type n = 0; for ( TSelectMapCI i = m_SelectMap.begin(), - end = m_SelectMap.end(); i != end; ++i ) { - size += i->second.size(); + iend = m_SelectMap.end(); i != iend; ++i ) { + n += i->second.size(); } - return size; + return n; } // iterators diff --git a/c++/include/util/resize_iter.hpp b/c++/include/util/resize_iter.hpp index a484a12c..5d83076d 100644 --- a/c++/include/util/resize_iter.hpp +++ b/c++/include/util/resize_iter.hpp @@ -1,7 +1,7 @@ #ifndef RESIZE_ITER__HPP #define RESIZE_ITER__HPP -/* $Id: resize_iter.hpp 489095 2016-01-08 13:02:41Z ivanov $ +/* $Id: resize_iter.hpp 506558 2016-07-08 15:55:21Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -161,15 +161,7 @@ size_t xx_BitsPerElement(const T*) template size_t x_BitsPerElement(const TIterator&) { -#ifdef _RWSTD_NO_CLASS_PARTIAL_SPEC - // Sun cares way too much about backward bug-for-bug compatibility... - return xx_BitsPerElement(__value_type(TIterator())); -#elif defined(NCBI_COMPILER_MSVC) - // iterator_traits seems to be broken under MSVC. :-/ - return xx_BitsPerElement(_Val_type(TIterator())); -#else return CHAR_BIT * sizeof(typename iterator_traits::value_type); -#endif } @@ -177,18 +169,7 @@ template TOut ExtractBits(TIterator& start, const TIterator& end, size_t& bit_offset, size_t bit_count) { -#if 1 static const size_t kBitsPerElement = x_BitsPerElement(start); -#elif defined(_RWSTD_NO_CLASS_PARTIAL_SPEC) - static const size_t kBitsPerElement - = xx_BitsPerElement(__value_type(TIterator())); -#elif defined(NCBI_COMPILER_MSVC) - static const size_t kBitsPerElement - = xx_BitsPerElement(_Val_type(TIterator())); -#else - static const size_t kBitsPerElement - = CHAR_BIT * sizeof(typename iterator_traits::value_type); -#endif const TOut kMask = (1 << bit_count) - 1; static const TOut kMask2 = (1 << kBitsPerElement) - 1; diff --git a/c++/include/util/resource_pool.hpp b/c++/include/util/resource_pool.hpp index ebbdea9f..cd832c15 100644 --- a/c++/include/util/resource_pool.hpp +++ b/c++/include/util/resource_pool.hpp @@ -1,7 +1,7 @@ #ifndef UTIL___RESOURCEPOOL__HPP #define UTIL___RESOURCEPOOL__HPP -/* $Id: resource_pool.hpp 144314 2008-10-28 22:52:29Z joukovv $ +/* $Id: resource_pool.hpp 500279 2016-05-03 17:12:04Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -385,7 +385,7 @@ public: if (m_Bucket.size() < i) { break; } - TResourcePool* rp = m_Bucket[i]; + rp = m_Bucket[i]; }} if (rp) { rp->FreeAll(); diff --git a/c++/include/util/simple_buffer.hpp b/c++/include/util/simple_buffer.hpp index 2e63fbc6..8e6a6af7 100644 --- a/c++/include/util/simple_buffer.hpp +++ b/c++/include/util/simple_buffer.hpp @@ -1,7 +1,7 @@ #ifndef UTIL_SIMPLE_BUFFER__HPP #define UTIL_SIMPLE_BUFFER__HPP -/* $Id: simple_buffer.hpp 437337 2014-06-05 13:51:11Z ucko $ +/* $Id: simple_buffer.hpp 500279 2016-05-03 17:12:04Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -88,14 +88,14 @@ public: typedef T value_type; typedef size_t size_type; public: - explicit CSimpleBufferT(size_type size=0) + explicit CSimpleBufferT(size_type new_size = 0) { - if (size) { - m_Buffer = x_Allocate(size); + if (new_size) { + m_Buffer = x_Allocate(new_size); } else { m_Buffer = 0; } - m_Size = m_Capacity = size; + m_Size = m_Capacity = new_size; } ~CSimpleBufferT() { @@ -242,12 +242,15 @@ public: private: + +#ifdef _DEBUG void x_Fill(value_type* buffer, int value, size_t elem) { -#ifdef _DEBUG memset(buffer, value, elem * sizeof(value_type)); -#endif } +#else + void x_Fill(value_type*, int, size_t) {} +#endif void x_Deallocate() { diff --git a/c++/include/util/static_set.hpp b/c++/include/util/static_set.hpp index f1661d71..49bdd897 100644 --- a/c++/include/util/static_set.hpp +++ b/c++/include/util/static_set.hpp @@ -1,7 +1,7 @@ #ifndef UTIL___STATIC_SET__HPP #define UTIL___STATIC_SET__HPP -/* $Id: static_set.hpp 361095 2012-04-30 14:12:22Z vasilche $ +/* $Id: static_set.hpp 500279 2016-05-03 17:12:04Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -738,18 +738,18 @@ protected: using namespace NStaticArray; CheckStaticType(file, line); _ASSERT(array_size % sizeof(value_type) == 0); - size_t size = array_size / sizeof(value_type); + size_t sz = array_size / sizeof(value_type); if ( m_Begin.second() ) { _ASSERT(m_Begin.second() == array_ptr); - _ASSERT(m_End == array_ptr + size); + _ASSERT(m_End == array_ptr + sz); _ASSERT(!m_DeallocateFunc); } else { - x_Validate(array_ptr, size, value_comp(), file, line); + x_Validate(array_ptr, sz, value_comp(), file, line); } m_DeallocateFunc = 0; m_Begin.second() = array_ptr; - m_End = array_ptr + size; + m_End = array_ptr + sz; } /// Assign array pointer and end pointer from differently typed array. @@ -762,10 +762,10 @@ protected: using namespace NStaticArray; CheckStaticType(file, line); _ASSERT(array2_size % sizeof(Type) == 0); - size_t size = array2_size / sizeof(Type); + size_t sz = array2_size / sizeof(Type); CArrayHolder holder(MakeConverter(static_cast(0), static_cast(0))); - holder.Convert(array2_ptr, size, file, line, warn); + holder.Convert(array2_ptr, sz, file, line, warn); if ( !m_Begin.second() ) { x_Validate(static_cast(holder.GetArrayPtr()), holder.GetElementCount(), value_comp(), file, line); @@ -775,7 +775,7 @@ protected: if ( !m_Begin.second() ) { m_Begin.second() = static_cast(holder.ReleaseArrayPtr()); - m_End = m_Begin.second() + size; + m_End = m_Begin.second() + sz; m_DeallocateFunc = x_DeallocateFunc; } }} diff --git a/c++/include/util/stream_source.hpp b/c++/include/util/stream_source.hpp index 0c12d0a9..dafa0345 100644 --- a/c++/include/util/stream_source.hpp +++ b/c++/include/util/stream_source.hpp @@ -1,7 +1,7 @@ #ifndef UTIL___STREAM_SOURCE__HPP #define UTIL___STREAM_SOURCE__HPP -/* $Id: stream_source.hpp 497775 2016-04-11 11:26:07Z mozese2 $ +/* $Id: stream_source.hpp 500707 2016-05-06 18:14:09Z vakatov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -62,7 +62,7 @@ BEGIN_NCBI_SCOPE /// CNcbiIstream& istr = *source; /// ... /// } -/// \encode +/// \endcode /// /// Streams are checked for error conditions at the start (badbit or /// failbit before being returned from the iterator) and end (badbit diff --git a/c++/include/util/strsearch.hpp b/c++/include/util/strsearch.hpp index d98d8b60..74cdcffe 100644 --- a/c++/include/util/strsearch.hpp +++ b/c++/include/util/strsearch.hpp @@ -1,7 +1,7 @@ #ifndef UTIL___STRSEARCH__HPP #define UTIL___STRSEARCH__HPP -/* $Id: strsearch.hpp 450776 2014-10-30 16:20:28Z vasilche $ +/* $Id: strsearch.hpp 501456 2016-05-16 15:12:46Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -395,7 +395,7 @@ typename CTextFsm::CState *CTextFsm::GetState(int state) template int CTextFsm::GetNextState(const CState& from, char letter) const { - char ch = m_CaseSensitive ? letter : toupper((unsigned char) letter); + char ch = m_CaseSensitive ? letter : (char)toupper((unsigned char) letter); return from.GetNextState(ch); } diff --git a/c++/include/util/table_printer.hpp b/c++/include/util/table_printer.hpp index 6c9df725..9139c479 100644 --- a/c++/include/util/table_printer.hpp +++ b/c++/include/util/table_printer.hpp @@ -1,7 +1,7 @@ #ifndef UTIL___TABLE_PRINTER__HPP #define UTIL___TABLE_PRINTER__HPP -/* $Id: table_printer.hpp 433382 2014-04-24 17:15:18Z gotvyans $ +/* $Id: table_printer.hpp 500279 2016-05-03 17:12:04Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -257,7 +257,7 @@ private: template<> inline CTablePrinter & operator << ( - CTablePrinter & table_printer, const CTablePrinter::SEndOfCell & end_of_cell ) + CTablePrinter & table_printer, const CTablePrinter::SEndOfCell & /*end_of_cell*/) { return table_printer.EndOfCurrentCell(); } diff --git a/c++/include/util/tables/raw_scoremat.h b/c++/include/util/tables/raw_scoremat.h index d0c9aceb..b3f4b5b5 100644 --- a/c++/include/util/tables/raw_scoremat.h +++ b/c++/include/util/tables/raw_scoremat.h @@ -1,7 +1,7 @@ #ifndef UTIL_TABLES___SCOREMAT__H #define UTIL_TABLES___SCOREMAT__H -/* $Id: raw_scoremat.h 458581 2015-02-06 15:18:12Z boratyng $ +/* $Id: raw_scoremat.h 501870 2016-05-19 16:29:22Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -42,7 +42,7 @@ extern "C" { /** data types */ -typedef signed char TNCBIScore; +typedef int TNCBIScore; /* historically signed char */ typedef struct SNCBIPackedScoreMatrix { const char* symbols; /**< order of residues */ const TNCBIScore* scores; /**< strlen(symbols) x strlen(symbols) */ diff --git a/c++/include/util/timsort.hpp b/c++/include/util/timsort.hpp new file mode 100644 index 00000000..24a3a1b0 --- /dev/null +++ b/c++/include/util/timsort.hpp @@ -0,0 +1,666 @@ +/* + * C++ implementation of timsort + * + * ported from Python's and OpenJDK's: + * - http://svn.python.org/projects/python/trunk/Objects/listobject.c + * - http://cr.openjdk.java.net/~martin/webrevs/openjdk7/timsort/raw_files/new/src/share/classes/java/util/TimSort.java + * + * Copyright (c) 2011 Fuji, Goro (gfx) . + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef GFX_TIMSORT_HPP +#define GFX_TIMSORT_HPP + +#include +#include +#include +#include +#include + +#ifdef ENABLE_TIMSORT_LOG +#include +#define GFX_TIMSORT_LOG(expr) (std::clog << "# " << __func__ << ": " << expr << std::endl) +#else +#define GFX_TIMSORT_LOG(expr) ((void)0) +#endif + +#if __cplusplus >= 201103L && !DISABLE_STD_MOVE +#define ENABLE_STD_MOVE 1 +#endif + +#if ENABLE_STD_MOVE +#define GFX_TIMSORT_MOVE(x) std::move(x) +#define GFX_TIMSORT_MOVE_RANGE(in1, in2, out) std::move((in1), (in2), (out)) +#define GFX_TIMSORT_MOVE_BACKWARD(in1, in2, out) std::move_backward((in1), (in2), (out)) +#else +#define GFX_TIMSORT_MOVE(x) (x) +#define GFX_TIMSORT_MOVE_RANGE(in1, in2, out) std::copy((in1), (in2), (out)) +#define GFX_TIMSORT_MOVE_BACKWARD(in1, in2, out) std::copy_backward((in1), (in2), (out)) +#endif + +namespace gfx { + +// --------------------------------------- +// Declaration +// --------------------------------------- + +/** + * Same as std::stable_sort(first, last). + */ +template +inline void timsort(RandomAccessIterator const first, RandomAccessIterator const last); + +/** + * Same as std::stable_sort(first, last, c). + */ +template +inline void timsort(RandomAccessIterator const first, RandomAccessIterator const last, LessFunction compare); + +// --------------------------------------- +// Implementation +// --------------------------------------- + +template class Compare { + public: + typedef Value value_type; + typedef LessFunction func_type; + + Compare(LessFunction f) : less_(f) { + } + Compare(const Compare &other) : less_(other.less_) { + } + + bool lt(value_type x, value_type y) { + return less_(x, y); + } + bool le(value_type x, value_type y) { + return less_(x, y) || !less_(y, x); + } + bool gt(value_type x, value_type y) { + return !less_(x, y) && less_(y, x); + } + bool ge(value_type x, value_type y) { + return !less_(x, y); + } + + func_type &less_function() { + return less_; + } + + private: + func_type less_; +}; + +template class TimSort { + typedef RandomAccessIterator iter_t; + typedef typename std::iterator_traits::value_type value_t; + typedef typename std::iterator_traits::reference ref_t; + typedef typename std::iterator_traits::difference_type diff_t; + typedef Compare compare_t; + + static const int MIN_MERGE = 32; + + compare_t comp_; + + static const int MIN_GALLOP = 7; + + int minGallop_; // default to MIN_GALLOP + + std::vector tmp_; // temp storage for merges + typedef typename std::vector::iterator tmp_iter_t; + + struct run { + iter_t base; + diff_t len; + + run(iter_t const b, diff_t const l) : base(b), len(l) { + } + }; + std::vector pending_; + + static void sort(iter_t const lo, iter_t const hi, compare_t c) { + assert(lo <= hi); + + diff_t nRemaining = (hi - lo); + if (nRemaining < 2) { + return; // nothing to do + } + + if (nRemaining < MIN_MERGE) { + diff_t const initRunLen = countRunAndMakeAscending(lo, hi, c); + GFX_TIMSORT_LOG("initRunLen: " << initRunLen); + binarySort(lo, hi, lo + initRunLen, c); + return; + } + + TimSort ts(c); + diff_t const minRun = minRunLength(nRemaining); + iter_t cur = lo; + do { + diff_t runLen = countRunAndMakeAscending(cur, hi, c); + + if (runLen < minRun) { + diff_t const force = std::min(nRemaining, minRun); + binarySort(cur, cur + force, cur + runLen, c); + runLen = force; + } + + ts.pushRun(cur, runLen); + ts.mergeCollapse(); + + cur += runLen; + nRemaining -= runLen; + } while (nRemaining != 0); + + assert(cur == hi); + ts.mergeForceCollapse(); + assert(ts.pending_.size() == 1); + + GFX_TIMSORT_LOG("size: " << (hi - lo) << " tmp_.size(): " << ts.tmp_.size() + << " pending_.size(): " << ts.pending_.size()); + } // sort() + + static void binarySort(iter_t const lo, iter_t const hi, iter_t start, compare_t compare) { + assert(lo <= start && start <= hi); + if (start == lo) { + ++start; + } + for (; start < hi; ++start) { + assert(lo <= start); + /*const*/ value_t pivot = GFX_TIMSORT_MOVE(*start); + + iter_t const pos = std::upper_bound(lo, start, pivot, compare.less_function()); + for (iter_t p = start; p > pos; --p) { + *p = GFX_TIMSORT_MOVE(*(p - 1)); + } + *pos = GFX_TIMSORT_MOVE(pivot); + } + } + + static diff_t countRunAndMakeAscending(iter_t const lo, iter_t const hi, compare_t compare) { + assert(lo < hi); + + iter_t runHi = lo + 1; + if (runHi == hi) { + return 1; + } + + if (compare.lt(*(runHi++), *lo)) { // descending + while (runHi < hi && compare.lt(*runHi, *(runHi - 1))) { + ++runHi; + } + std::reverse(lo, runHi); + } else { // ascending + while (runHi < hi && compare.ge(*runHi, *(runHi - 1))) { + ++runHi; + } + } + + return runHi - lo; + } + + static diff_t minRunLength(diff_t n) { + assert(n >= 0); + + diff_t r = 0; + while (n >= MIN_MERGE) { + r |= (n & 1); + n >>= 1; + } + return n + r; + } + + TimSort(compare_t c) : comp_(c), minGallop_(MIN_GALLOP) { + } + + void pushRun(iter_t const runBase, diff_t const runLen) { + pending_.push_back(run(runBase, runLen)); + } + + void mergeCollapse() { + while (pending_.size() > 1) { + diff_t n = pending_.size() - 2; + + if ((n > 0 && pending_[n - 1].len <= pending_[n].len + pending_[n + 1].len) || + (n > 1 && pending_[n - 2].len <= pending_[n - 1].len + pending_[n].len)) { + if (pending_[n - 1].len < pending_[n + 1].len) { + --n; + } + mergeAt(n); + } else if (pending_[n].len <= pending_[n + 1].len) { + mergeAt(n); + } else { + break; + } + } + } + + void mergeForceCollapse() { + while (pending_.size() > 1) { + diff_t n = pending_.size() - 2; + + if (n > 0 && pending_[n - 1].len < pending_[n + 1].len) { + --n; + } + mergeAt(n); + } + } + + void mergeAt(diff_t const i) { + diff_t const stackSize = pending_.size(); + assert(stackSize >= 2); + assert(i >= 0); + assert(i == stackSize - 2 || i == stackSize - 3); + + iter_t base1 = pending_[i].base; + diff_t len1 = pending_[i].len; + iter_t base2 = pending_[i + 1].base; + diff_t len2 = pending_[i + 1].len; + + assert(len1 > 0 && len2 > 0); + assert(base1 + len1 == base2); + + pending_[i].len = len1 + len2; + + if (i == stackSize - 3) { + pending_[i + 1] = pending_[i + 2]; + } + + pending_.pop_back(); + + diff_t const k = gallopRight(*base2, base1, len1, 0); + assert(k >= 0); + + base1 += k; + len1 -= k; + + if (len1 == 0) { + return; + } + + len2 = gallopLeft(*(base1 + (len1 - 1)), base2, len2, len2 - 1); + assert(len2 >= 0); + if (len2 == 0) { + return; + } + + if (len1 <= len2) { + mergeLo(base1, len1, base2, len2); + } else { + mergeHi(base1, len1, base2, len2); + } + } + + template diff_t gallopLeft(ref_t key, Iter const base, diff_t const len, diff_t const hint) { + assert(len > 0 && hint >= 0 && hint < len); + + diff_t lastOfs = 0; + diff_t ofs = 1; + + if (comp_.gt(key, *(base + hint))) { + diff_t const maxOfs = len - hint; + while (ofs < maxOfs && comp_.gt(key, *(base + (hint + ofs)))) { + lastOfs = ofs; + ofs = (ofs << 1) + 1; + + if (ofs <= 0) { // int overflow + ofs = maxOfs; + } + } + if (ofs > maxOfs) { + ofs = maxOfs; + } + + lastOfs += hint; + ofs += hint; + } else { + diff_t const maxOfs = hint + 1; + while (ofs < maxOfs && comp_.le(key, *(base + (hint - ofs)))) { + lastOfs = ofs; + ofs = (ofs << 1) + 1; + + if (ofs <= 0) { + ofs = maxOfs; + } + } + if (ofs > maxOfs) { + ofs = maxOfs; + } + + diff_t const tmp = lastOfs; + lastOfs = hint - ofs; + ofs = hint - tmp; + } + assert(-1 <= lastOfs && lastOfs < ofs && ofs <= len); + + return std::lower_bound(base + (lastOfs + 1), base + ofs, key, comp_.less_function()) - base; + } + + template diff_t gallopRight(ref_t key, Iter const base, diff_t const len, diff_t const hint) { + assert(len > 0 && hint >= 0 && hint < len); + + diff_t ofs = 1; + diff_t lastOfs = 0; + + if (comp_.lt(key, *(base + hint))) { + diff_t const maxOfs = hint + 1; + while (ofs < maxOfs && comp_.lt(key, *(base + (hint - ofs)))) { + lastOfs = ofs; + ofs = (ofs << 1) + 1; + + if (ofs <= 0) { + ofs = maxOfs; + } + } + if (ofs > maxOfs) { + ofs = maxOfs; + } + + diff_t const tmp = lastOfs; + lastOfs = hint - ofs; + ofs = hint - tmp; + } else { + diff_t const maxOfs = len - hint; + while (ofs < maxOfs && comp_.ge(key, *(base + (hint + ofs)))) { + lastOfs = ofs; + ofs = (ofs << 1) + 1; + + if (ofs <= 0) { // int overflow + ofs = maxOfs; + } + } + if (ofs > maxOfs) { + ofs = maxOfs; + } + + lastOfs += hint; + ofs += hint; + } + assert(-1 <= lastOfs && lastOfs < ofs && ofs <= len); + + return std::upper_bound(base + (lastOfs + 1), base + ofs, key, comp_.less_function()) - base; + } + + void mergeLo(iter_t const base1, diff_t len1, iter_t const base2, diff_t len2) { + assert(len1 > 0 && len2 > 0 && base1 + len1 == base2); + + copy_to_tmp(base1, len1); + + tmp_iter_t cursor1 = tmp_.begin(); + iter_t cursor2 = base2; + iter_t dest = base1; + + *(dest++) = GFX_TIMSORT_MOVE(*(cursor2++)); + if (--len2 == 0) { + GFX_TIMSORT_MOVE_RANGE(cursor1, cursor1 + len1, dest); + return; + } + if (len1 == 1) { + GFX_TIMSORT_MOVE_RANGE(cursor2, cursor2 + len2, dest); + *(dest + len2) = GFX_TIMSORT_MOVE(*cursor1); + return; + } + + int minGallop(minGallop_); + + // outer: + while (true) { + diff_t count1 = 0; + diff_t count2 = 0; + + bool break_outer = false; + do { + assert(len1 > 1 && len2 > 0); + + if (comp_.lt(*cursor2, *cursor1)) { + *(dest++) = GFX_TIMSORT_MOVE(*(cursor2++)); + ++count2; + count1 = 0; + if (--len2 == 0) { + break_outer = true; + break; + } + } else { + *(dest++) = GFX_TIMSORT_MOVE(*(cursor1++)); + ++count1; + count2 = 0; + if (--len1 == 1) { + break_outer = true; + break; + } + } + } while ((count1 | count2) < minGallop); + if (break_outer) { + break; + } + + do { + assert(len1 > 1 && len2 > 0); + + count1 = gallopRight(*cursor2, cursor1, len1, 0); + if (count1 != 0) { + GFX_TIMSORT_MOVE_BACKWARD(cursor1, cursor1 + count1, dest + count1); + dest += count1; + cursor1 += count1; + len1 -= count1; + + if (len1 <= 1) { + break_outer = true; + break; + } + } + *(dest++) = GFX_TIMSORT_MOVE(*(cursor2++)); + if (--len2 == 0) { + break_outer = true; + break; + } + + count2 = gallopLeft(*cursor1, cursor2, len2, 0); + if (count2 != 0) { + GFX_TIMSORT_MOVE_RANGE(cursor2, cursor2 + count2, dest); + dest += count2; + cursor2 += count2; + len2 -= count2; + if (len2 == 0) { + break_outer = true; + break; + } + } + *(dest++) = GFX_TIMSORT_MOVE(*(cursor1++)); + if (--len1 == 1) { + break_outer = true; + break; + } + + --minGallop; + } while ((count1 >= MIN_GALLOP) | (count2 >= MIN_GALLOP)); + if (break_outer) { + break; + } + + if (minGallop < 0) { + minGallop = 0; + } + minGallop += 2; + } // end of "outer" loop + + minGallop_ = std::min(minGallop, 1); + + if (len1 == 1) { + assert(len2 > 0); + GFX_TIMSORT_MOVE_RANGE(cursor2, cursor2 + len2, dest); + *(dest + len2) = GFX_TIMSORT_MOVE(*cursor1); + } else { + assert(len1 != 0 && "Comparison function violates its general contract"); + assert(len2 == 0); + assert(len1 > 1); + GFX_TIMSORT_MOVE_RANGE(cursor1, cursor1 + len1, dest); + } + } + + void mergeHi(iter_t const base1, diff_t len1, iter_t const base2, diff_t len2) { + assert(len1 > 0 && len2 > 0 && base1 + len1 == base2); + + copy_to_tmp(base2, len2); + + iter_t cursor1 = base1 + len1; + tmp_iter_t cursor2 = tmp_.begin() + len2; + iter_t dest = base2 + len2; + + *(--dest) = GFX_TIMSORT_MOVE(*(--cursor1)); + if (--len1 == 0) { + GFX_TIMSORT_MOVE_RANGE(tmp_.begin(), tmp_.begin() + len2, dest - len2); + return; + } + if (len2 == 1) { + dest -= len1; + cursor1 -= len1; + GFX_TIMSORT_MOVE_BACKWARD(cursor1, cursor1 + len1, dest + len1); + *(--dest) = GFX_TIMSORT_MOVE(*(--cursor2)); + return; + } + + int minGallop(minGallop_); + + // outer: + while (true) { + diff_t count1 = 0; + diff_t count2 = 0; + + bool break_outer = false; + do { + assert(len1 > 0 && len2 > 1); + + if (comp_.lt(*(cursor2-1), *(cursor1-1))) { + *(--dest) = GFX_TIMSORT_MOVE(*(--cursor1)); + ++count1; + count2 = 0; + if (--len1 == 0) { + break_outer = true; + break; + } + } else { + *(--dest) = GFX_TIMSORT_MOVE(*(--cursor2)); + ++count2; + count1 = 0; + if (--len2 == 1) { + break_outer = true; + break; + } + } + } while ((count1 | count2) < minGallop); + if (break_outer) { + break; + } + + do { + assert(len1 > 0 && len2 > 1); + + count1 = len1 - gallopRight(*(cursor2-1), base1, len1, len1 - 1); + if (count1 != 0) { + dest -= count1; + cursor1 -= count1; + len1 -= count1; + GFX_TIMSORT_MOVE_BACKWARD(cursor1, cursor1 + count1, dest + count1); + + if (len1 == 0) { + break_outer = true; + break; + } + } + *(--dest) = GFX_TIMSORT_MOVE(*(--cursor2)); + if (--len2 == 1) { + break_outer = true; + break; + } + + count2 = len2 - gallopLeft(*(cursor1-1), tmp_.begin(), len2, len2 - 1); + if (count2 != 0) { + dest -= count2; + cursor2 -= count2; + len2 -= count2; + GFX_TIMSORT_MOVE_RANGE(cursor2, cursor2 + count2, dest); + if (len2 <= 1) { + break_outer = true; + break; + } + } + *(--dest) = GFX_TIMSORT_MOVE(*(--cursor1)); + if (--len1 == 0) { + break_outer = true; + break; + } + + minGallop--; + } while ((count1 >= MIN_GALLOP) | (count2 >= MIN_GALLOP)); + if (break_outer) { + break; + } + + if (minGallop < 0) { + minGallop = 0; + } + minGallop += 2; + } // end of "outer" loop + + minGallop_ = std::min(minGallop, 1); + + if (len2 == 1) { + assert(len1 > 0); + dest -= len1; + GFX_TIMSORT_MOVE_BACKWARD(cursor1 - len1, cursor1, dest + len1); + *(--dest) = GFX_TIMSORT_MOVE(*(--cursor2)); + } else { + assert(len2 != 0 && "Comparison function violates its general contract"); + assert(len1 == 0); + assert(len2 > 1); + GFX_TIMSORT_MOVE_RANGE(tmp_.begin(), tmp_.begin() + len2, dest - len2); + } + } + + void copy_to_tmp(iter_t const begin, diff_t const len) { + tmp_.clear(); + tmp_.reserve(len); + GFX_TIMSORT_MOVE_RANGE(begin, begin + len, std::back_inserter(tmp_)); + } + + // the only interface is the friend timsort() function + template friend void timsort(IterT first, IterT last, LessT c); +}; + +template +inline void timsort(RandomAccessIterator const first, RandomAccessIterator const last) { + typedef typename std::iterator_traits::value_type value_type; + timsort(first, last, std::less()); +} + +template +inline void timsort(RandomAccessIterator const first, RandomAccessIterator const last, LessFunction compare) { + TimSort::sort(first, last, compare); +} + +} // namespace gfx + +#undef GFX_TIMSORT_LOG +#undef GFX_TIMSORT_MOVE +#undef GFX_TIMSORT_MOVE_RANGE +#undef GFX_TIMSORT_MOVE_BACKWARD +#endif // GFX_TIMSORT_HPP diff --git a/c++/include/util/value_convert.hpp b/c++/include/util/value_convert.hpp index 09ae3693..8a5a2575 100644 --- a/c++/include/util/value_convert.hpp +++ b/c++/include/util/value_convert.hpp @@ -1,7 +1,7 @@ #ifndef UTIL___VALUE_CONVERT__HPP #define UTIL___VALUE_CONVERT__HPP -/* $Id: value_convert.hpp 499843 2016-04-28 16:12:36Z ivanov $ +/* $Id: value_convert.hpp 499250 2016-04-25 12:27:42Z gouriano $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/include/util/value_convert_policy.hpp b/c++/include/util/value_convert_policy.hpp index 5471d707..e34d59aa 100644 --- a/c++/include/util/value_convert_policy.hpp +++ b/c++/include/util/value_convert_policy.hpp @@ -1,7 +1,7 @@ #ifndef UTIL___VALUE_CONV_POLICY__HPP #define UTIL___VALUE_CONV_POLICY__HPP -/* $Id: value_convert_policy.hpp 499843 2016-04-28 16:12:36Z ivanov $ +/* $Id: value_convert_policy.hpp 499250 2016-04-25 12:27:42Z gouriano $ * =========================================================================== * * PUBLIC DOMAIN NTOICE diff --git a/c++/scripts/common/add_vdb.sh b/c++/scripts/common/add_vdb.sh index 8d66b717..e6346b03 100755 --- a/c++/scripts/common/add_vdb.sh +++ b/c++/scripts/common/add_vdb.sh @@ -1,5 +1,5 @@ #!/bin/sh -# $Id: add_vdb.sh 486134 2015-12-01 18:54:11Z ucko $ +# $Id: add_vdb.sh 515777 2016-10-05 17:33:58Z ivanov $ . "`dirname $0`/common.sh" set -e @@ -33,7 +33,7 @@ if [ ! -d interfaces ]; then git checkout master fi if [ "$platform" = IntelMAC ]; then - archflag=--arch=fat86 + # archflag=--arch=fat86 if [ ! -d $root/tmp/force-clang ]; then mkdir -p $root/tmp/force-clang ln -s /usr/bin/clang $root/tmp/force-clang/gcc @@ -45,6 +45,12 @@ fi ./configure --prefix=$root/$name --build-prefix=$root/build/$name $archflag \ ${LIBXML_LIBPATH:+"LDFLAGS=$LIBXML_LIBPATH"} make + +for x in lib lib64; do + if [ -L $root/$name/$x ]; then + rm $root/$name/$x + fi +done make install if [ -f $root/$name/include/klib/rc.h ]; then : diff --git a/c++/scripts/common/check/check_add.sh b/c++/scripts/common/check/check_add.sh index e3793da8..7ffcca1b 100755 --- a/c++/scripts/common/check/check_add.sh +++ b/c++/scripts/common/check/check_add.sh @@ -1,5 +1,5 @@ #! /bin/sh -# $Id: check_add.sh 487040 2015-12-14 17:30:22Z ivanov $ +# $Id: check_add.sh 512371 2016-08-30 14:51:15Z ivanov $ # Author: Vladimir Ivanov, NCBI # ########################################################################### @@ -121,7 +121,14 @@ fi # Write data about current test into the list file for x_cmd in $x_run; do x_cmd=`echo "$x_cmd" | sed -e 's/%gj_s4%/ /g'` - x_name=`echo "$x_cmd" | sed -e 's/^.*CHECK_NAME *= *\([A-Za-z0-9_]*\).*/\1/' -e 's/.*CHECK_CMD.*//'` + x_name=`echo "$x_cmd" | sed -e 's/^.*CHECK_NAME *= *//' -e 's/ *$//' -e 's/.*CHECK_CMD.*//'` + if [ -n "$x_name" ]; then + xx_name=`echo "$x_name" | sed -e 's/\([A-Za-z0-9_.-]*\).*/\1/'` + if [ "$x_name" != "$xx_name" ]; then + echo "Warning: Incorrect CHECK_NAME value '$x_name', '$xx_name' will be used instead. Please fix." + x_name=$xx_name + fi + fi x_cmd=`echo "$x_cmd" | sed -e 's/ *\/CHECK_NAME.*//' -e 's/^[^=]*=//' -e 's/^ *//' -e 's/\"/\\\\"/g'` echo "$x_srcdir_rel$x_delim$x_test$x_delim$x_app$x_delim$x_cmd$x_delim$x_name$x_delim$x_files$x_delim$x_timeout$x_delim$x_requires$x_delim$x_watchers" >> $x_out done diff --git a/c++/scripts/common/check/check_make_cfg.sh b/c++/scripts/common/check/check_make_cfg.sh index 89af5e44..57f32a5c 100755 --- a/c++/scripts/common/check/check_make_cfg.sh +++ b/c++/scripts/common/check/check_make_cfg.sh @@ -1,6 +1,6 @@ #! /bin/sh -# $Id: check_make_cfg.sh 500063 2016-05-02 12:21:38Z ivanov $ +# $Id: check_make_cfg.sh 499855 2016-04-28 17:06:32Z ivanov $ # Author: Vladimir Ivanov, NCBI # ########################################################################### diff --git a/c++/scripts/common/check/check_make_unix.sh b/c++/scripts/common/check/check_make_unix.sh index e8f9ac09..b739524e 100755 --- a/c++/scripts/common/check/check_make_unix.sh +++ b/c++/scripts/common/check/check_make_unix.sh @@ -1,6 +1,6 @@ #! /bin/sh -# $Id: check_make_unix.sh 500063 2016-05-02 12:21:38Z ivanov $ +# $Id: check_make_unix.sh 501272 2016-05-12 20:12:39Z vakatov $ # Author: Vladimir Ivanov, NCBI # ########################################################################### @@ -432,7 +432,12 @@ fi if test "\$NCBI_CHECK_SETLIMITS" != "0"; then ulimit -c 1000000 if [ \$cygwin = false ]; then - ulimit -v 4000000 + if test "\$NCBI_CHECK_TOOLS" = "regular"; then + ulimit -v 4000000 + else + # Increase memory limits if run under check tool + ulimit -v 16000000 + fi fi fi diff --git a/c++/scripts/common/check/inspxe-suppressions/_vs.sup b/c++/scripts/common/check/inspxe-suppressions/_vs.sup index 05b25f0c..c769d1e2 100644 --- a/c++/scripts/common/check/inspxe-suppressions/_vs.sup +++ b/c++/scripts/common/check/inspxe-suppressions/_vs.sup @@ -263,39 +263,71 @@ suppression = { } } suppression = { - name = "False positive in MS implementation of basic_string::assign()" + name = "libsybct64.dll internal problem" type = {invalid_memory_access} stacks = { { !!!; - src=xstring,func=assign,line=1160,func_line=12; + mod=ntdll.dll,func=RtlCompareUnicodeStrings; + ...; + mod=libsybct64.dll,func=ct_dynsqlda; } } } suppression = { - name = "libsybct64.dll internal problem" + name = "Unreachable MSVCR120.dll memory error in stat64()" type = {invalid_memory_access} stacks = { allocation={ - !!!; - mod=ntdll.dll,func=RtlCompareUnicodeStrings; ...; - mod=libsybct64.dll,func=ct_dynsqlda; + mod=MSVCR120.dll,func=stat64; + } + { + ...; + mod=MSVCR120.dll,func=stat64; } } } suppression = { - name = "MSVCR120.dll memory error in stat64()" + name = "Unreachable OLEAUT32.dll memory error in SysStringByteLen()" type = {invalid_memory_access} stacks = { - allocation={ + { ...; - mod=MSVCR120.dll,func=stat64; + mod=OLEAUT32.dll,func=SysStringByteLen; } + } +} +suppression = { + name = "Unreachable libgnutls-30.dll memory error in gnutls_psk_set_server_params_function()" + type = {invalid_memory_access} + stacks = { + { + !!!; + mod=libgnutls-30.dll,func=gnutls_psk_set_server_params_function; + } + } +} +suppression = { + name = "False positive in operator<<()" + type = {invalid_memory_access} + stacks = { { ...; - mod=MSVCR120.dll,func=stat64; + mod=MSVCR120.dll,func=flsbuf; + } + } +} +suppression = { + name = "False positive in fclose()" + type = {invalid_memory_access} + stacks = { + { + ...; + mod=MSVCR120.dll,func=write; + ...; + mod=MSVCR120.dll,func=fclose; + func=close,src=fstream; } } } - diff --git a/c++/scripts/common/check/inspxe-suppressions/connect.sup b/c++/scripts/common/check/inspxe-suppressions/connect.sup index 9436a0ee..6dee664f 100644 --- a/c++/scripts/common/check/inspxe-suppressions/connect.sup +++ b/c++/scripts/common/check/inspxe-suppressions/connect.sup @@ -46,3 +46,17 @@ suppression = { } } } +suppression = { + name = "gnutls_handshake() non-important (only DLL build)" + type = {invalid_memory_access_partial} + stacks = { + allocation={ + !!!; + mod=test_netstorage.exe,func=s_GnuTlsOpen; + } + { + !!!; + mod=libgnutls-28.dll,func=gnutls_psk_set_server_params_function; + } + } +} diff --git a/c++/scripts/common/check/inspxe-suppressions/corelib.sup b/c++/scripts/common/check/inspxe-suppressions/corelib.sup index dd9a191d..00289091 100644 --- a/c++/scripts/common/check/inspxe-suppressions/corelib.sup +++ b/c++/scripts/common/check/inspxe-suppressions/corelib.sup @@ -118,3 +118,27 @@ suppression = { } } } +suppression = { + name = "False positive in basic_string::assign() called from CNcbiEnvironment constructor" + type = {invalid_memory_access} + stacks = { + { + ...; + func=assign,src=xstring; + func=Reset,src=ncbienv.cpp; + func=CNcbiEnvironment,src=ncbienv.cpp; + } + } +} +suppression = { + name = "False positive in basic_string::assign() called from CNcbiEnvironment constructor" + type = {invalid_memory_access_partial} + stacks = { + { + ...; + func=assign,src=xstring; + func=Reset,src=ncbienv.cpp; + func=CNcbiEnvironment,src=ncbienv.cpp; + } + } +} diff --git a/c++/scripts/common/check/inspxe-suppressions/misc.sup b/c++/scripts/common/check/inspxe-suppressions/misc.sup index 3631e5d3..130f9aba 100644 --- a/c++/scripts/common/check/inspxe-suppressions/misc.sup +++ b/c++/scripts/common/check/inspxe-suppressions/misc.sup @@ -18,3 +18,44 @@ suppression = { } } } +suppression = { + name = "Deallocation without allocation in KNgcObjWriteToFile() at ncbi_vdb.dll - False positive" + type = {invalid_deallocation} + stacks = { + { + ...; + func=KNgcObjWriteToFile; + } + } +} +suppression = { + name = "Missing allocation in vdbread.cpp:707 - False positive" + type = {invalid_deallocation} + stacks = { + { + !!!; + src=vdbread.cpp,func=Init; + } + } +} +suppression = { + name = "Invalid memory access in vdbread.cpp:477 - False positive" + type = {invalid_memory_access} + stacks = { + { + ...; + src=vdbread.cpp,func=CVDB; + } + } +} +suppression = { + name = "Invalid memory access in libgnutls" + type = {invalid_memory_access} + stacks = { + allocation = { + ...; + func=gnutls_pkcs12_export2; + } + } +} + diff --git a/c++/scripts/common/check/inspxe.sh b/c++/scripts/common/check/inspxe.sh index 5b5d2f02..fcac9c24 100755 --- a/c++/scripts/common/check/inspxe.sh +++ b/c++/scripts/common/check/inspxe.sh @@ -37,7 +37,7 @@ exe=$1.exe shift # Run test -"$inspxe" -collect mi3 -knob detect-resource-leaks=false -knob stack-depth=32 -result-dir $rd -return-app-exitcode -suppression-file "$suppress_dir" -- $exe "$@" +"$inspxe" -collect mi3 -knob detect-leaks-on-exit=false -knob enable-memory-growth-detection=false -knob enable-on-demand-leak-detection=false -knob still-allocated-memory=false -knob detect-resource-leaks=false -knob stack-depth=32 -result-dir $rd -return-app-exitcode -suppression-file "$suppress_dir" -- $exe "$@" app_result=$? "$inspxe" -report problems -report-all -result-dir $rd insp_result=$? diff --git a/c++/scripts/common/check/valgrind.supp b/c++/scripts/common/check/valgrind.supp index 8573afda..c7f4bc46 100644 --- a/c++/scripts/common/check/valgrind.supp +++ b/c++/scripts/common/check/valgrind.supp @@ -1,4 +1,4 @@ -# $Id: valgrind.supp 481966 2015-10-19 16:23:39Z vakatov $ +# $Id: valgrind.supp 493573 2016-02-29 19:59:14Z vakatov $ # # Valgrind suppression file (version 3.5.0 -> 3.11.0). # @@ -335,6 +335,29 @@ fun:_ZN4ncbi7CObject11InitCounterEv } +{ + Sybase CTLIB 15.7-SP122-64bit (Case 1) + Memcheck:Addr1 + fun:com_secure_memset + fun:ct__tds_loginover + fun:ct_async_exec_stack + fun:ct_connect +} + +{ + Sybase DBLIB 15.7-SP122-64bit (Case 2) + Memcheck:Param + socketcall.sendto(msg) + fun:send + fun:sybsoc_write + fun:sybnet_write + fun:write_buffer + fun:sendflush + fun:sendeom + fun:bcp__endbatch + fun:bcp_done +} + { Sybase DBLIB 12.5.1.10-ESD26-64bit (case 1) Memcheck:Param diff --git a/c++/scripts/common/impl/compress_tests.sh b/c++/scripts/common/impl/compress_tests.sh index 7cc317f6..643c3fb4 100755 --- a/c++/scripts/common/impl/compress_tests.sh +++ b/c++/scripts/common/impl/compress_tests.sh @@ -39,7 +39,7 @@ for dir in "$@"; do targets="$targets `basename $f`$ext" ;; *blast* | datatool | gbench* | id1_fetch | idwwwget | lbsmc \ - | one2all ) + | one2all | run_with_lock ) ;; *) test "$compress_others" = "no" || \ diff --git a/c++/scripts/common/impl/install.sh b/c++/scripts/common/impl/install.sh index 66b3d452..e8fab72c 100755 --- a/c++/scripts/common/impl/install.sh +++ b/c++/scripts/common/impl/install.sh @@ -16,7 +16,7 @@ echo "[`date`]" -svn_location=`echo '$URL: https://svn.ncbi.nlm.nih.gov/repos/toolkit/release/blast/2.4.0/c++/scripts/common/impl/install.sh $' | sed "s%\\$[U]RL: *\\([^$][^$]*\\) \\$.*%\\1%"` +svn_location=`echo '$URL: https://svn.ncbi.nlm.nih.gov/repos/toolkit/release/blast/2.6.0/c++/scripts/common/impl/install.sh $' | sed "s%\\$[U]RL: *\\([^$][^$]*\\) \\$.*%\\1%"` svn_revision=`echo '$Revision: 429376 $' | sed "s%\\$[R]evision: *\\([^$][^$]*\\) \\$.*%\\1%"` script_name=`basename $0` diff --git a/c++/scripts/common/impl/python-config.py b/c++/scripts/common/impl/python-config.py new file mode 100755 index 00000000..d13a6ac0 --- /dev/null +++ b/c++/scripts/common/impl/python-config.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python +# $Id: python-config.py 503831 2016-06-08 14:54:36Z ucko $ + +from distutils import sysconfig +import sys + +def lookup(want): + if want == 'VERSION': + return sysconfig.get_config_var('VERSION') + elif want == 'INCLUDE': + return ('-I%s -I%s' % (sysconfig.get_python_inc(), + sysconfig.get_python_inc(True))) + elif want == 'LIBPATH': + return ' '.join(sysconfig.get_config_vars('LIBDIR', 'LIBPL')) + elif want == 'DEPS': + return ' '.join(sysconfig.get_config_vars('LIBS', 'SYSLIBS')) + elif want == 'LDVERSION': + return (sysconfig.get_config_var('LDVERSION') + or sysconfig.get_config_var('VERSION')) + elif want == 'LIBS': + return '-lpython' + lookup('LDVERSION') + ' ' + lookup('DEPS') + else: + raise RuntimeError('Unsupported mode ' + want) + +print(lookup(sys.argv[1].lstrip('-').upper())) diff --git a/c++/scripts/common/new_project.sh b/c++/scripts/common/new_project.sh index 42df8547..9932811f 100755 --- a/c++/scripts/common/new_project.sh +++ b/c++/scripts/common/new_project.sh @@ -1,9 +1,9 @@ #! /bin/sh -# $Id: new_project.sh 442644 2014-08-05 20:01:57Z ucko $ +# $Id: new_project.sh 501452 2016-05-16 15:10:32Z elisovdn $ # Authors: Denis Vakatov (vakatov@ncbi.nlm.nih.gov), # Aaron Ucko (ucko@ncbi.nlm.nih.gov) -svn_revision=`echo '$Revision: 442644 $' | sed "s%\\$[R]evision: *\\([^$][^$]*\\) \\$.*%\\1%"` +svn_revision=`echo '$Revision: 501452 $' | sed "s%\\$[R]evision: *\\([^$][^$]*\\) \\$.*%\\1%"` def_builddir="$NCBI/c++/Debug/build" repository_url='http://anonsvn.ncbi.nlm.nih.gov/repos/v1' @@ -38,6 +38,7 @@ ARGUMENTS: lib/dtd to build a library from an XML DTD lib/xsd to build a library from an XML Schema app[/basic] to build a simple application + app/multicmd to build a simple command-based application app/alnmgr to build an application using the alignment manager app/asn to build a library from ASN.1 spec, and sample application app/blast to build an application using BLAST diff --git a/c++/scripts/common/new_project.wsf b/c++/scripts/common/new_project.wsf index 9ca41d72..490ac1ba 100644 --- a/c++/scripts/common/new_project.wsf +++ b/c++/scripts/common/new_project.wsf @@ -157,6 +157,7 @@ usage_str += " -- name of the project\n"; usage_str += " -- one of the following:\n"; usage_str += " app[/basic] a simple application\n"; + usage_str += " app/multicmd a simple command-based application\n"; usage_str += " app/alnmgr an application that uses Alignment Manager\n"; usage_str += " app/asn an application that uses ASN.1 specification\n"; usage_str += " app/blast a BLAST application\n"; @@ -244,6 +245,7 @@ prompt += "This can be one of the following:\n"; prompt += "\tapp\n"; prompt += "\tapp/basic\n"; + prompt += "\tapp/multicmd\n"; prompt += "\tapp/alnmgr\n"; prompt += "\tapp/asn\n"; prompt += "\tapp/blast\n"; @@ -281,6 +283,7 @@ this.TemplatesDict = new ActiveXObject("Scripting.Dictionary"); this.TemplatesDict.Add("app", "sample/app/basic"); this.TemplatesDict.Add("app/basic", "sample/app/basic"); + this.TemplatesDict.Add("app/multicmd", "sample/app/multicmd"); this.TemplatesDict.Add("app/alnmgr", "sample/app/alnmgr"); this.TemplatesDict.Add("app/asn", "sample/app/asn"); this.TemplatesDict.Add("app/blast", "sample/app/blast"); diff --git a/c++/scripts/common/new_project_msvc7.bat b/c++/scripts/common/new_project_msvc7.bat deleted file mode 100755 index e8f9c1af..00000000 --- a/c++/scripts/common/new_project_msvc7.bat +++ /dev/null @@ -1,45 +0,0 @@ -IF _%1%==_ GOTO USAGE -IF _%2%==_ GOTO USAGE -ECHO %CD% - -:PREPARE -SET TREE_ROOT=%CD%\..\ - -SET PROJ_DIR=%TREE_ROOT%src\%1\ -SET COMPILERS_DIR=%TREE_ROOT%compilers\ -SET PTB_EXE_PATH=%COMPILERS_DIR%msvc710_prj\static\bin\debug\ -SET PTB_INI_PATH=%COMPILERS_DIR%msvc710_prj\ - -IF EXIST %PTB_EXE_PATH%project_tree_builder.exe GOTO START_PTB -:BUILD_PTB -ECHO "Building project_tree_builder ..." -devenv %COMPILERS_DIR%msvc710_prj\static\build\app\project_tree_builder\project_tree_builder.sln /build Debug /project "-BUILD-ALL-" > Debug.log -IF ERRORLEVEL 1 GOTO ABORT -ECHO "Completed." -GOTO START_PTB - -:START_PTB -ECHO "Creating requested solution ..." -%PTB_EXE_PATH%project_tree_builder.exe -logfile out.log -conffile %PTB_INI_PATH%project_tree_builder.ini %TREE_ROOT% src\%1 %PROJ_DIR%%2 -IF ERRORLEVEL 1 GOTO ABORT -ECHO "Completed." -GOTO OPEN_SOLUTION - -:OPEN_SOLUTION -devenv %PROJ_DIR%%2 -GOTO EXIT - -:USAGE -ECHO "bat file for starting a new project with MSVC 7.10" -ECHO "UNIX makefiles must be created first!" -ECHO "USAGE:" -ECHO "new_project_msvc7 " -ECHO "Example:" -ECHO "new_project_msvc7 internal\cppcore\test_stat test_stat.sln" -GOTO EXIT - -:ABORT -ECHO "FAILED" -GOTO EXIT - -:EXIT \ No newline at end of file diff --git a/c++/scripts/common/project_utilits.js b/c++/scripts/common/project_utilits.js index c1fca388..448d66bc 100644 --- a/c++/scripts/common/project_utilits.js +++ b/c++/scripts/common/project_utilits.js @@ -1,6 +1,6 @@ +// $Id: project_utilits.js 501454 2016-05-16 15:12:21Z elisovdn $ //////////////////////////////////////////////////////////////////////////////////// // Shared part of new_project.wsf and import_project.wsf - // global settings var g_verbose = false; var g_usefilecopy = true; @@ -10,7 +10,7 @@ var g_open_solution = true; var g_def_branch = "toolkit/trunk/internal/c++"; var g_branch = "toolkit/trunk/internal/c++"; -// valid: "71", "80", "80x64", "90", "90x64", "100", "100x64", "120", "120x64" +// valid: "120", "120x64", "140", "140x64" var g_def_msvcver = "120"; var g_msvcver = "120"; @@ -159,18 +159,11 @@ function GetConfigs(oTask) if (oTask.DllBuild) { var configs = new Array ("DebugDLL", "ReleaseDLL"); return configs; - } else { - if (g_msvcver == "71") { - var configs = new Array ( - "Debug", "DebugMT", "DebugDLL", - "Release", "ReleaseMT", "ReleaseDLL"); - return configs; - } else { - var configs = new Array ( - "DebugMT", "DebugDLL", - "ReleaseMT", "ReleaseDLL"); - return configs; - } + } else { + var configs = new Array ( + "DebugMT", "DebugDLL", + "ReleaseMT", "ReleaseDLL"); + return configs; } } // recursive path creator - oFso is pre-created file system object @@ -496,11 +489,10 @@ function SetMsvcVer(oArgs, flag) { var msvcver = GetFlaggedValue(oArgs, flag, ""); if (msvcver.length != 0) { - if (msvcver != "71" && msvcver != "80" && msvcver != "80x64" - && msvcver != "90" && msvcver != "90x64" - && msvcver != "100" && msvcver != "100x64" - && msvcver != "110" && msvcver != "110x64" - && msvcver != "120" && msvcver != "120x64" + if ( + msvcver != "110" && msvcver != "110x64" + && msvcver != "120" && msvcver != "120x64" + && msvcver != "140" && msvcver != "140x64" ) { WScript.Echo("ERROR: Unknown version of MSVC requested: " + msvcver); WScript.Quit(1); @@ -511,22 +503,16 @@ function SetMsvcVer(oArgs, flag) function GetMsvcFolder() { - if (g_msvcver == "80" || g_msvcver == "80x64") { - return "msvc800_prj"; - } - if (g_msvcver == "90" || g_msvcver == "90x64") { - return "msvc900_prj"; - } - if (g_msvcver == "100" || g_msvcver == "100x64") { - return "msvc1000_prj"; - } if (g_msvcver == "110" || g_msvcver == "110x64") { return "vs2013"; } if (g_msvcver == "120" || g_msvcver == "120x64") { return "vs2013"; } - return "msvc710_prj"; + if (g_msvcver == "140" || g_msvcver == "140x64") { + return "vs2015"; + } + return "vs2013"; } function GetFlaggedValue(oArgs, flag, default_val) @@ -591,25 +577,15 @@ function GetPositionalValue(oArgs, position) // Configuration of pre-built C++ toolkit function GetDefaultSuffix() { - var s = "msvc8"; - if (g_msvcver == "80") { - s = "msvc8"; - } else if (g_msvcver == "80x64") { - s = "msvc8.64"; - } else if (g_msvcver == "90") { - s = "msvc9"; - } else if (g_msvcver == "90x64") { - s = "msvc9.64"; - } else if (g_msvcver == "100") { - s = "msvc10"; - } else if (g_msvcver == "100x64") { - s = "msvc10.64"; - } else if (g_msvcver == "110" || g_msvcver == "120") { + var s = "vs2013"; + if (g_msvcver == "110" || g_msvcver == "120") { s = "vs2013"; } else if (g_msvcver == "110x64" || g_msvcver == "120x64") { s = "vs2013.64"; - } else { - s = "msvc71"; + } else if (g_msvcver == "140") { + s = "vs2015"; + } else if (g_msvcver == "140x64") { + s = "vs2015.64"; } return s; } @@ -620,19 +596,7 @@ function GetPtbTargetSolutionArgs(oShell, ptb) if (ver < 180) { return s; } - if (g_msvcver == "80") { - s = " -ide 800 -arch Win32"; - } else if (g_msvcver == "80x64") { - s = " -ide 800 -arch x64"; - } else if (g_msvcver == "90") { - s = " -ide 900 -arch Win32"; - } else if (g_msvcver == "90x64") { - s = " -ide 900 -arch x64"; - } else if (g_msvcver == "100") { - s = " -ide 1000 -arch Win32"; - } else if (g_msvcver == "100x64") { - s = " -ide 1000 -arch x64"; - } else if (g_msvcver == "110") { + if (g_msvcver == "110") { s = " -ide 1100 -arch Win32"; } else if (g_msvcver == "110x64") { s = " -ide 1100 -arch x64"; @@ -640,16 +604,19 @@ function GetPtbTargetSolutionArgs(oShell, ptb) s = " -ide 1200 -arch Win32"; } else if (g_msvcver == "120x64") { s = " -ide 1200 -arch x64"; + } else if (g_msvcver == "140") { + s = " -ide 1400 -arch Win32"; + } else if (g_msvcver == "140x64") { + s = " -ide 1400 -arch x64"; } else { - s = " -ide 710 -arch Win32"; + s = " -ide 1200 -arch Win32"; } return s; } function GetTargetPlatform() { - if (g_msvcver == "80x64" || g_msvcver == "90x64" || - g_msvcver == "100x64" || g_msvcver == "110x64" || - g_msvcver == "120x64") { + if (g_msvcver == "110x64" || + g_msvcver == "120x64" || g_msvcver == "140x64") { return "x64"; } return "Win32"; diff --git a/c++/scripts/projects/blast/LICENSE b/c++/scripts/projects/blast/LICENSE index f3577c23..b5e84461 100644 --- a/c++/scripts/projects/blast/LICENSE +++ b/c++/scripts/projects/blast/LICENSE @@ -17,3 +17,508 @@ purpose. Please cite the author in any work or product based on this material. + + =========================================================================== + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/c++/scripts/projects/blast/Manifest b/c++/scripts/projects/blast/Manifest index 2b70f660..566bafce 100644 --- a/c++/scripts/projects/blast/Manifest +++ b/c++/scripts/projects/blast/Manifest @@ -1,7 +1,7 @@ # # Filename: Manifest # -# $Id: Manifest 493735 2016-03-01 21:14:46Z camacho $ +# $Id: Manifest 512796 2016-09-02 19:46:40Z camacho $ # # Author: Christiam Camacho # @@ -25,9 +25,10 @@ APP: makeprofiledb blast_formatter COPY: $srcdir/src/app/blast/legacy_blast.pl $installdir/bin COPY: $srcdir/src/app/blast/update_blastdb.pl $installdir/bin -POSTBUILD: $srcdir/scripts/projects/blast/post_build/make_installers.py -v $version $platform $installdir "$tarball" +POSTBUILD: $srcdir/scripts/projects/blast/post_build/make_installers.py -v $version $platform $installdir "$tarball" $bindir -DEFAULT_CONFIGURE_FLAGS: --without-debug --with-strip --with-openmp --with-mt --with-build-root=$srcdir/ReleaseMT +# N.B.: This allows customization of configure script in prepare_release output +DEFAULT_CONFIGURE_FLAGS: --without-debug --with-strip --with-openmp --with-mt --without-vdb --with-build-root=$srcdir/ReleaseMT # Each line describes a single configuration # The format is as follows: @@ -40,17 +41,18 @@ DEFAULT_CONFIGURE_FLAGS: --without-debug --with-strip --with-openmp --with-mt -- # ICC gives us about 10% improvement in the core2 microarchitecture, so prefer # that. The build-root is needed so that rpmbuild can find the proper directories # to copy the binaries from -Linux64-Centos : icc : ICC.sh --with-strip --without-debug --without-pcre --with-mt --with-openmp --with-flat-makefile --with-experimental=Int8GI -#Linux64-Centos : gcc : GCC.sh --with-strip --without-debug --without-pcre --with-mt --with-openmp --with-flat-makefile -#Linux64-Centos : gcc-debug : GCC.sh --with-strip --with-debug --without-pcre --with-mt --with-openmp --with-flat-makefile +Linux64-Centos : icc : ICC.sh --with-bin-release --with-strip --without-debug --without-pcre --with-mt --with-openmp --with-flat-makefile --with-experimental=Int8GI --without-vdb --with-gnutls=/netopt/ncbi_tools64/gnutls-3.4.0 --without-gcrypt +#Linux64-Centos : gcc : GCC.sh --with-bin-release --with-strip --without-debug --without-pcre --with-mt --with-openmp --with-flat-makefile --with-experimental=Int8GI --without-vdb +#Linux64-Centos : gcc-debug : GCC.sh --with-strip --with-debug --without-pcre --with-mt --with-openmp --with-flat-makefile --with-experimental=Int8GI --without-vdb DEFAULT_CONFIGURATIONS: Linux64-Centos:icc +#DEFAULT_CONFIGURATIONS: Linux64-Centos:gcc -Win32 : plain : static 32 ReleaseMT -Win64 : plain : static 64 ReleaseMT +# FIXME: how to specify without VDB? +Win64 : plain : static 64 ReleaseDLL NCBI_CONFIG____ENABLEDUSERREQUESTS__NCBI-INT8-GI=1 -#IntelMAC : universal : GCC.sh --without-debug --without-pcre --with-mt --with-openmp --with-flat-makefile --with-universal=i386,x86_64 --with-ncbi-public -IntelMAC : universal : Clang.sh --without-debug --without-pcre --with-mt --with-openmp --with-flat-makefile --with-universal=i386,x86_64 --with-ncbi-public --with-experimental=Int8GI -#IntelMAC-Clang36 : clang : Clang.sh --without-debug --without-pcre --with-mt --with-openmp --with-flat-makefile --with-ncbi-public +#IntelMAC : gcc : GCC.sh --with-bin-release --without-debug --without-pcre --with-mt --with-openmp --with-flat-makefile --with-ncbi-public --with-experimental=Int8GI --without-vdb --with-gnutls=/netopt/ncbi_tools/gnutls-3.4.0 --without-gcrypt +#IntelMAC : clang : Clang.sh --with-bin-release --without-debug --without-pcre --with-mt --with-openmp --with-flat-makefile --with-ncbi-public --with-experimental=Int8GI --without-vdb --with-gnutls=/netopt/ncbi_tools/gnutls-3.4.0 --without-gcrypt +IntelMAC-Clang36 : clang : Clang.sh 7.0.2 --with-bin-release --without-debug --without-pcre --with-mt --with-openmp --with-flat-makefile --with-ncbi-public --with-experimental=Int8GI --without-vdb --with-gnutls=/netopt/ncbi_tools/gnutls-3.4.0 --without-gcrypt USE_COMPONENTS diff --git a/c++/scripts/projects/blast/components.link b/c++/scripts/projects/blast/components.link index e8df490c..86d2dd20 100644 --- a/c++/scripts/projects/blast/components.link +++ b/c++/scripts/projects/blast/components.link @@ -1,9 +1,9 @@ [components] -infrastructure 17.0 -core 17.0 -dbase 17.0 -web 17.0 -objects 17.0 -objtools 17.0 -algo 17.0 -app 17.0 +infrastructure 18.0 +core 18.0 +dbase 18.0 +web 18.0 +objects 18.0 +objtools 18.0 +algo 18.0 +app 18.0 diff --git a/c++/scripts/projects/blast/post_build/blast_utils.py b/c++/scripts/projects/blast/post_build/blast_utils.py index 08da04a5..2209bef5 100644 --- a/c++/scripts/projects/blast/post_build/blast_utils.py +++ b/c++/scripts/projects/blast/post_build/blast_utils.py @@ -83,16 +83,14 @@ def create_new_tarball_name(platform, program, version): retval = "ncbi-" + program + "-" + version if program == "blast": retval += "+" - if platform.startswith("Win32"): - retval += "-ia32-win32" - elif platform.startswith("Win64"): + if platform.startswith("Win"): retval += "-x64-win64" elif platform.startswith("Linux32"): retval += "-ia32-linux" elif platform.startswith("Linux64"): retval += "-x64-linux" - elif platform == "IntelMAC": - retval += "-universal-macosx" + elif platform.startswith("IntelMAC"): + retval += "-x64-macosx" elif platform == "SunOSSparc": retval += "-sparc64-solaris" elif platform == "SunOSx86": diff --git a/c++/scripts/projects/blast/post_build/macosx/ncbi-blast.sh b/c++/scripts/projects/blast/post_build/macosx/ncbi-blast.sh index 05643ae7..0e3a8322 100755 --- a/c++/scripts/projects/blast/post_build/macosx/ncbi-blast.sh +++ b/c++/scripts/projects/blast/post_build/macosx/ncbi-blast.sh @@ -79,7 +79,10 @@ create_product_archive() create_disk_image() { - /usr/bin/hdiutil create $PRODUCT.dmg -srcfolder $PRODUCT + du -shc $PRODUCT # For diagnostics + # Note: if this command fails, it could be because the -size argument is no + # longer large enough, adjust accordingly + /usr/bin/hdiutil create $PRODUCT.dmg -srcfolder $PRODUCT -verbose -size 150m mkdir $INSTALLDIR/installer mv $PRODUCT.dmg $INSTALLDIR/installer } diff --git a/c++/scripts/projects/blast/post_build/make_installers.py b/c++/scripts/projects/blast/post_build/make_installers.py index d7ce0b60..11573872 100755 --- a/c++/scripts/projects/blast/post_build/make_installers.py +++ b/c++/scripts/projects/blast/post_build/make_installers.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 """Driver program for post-build processing""" -# $Id: make_installers.py 495954 2016-03-22 19:12:50Z camacho $ +# $Id: make_installers.py 512684 2016-09-01 22:19:28Z camacho $ # # Author: Christiam Camacho # @@ -9,6 +9,7 @@ from __future__ import print_function import os, sys, os.path from optparse import OptionParser import blast_utils +import shutil VERBOSE = False SCRIPTS_DIR = os.path.dirname(os.path.abspath(sys.argv[0])) @@ -20,11 +21,11 @@ def main(): #IGNORE:R0911 parser.add_option("-v", "--verbose", action="store_true", default=False, help="Show verbose output", dest="VERBOSE") options, args = parser.parse_args() - if len(args) != 4: + if len(args) != 5: parser.error("Incorrect number of arguments") return 1 - blast_version, platform, installdir, srctarball = args + blast_version, platform, installdir, srctarball, libdir = args global VERBOSE #IGNORE:W0603 VERBOSE = options.VERBOSE @@ -33,15 +34,32 @@ def main(): #IGNORE:R0911 print("Platform:", platform) print("Installation directory:", installdir) print("Source tarball:", srctarball) + print("Lib directory:", libdir) if platform.startswith("Win"): + import glob + print("Files in libdir " + libdir + ":") + for dll in glob.glob(libdir + "/*"): + print(dll) + print("Files in install dir " + installdir + ":") + for dll in glob.glob(installdir + "/*"): + print(dll) + + + if platform.startswith("Win"): + shutil.copy(libdir + "libgcc_s_seh-1.dll", installdir + "bin") + shutil.copy(libdir + "libgmp-10.dll", installdir + "bin") + shutil.copy(libdir + "libgnutls-30.dll", installdir + "bin") + shutil.copy(libdir + "libhogweed-4-2.dll", installdir + "bin") + shutil.copy(libdir + "libnettle-6-2.dll", installdir + "bin") + shutil.copy(libdir + "libp11-kit-0.dll", installdir + "bin") return launch_win_installer_build(installdir, blast_version) if platform.startswith("Linux64"): return launch_rpm_build(installdir, blast_version, srctarball) if platform == "FreeBSD32" or platform.startswith("SunOS") or \ platform.startswith("Linux32"): return do_nothing(platform) - if platform == "IntelMAC": + if platform.startswith("IntelMAC"): return mac_post_build(installdir, blast_version) print("Unknown OS identifier:" + platform, file=sys.stderr) diff --git a/c++/scripts/projects/blast/post_build/win/make_win.py b/c++/scripts/projects/blast/post_build/win/make_win.py index 648b3ef1..0d4b51b7 100644 --- a/c++/scripts/projects/blast/post_build/win/make_win.py +++ b/c++/scripts/projects/blast/post_build/win/make_win.py @@ -1,6 +1,6 @@ #! /usr/bin/env python3 """Script to create the Windows installer for BLAST command line applications""" -# $Id: make_win.py 495892 2016-03-22 15:02:26Z camacho $ +# $Id: make_win.py 511374 2016-08-22 13:18:52Z camacho $ # # Author: Christiam camacho @@ -62,7 +62,14 @@ def main(): "blast_formatter.exe", "deltablast.exe", "legacy_blast.pl", - "update_blastdb.pl" ] + "update_blastdb.pl", + "libgcc_s_seh-1.dll", + "libgmp-10.dll", + "libgnutls-30.dll", + "libhogweed-4-2.dll", + "libnettle-6-2.dll", + "libp11-kit-0.dll" + ] cwd = os.getcwd() for app in apps: diff --git a/c++/scripts/projects/blast/post_build/win/ncbi-blast.nsi b/c++/scripts/projects/blast/post_build/win/ncbi-blast.nsi index 71590ba6..593b76fa 100755 --- a/c++/scripts/projects/blast/post_build/win/ncbi-blast.nsi +++ b/c++/scripts/projects/blast/post_build/win/ncbi-blast.nsi @@ -81,6 +81,12 @@ Section "DefaultSection" SecDflt File "blastdbcheck.exe" File "blast_formatter.exe" File "deltablast.exe" + File "libgcc_s_seh-1.dll" + File "libgmp-10.dll" + File "libgnutls-30.dll" + File "libhogweed-4-2.dll" + File "libnettle-6-2.dll" + File "libp11-kit-0.dll" SetOutPath "$INSTDIR\doc" File "README.txt" @@ -124,6 +130,12 @@ Section "Uninstall" Delete "$INSTDIR\bin\blastdbcheck.exe" Delete "$INSTDIR\bin\blast_formatter.exe" Delete "$INSTDIR\bin\deltablast.exe" + Delete "$INSTDIR\bin\libgcc_s_seh-1.dll" + Delete "$INSTDIR\bin\libgmp-10.dll" + Delete "$INSTDIR\bin\libgnutls-30.dll" + Delete "$INSTDIR\bin\libhogweed-4-2.dll" + Delete "$INSTDIR\bin\libnettle-6-2.dll" + Delete "$INSTDIR\bin\libp11-kit-0.dll" Delete "$INSTDIR\doc\README.txt" RmDir "$INSTDIR\bin" RmDir "$INSTDIR\doc" diff --git a/c++/scripts/projects/blast/project.lst b/c++/scripts/projects/blast/project.lst index f24331e0..3c970875 100644 --- a/c++/scripts/projects/blast/project.lst +++ b/c++/scripts/projects/blast/project.lst @@ -78,3 +78,6 @@ objtools/simple$ -objects/.*/test -objects/.*/demo -objects/.*/unit_test +misc$ +misc/third_party +misc/third_party_static diff --git a/c++/scripts/projects/cobalt/Manifest b/c++/scripts/projects/cobalt/Manifest index fe16c002..ca069404 100644 --- a/c++/scripts/projects/cobalt/Manifest +++ b/c++/scripts/projects/cobalt/Manifest @@ -36,7 +36,7 @@ DEFAULT_CONFIGURATIONS: Linux32-Centos:icc Linux64-Centos:icc Win32_13 : plain : static 32 ReleaseMT Win64_13 : plain : static 64 ReleaseMT -IntelMAC : universal : GCC.sh --without-debug --without-pcre --with-mt --with-flat-makefile --with-universal=i386,x86_64 --with-ncbi-public +IntelMAC : gcc : GCC.sh --without-debug --without-pcre --with-mt --with-flat-makefile --with-ncbi-public USE_COMPONENTS diff --git a/c++/scripts/projects/datatool/ChangeLog b/c++/scripts/projects/datatool/ChangeLog index d85ed646..71b909f1 100644 --- a/c++/scripts/projects/datatool/ChangeLog +++ b/c++/scripts/projects/datatool/ChangeLog @@ -152,6 +152,8 @@ Added mapping of certain data types to strings. Fixed delayed buffer in choice variants. Changed to print schema comments using documentation tag. - +July 21, 2016 +Version 2.16.0, CXX-8385 +Added option to distinguish BigInt and Int8 in ASN binary serialization. diff --git a/c++/scripts/projects/datatool/Manifest b/c++/scripts/projects/datatool/Manifest index 4172f6f1..72799a77 100644 --- a/c++/scripts/projects/datatool/Manifest +++ b/c++/scripts/projects/datatool/Manifest @@ -1,7 +1,7 @@ # # Filename: Manifest # -# $Id: Manifest 486339 2015-12-03 15:52:01Z fukanchi $ +# $Id: Manifest 508788 2016-08-01 16:12:18Z fukanchi $ # # Author: Sergey Satskiy # @@ -36,7 +36,7 @@ IntelMAC : plain : GCC.sh --without-debug --without-mt --with-stati Win32_13 : plain : static 32 ReleaseMT -XCode : plain : Xcode.sh 30 --without-debug --with-universal=i386,x86_64 +XCode : plain : Xcode.sh 30 --without-debug USE_COMPONENTS diff --git a/c++/scripts/projects/dispatcher/Manifest b/c++/scripts/projects/dispatcher/Manifest index e7e503e0..d48558f6 100644 --- a/c++/scripts/projects/dispatcher/Manifest +++ b/c++/scripts/projects/dispatcher/Manifest @@ -1,7 +1,7 @@ # # Filename: Manifest # -# $Id: Manifest 486339 2015-12-03 15:52:01Z fukanchi $ +# $Id: Manifest 508788 2016-08-01 16:12:18Z fukanchi $ # # Author: Sergey Satskiy # @@ -36,5 +36,5 @@ POSTBUILD: [ "$platform" != "Cygwin64" ] || { cp -vp /usr/{bin/cygcheck.exe,bin/ Linux64-Centos : ICC : ICC.sh --with-local-lbsm --without-debug --without-mt --with-static --without-serial --without-runpath --with-flat-makefile Linux64-Centos : GCC : GCC.sh --with-local-lbsm --without-debug --without-mt --with-static --without-serial --without-runpath --with-flat-makefile FreeBSD64 : Clang : Clang.sh --with-local-lbsm --without-debug --without-mt --with-static --without-serial --without-runpath --with-flat-makefile -IntelMAC : GCC : GCC.sh --with-local-lbsm --without-debug --without-mt --with-static --without-serial --without-runpath --with-flat-makefile --with-universal=i386,x86_64 +IntelMAC : GCC : GCC.sh --with-local-lbsm --without-debug --without-mt --with-static --without-serial --without-runpath --with-flat-makefile # Cygwin64 : GCC : GCC.sh --with-local-lbsm --without-debug --without-mt --with-static --without-serial --without-runpath --without-flat-makefile diff --git a/c++/scripts/projects/gumbel_params/Manifest b/c++/scripts/projects/gumbel_params/Manifest index 24285968..49e0a0b4 100644 --- a/c++/scripts/projects/gumbel_params/Manifest +++ b/c++/scripts/projects/gumbel_params/Manifest @@ -39,6 +39,6 @@ Win64_13 : plain : static 64 ReleaseMT SunOSx86 : plain : WorkShop59.sh 64 --without-debug --without-pcre --with-mt --with-flat-makefile -IntelMAC : universal : GCC.sh --without-debug --without-pcre --with-mt --with-flat-makefile --with-universal=i386,x86_64 --with-ncbi-public +IntelMAC : gcc : GCC.sh --without-debug --without-pcre --with-mt --with-flat-makefile --with-ncbi-public # USE_COMPONENTS diff --git a/c++/scripts/projects/igblast/ChangeLog b/c++/scripts/projects/igblast/ChangeLog index 7937b965..b382e946 100644 --- a/c++/scripts/projects/igblast/ChangeLog +++ b/c++/scripts/projects/igblast/ChangeLog @@ -1,3 +1,13 @@ +Oct 26, 2016 +* Release 1.6.1 +* Added clonotype report + +April 25, 2016 +* Release 1.5.0 +* Added CDR3 annotation +* Added option for extending at 5' side +* Default to IMGT region (was Kabat previously) + July 17, 2014 * Release 1.4.0 * Added capability to analyze monkey sequences. diff --git a/c++/scripts/projects/igblast/LICENSE b/c++/scripts/projects/igblast/LICENSE index f3577c23..b5e84461 100644 --- a/c++/scripts/projects/igblast/LICENSE +++ b/c++/scripts/projects/igblast/LICENSE @@ -17,3 +17,508 @@ purpose. Please cite the author in any work or product based on this material. + + =========================================================================== + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/c++/scripts/projects/igblast/Manifest b/c++/scripts/projects/igblast/Manifest index e38fa0cd..68ba2775 100644 --- a/c++/scripts/projects/igblast/Manifest +++ b/c++/scripts/projects/igblast/Manifest @@ -1,7 +1,7 @@ # # Filename: Manifest # -# $Id: Manifest 497677 2016-04-08 19:08:30Z camacho $ +# $Id: Manifest 517012 2016-10-19 21:23:41Z camacho $ # # Author: Christiam Camacho # @@ -16,9 +16,9 @@ # It is allowed to have more than one of each statements APP: igblastp igblastn makeblastdb -POSTBUILD: $srcdir/scripts/projects/igblast/post_build/make_installers.py -v $version $platform $installdir +POSTBUILD: $srcdir/scripts/projects/igblast/post_build/make_installers.py -v $version $platform $installdir "$tarball" $bindir -DEFAULT_CONFIGURE_FLAGS: --without-debug --with-strip --with-mt --with-build-root=$srcdir/ReleaseMT +DEFAULT_CONFIGURE_FLAGS: --without-debug --with-strip --with-openmp --with-mt --without-vdb --with-build-root=$srcdir/ReleaseMT # Each line describes a single configuration # The format is as follows: @@ -31,15 +31,16 @@ DEFAULT_CONFIGURE_FLAGS: --without-debug --with-strip --with-mt --with-build-roo # ICC gives us about 10% improvement in the core2 microarchitecture, so prefer # that. The build-root is needed so that rpmbuild can find the proper directories # to copy the binaries from -Linux64-Centos : icc : ICC.sh --with-strip --without-debug --without-pcre --with-mt --with-openmp --with-flat-makefile +Linux64-Centos : icc : ICC.sh --with-bin-release --with-strip --without-debug --without-pcre --with-mt --with-openmp --with-flat-makefile --with-experimental=Int8GI --without-vdb --with-gnutls=/netopt/ncbi_tools64/gnutls-3.4.0 --without-gcrypt #Linux64-Centos : gcc-debug : GCC.sh --with-strip --with-debug --without-pcre --with-mt --with-flat-makefile DEFAULT_CONFIGURATIONS: Linux64-Centos:icc -Win32 : plain : static 32 ReleaseMT -Win64 : plain : static 64 ReleaseMT +#Win32 : plain : static 32 ReleaseMT +#Win64 : plain : static 64 ReleaseMT +Win64 : plain : static 64 ReleaseDLL NCBI_CONFIG____ENABLEDUSERREQUESTS__NCBI-INT8-GI=1 -IntelMAC : universal : Clang.sh --without-debug --without-pcre --with-mt --with-openmp --with-flat-makefile --with-universal=i386,x86_64 --with-ncbi-public +IntelMAC : clang : Clang.sh --with-bin-release --without-debug --without-pcre --with-mt --with-openmp --with-flat-makefile --with-ncbi-public --with-experimental=Int8GI --without-vdb --with-gnutls=/netopt/ncbi_tools/gnutls-3.4.0 --without-gcrypt +IntelMAC-Clang36 : clang : Clang.sh 7.0.2 --with-bin-release --without-debug --without-pcre --with-mt --with-openmp --with-flat-makefile --with-ncbi-public --with-experimental=Int8GI --without-vdb --with-gnutls=/netopt/ncbi_tools/gnutls-3.4.0 --without-gcrypt USE_COMPONENTS - diff --git a/c++/scripts/projects/igblast/README b/c++/scripts/projects/igblast/README index c23b8731..e3c476a9 100644 --- a/c++/scripts/projects/igblast/README +++ b/c++/scripts/projects/igblast/README @@ -31,15 +31,16 @@ program is) or a path pointed to by IGDATA environmental variable. Note that th any germline gene databases you should search (see above for how you can obtain a germline gene database). 2. Optional files (download from the release/ directory): -This is the file to indicate germline J gene coding frame start position (position is 0-based) for each -sequence in your germline J sequence database. Note that the supplied file contains only information -for NCBI or IMGT germline database. If you search your own database and if it contains different +This is the file to indicate germline J gene coding frame start position (position is 0-based), the J gene type, +and the CDR3 end position for each sequence in the germline J sequence database (Fields are tab-delimited). + +Note that the supplied file contains only information for NCBI or IMGT germline gene sequence database +(including gene names as well as the sequences). If you search your own database and if it contains different sequences or sequence identifiers, then you need to edit that file (or supply your own file) to reflect that -or you won't get proper frame status information for a rearrangement (other results will still be shown). -The entry format has tab-delimited fields for sequence id and coding frame start position. See -human_gl.aux or mouse_gl.aux for examples. Enter -1 if the frame information is unknown (or simply -don't include that sequence entry at all). You need to use -auxiliary_data option to specify your file. You -can directly supply a path to this file or put it under a path pointed to by IGDATA environmental variable. +or you won't get proper frame status or CDR3 information (other results will still be shown correctly). +See human_gl.aux or mouse_gl.aux for examples. Enter -1 if the frame information is unknown. +You need to use -auxiliary_data option to specify your file. You can directly supply a path to this file or +put it under a path pointed to by IGDATA environmental variable. 3. Some examples. 1). Searching germline gene database diff --git a/c++/scripts/projects/igblast/components.link b/c++/scripts/projects/igblast/components.link index e8df490c..86d2dd20 100644 --- a/c++/scripts/projects/igblast/components.link +++ b/c++/scripts/projects/igblast/components.link @@ -1,9 +1,9 @@ [components] -infrastructure 17.0 -core 17.0 -dbase 17.0 -web 17.0 -objects 17.0 -objtools 17.0 -algo 17.0 -app 17.0 +infrastructure 18.0 +core 18.0 +dbase 18.0 +web 18.0 +objects 18.0 +objtools 18.0 +algo 18.0 +app 18.0 diff --git a/c++/scripts/projects/igblast/post_build/blast_utils.py b/c++/scripts/projects/igblast/post_build/blast_utils.py index cfa22b0e..ef9940df 100644 --- a/c++/scripts/projects/igblast/post_build/blast_utils.py +++ b/c++/scripts/projects/igblast/post_build/blast_utils.py @@ -72,7 +72,7 @@ def update_blast_version(config_file, ver): os.remove(fname) -def create_new_tarball_name(platform, version): +def create_new_tarball_name(platform, program, version): """ Converts the name of a platform as specified to the prepare_release framework to an archive name according to BLAST release naming conventions. @@ -80,17 +80,17 @@ def create_new_tarball_name(platform, version): more information can be found in http://mini.ncbi.nih.gov/3oo """ - retval = "ncbi-blast-" + version + "+" - if platform.startswith("Win32"): - retval += "-ia32-win32" - elif platform.startswith("Win64"): + retval = "ncbi-" + program + "-" + version + if program == "blast": + retval += "+" + if platform.startswith("Win"): retval += "-x64-win64" elif platform.startswith("Linux32"): retval += "-ia32-linux" elif platform.startswith("Linux64"): retval += "-x64-linux" - elif platform == "IntelMAC": - retval += "-universal-macosx" + elif platform.startswith("IntelMAC"): + retval += "-x64-macosx" elif platform == "SunOSSparc": retval += "-sparc64-solaris" elif platform == "SunOSx86": @@ -99,6 +99,7 @@ def create_new_tarball_name(platform, version): raise RuntimeError("Unknown platform: " + platform) return retval + def determine_platform(): """ Determines the platform (as defined in prepare_release) for the current hostname diff --git a/c++/scripts/projects/igblast/post_build/make_installers.py b/c++/scripts/projects/igblast/post_build/make_installers.py index da4e560a..4ac612f5 100755 --- a/c++/scripts/projects/igblast/post_build/make_installers.py +++ b/c++/scripts/projects/igblast/post_build/make_installers.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 """Driver program for post-build processing""" -# $Id: make_installers.py 496124 2016-03-23 20:34:27Z camacho $ +# $Id: make_installers.py 517012 2016-10-19 21:23:41Z camacho $ # # Author: Christiam Camacho # @@ -9,21 +9,23 @@ from __future__ import print_function import os, sys, os.path from optparse import OptionParser import blast_utils +import shutil VERBOSE = False SCRIPTS_DIR = os.path.dirname(os.path.abspath(sys.argv[0])) def main(): #IGNORE:R0911 """ Creates installers for selected platforms. """ - parser = OptionParser("%prog ") + parser = OptionParser("%prog \ + \"\"") parser.add_option("-v", "--verbose", action="store_true", default=False, help="Show verbose output", dest="VERBOSE") options, args = parser.parse_args() - if len(args) != 3: + if len(args) != 5: parser.error("Incorrect number of arguments") return 1 - blast_version, platform, installdir = args + blast_version, platform, installdir, srctarball, libdir = args global VERBOSE #IGNORE:W0603 VERBOSE = options.VERBOSE @@ -31,17 +33,36 @@ def main(): #IGNORE:R0911 print("BLAST version", blast_version) print("Platform:", platform) print("Installation directory:", installdir) + print("Source tarball:", srctarball) + print("Lib directory:", libdir) if platform.startswith("Win"): + import glob + print("Files in libdir " + libdir + ":") + for dll in glob.glob(libdir + "/*"): + print(dll) + print("Files in install dir " + installdir + ":") + for dll in glob.glob(installdir + "/*"): + print(dll) + + + if platform.startswith("Win"): + shutil.copy(libdir + "libgcc_s_seh-1.dll", installdir + "bin") + shutil.copy(libdir + "libgmp-10.dll", installdir + "bin") + shutil.copy(libdir + "libgnutls-30.dll", installdir + "bin") + shutil.copy(libdir + "libhogweed-4-2.dll", installdir + "bin") + shutil.copy(libdir + "libnettle-6-2.dll", installdir + "bin") + shutil.copy(libdir + "libp11-kit-0.dll", installdir + "bin") return launch_win_installer_build(installdir, blast_version) - if platform.startswith("Linux"): + if platform.startswith("Linux64"): return launch_rpm_build(installdir, blast_version) - if platform == "FreeBSD32" or platform.startswith("SunOS"): + if platform == "FreeBSD32" or platform.startswith("SunOS") or \ + platform.startswith("Linux32"): return do_nothing(platform) - if platform == "IntelMAC": + if platform.startswith("IntelMAC"): return mac_post_build(installdir, blast_version) - print("Unknown OS identifier:", platform, file=sys.stderr) + print("Unknown OS identifier:" + platform, file=sys.stderr) print("Exiting post build script.", file=sys.stderr) return 2 diff --git a/c++/scripts/projects/igblast/post_build/win/make_win.py b/c++/scripts/projects/igblast/post_build/win/make_win.py index e7fb633f..b6d882f7 100644 --- a/c++/scripts/projects/igblast/post_build/win/make_win.py +++ b/c++/scripts/projects/igblast/post_build/win/make_win.py @@ -1,6 +1,6 @@ #! /usr/bin/env python3 """Script to create the Windows installer for BLAST command line applications""" -# $Id: make_win.py 495893 2016-03-22 15:02:30Z camacho $ +# $Id: make_win.py 516804 2016-10-18 15:15:47Z camacho $ # # Author: Christiam camacho @@ -41,7 +41,14 @@ def main(): blast_version, installdir = args VERBOSE = options.VERBOSE - apps = [ "igblastn.exe", "igblastp.exe" ] + apps = [ "igblastn.exe", "igblastp.exe", + "libgcc_s_seh-1.dll", + "libgmp-10.dll", + "libgnutls-30.dll", + "libhogweed-4-2.dll", + "libnettle-6-2.dll", + "libp11-kit-0.dll" + ] cwd = os.getcwd() for app in apps: diff --git a/c++/scripts/projects/igblast/post_build/win/ncbi-blast.nsi b/c++/scripts/projects/igblast/post_build/win/ncbi-blast.nsi index f1adc07c..4e6b7160 100755 --- a/c++/scripts/projects/igblast/post_build/win/ncbi-blast.nsi +++ b/c++/scripts/projects/igblast/post_build/win/ncbi-blast.nsi @@ -62,6 +62,12 @@ Section "DefaultSection" SecDflt File "igblastn.exe" File "igblastp.exe" + File "libgcc_s_seh-1.dll" + File "libgmp-10.dll" + File "libgnutls-30.dll" + File "libhogweed-4-2.dll" + File "libnettle-6-2.dll" + File "libp11-kit-0.dll" SetOutPath "$INSTDIR\doc" File "README" diff --git a/c++/scripts/projects/igblast/project.lst b/c++/scripts/projects/igblast/project.lst index 784632ec..a206abea 100644 --- a/c++/scripts/projects/igblast/project.lst +++ b/c++/scripts/projects/igblast/project.lst @@ -82,3 +82,6 @@ objtools/simple$ -objects/.*/test -objects/.*/demo -objects/.*/unit_test +misc$ +misc/third_party +misc/third_party_static diff --git a/c++/scripts/projects/magicblast/ChangeLog b/c++/scripts/projects/magicblast/ChangeLog new file mode 100644 index 00000000..f1af1882 --- /dev/null +++ b/c++/scripts/projects/magicblast/ChangeLog @@ -0,0 +1,11 @@ +August 19, 2016 +* First release + +November 4, 2016 +* 1.1.0 release +Improvements: +* -sra option connects to NCBI via HTTPS +* Results are formatted with 'bare' accessions +* Tabular output includes a header with column titles +Bug fixes: +* Fixed SAM flag values diff --git a/c++/scripts/projects/magicblast/LICENSE b/c++/scripts/projects/magicblast/LICENSE new file mode 100644 index 00000000..b5e84461 --- /dev/null +++ b/c++/scripts/projects/magicblast/LICENSE @@ -0,0 +1,524 @@ + PUBLIC DOMAIN NOTICE + National Center for Biotechnology Information + + This software/database is a "United States Government Work" under the + terms of the United States Copyright Act. It was written as part of + the author's official duties as a United States Government employee and + thus cannot be copyrighted. This software/database is freely available + to the public for use. The National Library of Medicine and the U.S. + Government have not placed any restriction on its use or reproduction. + + Although all reasonable efforts have been taken to ensure the accuracy + and reliability of the software and data, the NLM and the U.S. + Government do not and cannot warrant the performance or results that + may be obtained by using this software or data. The NLM and the U.S. + Government disclaim all warranties, express or implied, including + warranties of performance, merchantability or fitness for any particular + purpose. + + Please cite the author in any work or product based on this material. + + =========================================================================== + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/c++/scripts/projects/magicblast/Manifest b/c++/scripts/projects/magicblast/Manifest new file mode 100644 index 00000000..73a93d8f --- /dev/null +++ b/c++/scripts/projects/magicblast/Manifest @@ -0,0 +1,50 @@ +# +# Filename: Manifest +# +# $Id $ +# +# Author: Christiam Camacho, Greg Boratyn +# +# Purpose: This file holds all the supported configurations of a package +# It is used by release configurator. +# + +# The APP: statement describes binaries +# The LIB: statement describes libraries +# The DLL: statement describes shared objects +# The ETC: statement describes configuration files +# It is allowed to have more than one of each statements +# NOTE: When applications are added/removed from this list, please update +# the application listings in post_build/win/{make_win.py,ncbi-blast.nsi}, +# post_build/macosx/ncbi-blast.sh, and post_build/rpm/ncbi-blast.spec +APP: magicblast makeblastdb + +POSTBUILD: $srcdir/scripts/projects/magicblast/post_build/make_installers.py -v $version $platform $installdir "$tarball" $bindir + +DEFAULT_CONFIGURE_FLAGS: --without-debug --with-strip --with-openmp --with-mt --with-build-root=$srcdir/ReleaseMT --with-downloaded-vdb --with-static-vdb + +# Each line describes a single configuration +# The format is as follows: +# : : +# Configuration script is relative to c++/compilers/unix/ . +# Release configurator assumes that this script will eventually call standard configure script and pass all options +# to it. So some standard options may be added by release configurator, such as --build-root-sfx, --with-projects, +# --with-distcc, --with-action etc. + +# ICC gives us about 10% improvement in the core2 microarchitecture, so prefer +# that. The build-root is needed so that rpmbuild can find the proper directories +# to copy the binaries from +Linux64-Centos : icc : ICC.sh --with-bin-release --with-strip --without-debug --without-pcre --with-mt --with-openmp --with-flat-makefile --with-experimental=Int8GI --with-downloaded-vdb --with-static-vdb --with-gnutls=/netopt/ncbi_tools64/gnutls-3.4.0 --without-gcrypt +#Linux64-Centos : gcc : GCC.sh --with-bin-release --with-strip --without-debug --without-pcre --with-mt --with-openmp --with-flat-makefile --with-experimental=Int8GI --with-downloaded-vdb --with-static-vdb +#Linux64-Centos : gcc-debug : GCC.sh --with-strip --with-debug --without-pcre --with-mt --with-openmp --with-flat-makefile --with-downloaded-vdb + +DEFAULT_CONFIGURATIONS: Linux64-Centos:icc +#DEFAULT_CONFIGURATIONS: Linux64-Centos:gcc + +Win64 : plain : static 64 ReleaseDLL NCBI_CONFIG____ENABLEDUSERREQUESTS__NCBI-INT8-GI=1 + +#IntelMAC : gcc : GCC.sh --with-bin-release --without-debug --without-pcre --with-mt --with-openmp --with-flat-makefile --with-ncbi-public --with-downloaded-vdb --with-static-vdb +IntelMAC : clang : Clang.sh --with-bin-release --without-debug --without-pcre --with-mt --with-openmp --with-flat-makefile --with-ncbi-public --with-experimental=Int8GI --with-downloaded-vdb --with-static-vdb --with-gnutls=/netopt/ncbi_tools/gnutls-3.4.0 --without-gcrypt +IntelMAC-Clang36 : clang : Clang.sh 7.0.2 --with-bin-release --without-debug --without-pcre --with-mt --with-openmp --with-flat-makefile --with-ncbi-public --with-experimental=Int8GI --with-downloaded-vdb --with-static-vdb --with-gnutls=/netopt/ncbi_tools/gnutls-3.4.0 --without-gcrypt + +USE_COMPONENTS diff --git a/c++/scripts/projects/magicblast/README b/c++/scripts/projects/magicblast/README new file mode 100644 index 00000000..f2e4b061 --- /dev/null +++ b/c++/scripts/projects/magicblast/README @@ -0,0 +1,170 @@ +Magic-BLAST is a tool for mapping large next-generation RNA or DNA sequencing +runs against a whole genome or transcriptome. Each alignment optimizes +a composite score, taking into account simultaneously the two reads of +a pair, and in case of RNA-seq, locating the candidate introns and adding +up the score of all exons. This is very different from other versions of +BLAST, where each exon is scored as a separate hit and read-pairing is +ignored. + +Magic-Blast incorporates within the NCBI BLAST code framework ideas +developed in the NCBI Magic pipeline, in particular hit extensions by +local walk and jump, which is faster than Smith-Waterman extension +(http://www.ncbi.nlm.nih.gov/pubmed/26109056), and recursive clipping of +mismatches near the edges of the reads, which avoids accumulating +artefactual mismatches near splice sites and is needed to distinguish +short indels from substitutions near the edges. + +We call the whole next generation run (from Illumina, Roche-454, ABI, or +another sequencing platform excluding SOLiD), a query. The input reads may +be provided as SRA accession or file in a SRA, FASTA, FASTQ, or FASTC format. +Read pairs can be presented as parallel files, or as successive reads in a +single file. + +The reference genome or transcriptome can be given as a BLAST database +or a FASTA file. It is preferable to use BLAST database for large genomes, +such as human, or transcript collections, such as all of RefSeq, Ensembl, +or AceView. The procedure for creating a BLAST database is described below. + +The full list of options is listed when you use -help option. + +=================== + +EXAMPLES: +Use this command line to map RNA-seq reads in FASTA format to a reference +genome in FASTA format: +magicblast -query reads.fa -subject genome.fa + +Use this command line to map RNA-seq reads to a reference genome provided +as a BLAST database: +magicblast -query reads.fa -db genome + +Use this command line to map RNA-seq reads in FASTQ format: +magicblast -query reads.fastq -db genome -infmt fastq + +The reads can also be provided from the standard input: +cat reads.fa | magicblast -query - -db genome +cat reads.fa | magicblast -db genome + +Magic-Blast recognizes read and reference file names with extension ".gz" +as compressed and decompresses them automatically using gzip. + +Use this command line to map SRA run to a genome: +magicblast -sra sra_accession -db genome + + + +PAIRED-READS: + +For paired reads presented as successive entries in a single FASTA or FASTQ +file, i.e. read 1 and 2 of fragment 1, then read 1 and 2 of fragment 2, +etc., simply add the parameter '-paired': +magicblast -query reads.fa -db genome -paired + +If you are using fastq-dump +(http://www.ncbi.nlm.nih.gov/Traces/sra/sra.cgi?view=toolkit_doc&f=fastq-dump) +to download NCBI SRA data or convert SRA file to the FASTQ format, use these +parameters for runs with paired reads to create a single merged input file +for Magic-Blast: +fastq-dump -I --split-spot + +For paired reads presented in two parallel files, use these options: +magicblast -query reads.fa -query_mate mates.fa -db genome + + +RNA versus DNA: + +By default, Magic-Blast aligns RNA reads to a genome and reports spliced +alignments, possibly spanning several exons. To disable spliced alignments, +use the '-splice F' option. Use the '-reftype transcriptome' option, to +map reads to a transcriptome database. These are example command lines: +magicblast -query reads.fa -db genome -splice F +magicblast -query reads.fa -db genome -reftype transcriptome + +Magic-Blast finds alignments between a read and a genome based on initial +common word in both. To make mapping faster we first count word occurrences +in the genome and disregard those that occur too often. With the +'-reftype transcripts' option the words that are frequent in the transcript +database are used for alignment. + + +MULTI-THREADING + +To use multiple CPUs, specify the maximal number of threads with the +'-num_threads' parameter: +magicblast -query reads.fa -db genome -num_threads 10 + + +OUTPUT: + +By default, results are provided to the standard output in the SAM format. +Use '-out filename' option to redirect output to a file. +Use '-outfmt' option to specify the output format: +-outfmt SAM : SAM format (default) +-outfmt tabular : exports a simple tab delimited format defined below. + +The output can be also compressed, using the '-gzo' flag: +magicblast -query reads.fa -db genome -out output.gz -gzo + + +CREATION OF A BLAST DATABASE: + +Use this command line to create a BLAST database: +makeblastdb -in fasta_file -dbtype nucl -parse_seqids -out database_name +-title "Database title" + +The -parse_seqids option is required to keep the original sequence +identifiers. Otherwise makeblastdb will generate its own identifiers. + + +TABULAR OUTPUT FORMAT + +The tabular output format shows one alignment per line with these tab +delimited fields: +1. Query/read sequence identifier +2. Reference sequence identifier +3. Percent identity of the alignment +4. Not used +5. Not used +6. Not used +7. Alignment start position on the query sequence +8. Alignment stop position on the query sequence +9. Alignment start position on the reference sequence +10. Alignment stop position on the reference sequence +11. Not used +12. Not used +13. Alignment score +14. Query strand +15. Reference sequence strand +16. Query/read length +17. Alignment as extended BTOP string + This is the same BTOP string as in BLAST tabular output with a + few extensions: + - a number represents this many matches, + - two bases represent a mismatch and show query and reference base, + - base and gap or gap and base, show a gap in query or reference, + - ^^ represents an intron of this number of bases, + - __ represents a gap in query of this number of bases, + - () shows number of query bases that are shared between + two parts of a spliced alignment; used when proper splice sites + were not found +18. Number of different alignments reported for this query sequence +19. Information about detected splice sites, polyA tails, or adapter + sequences found at the edges of the alignment +20. Compartment - a unique identifier for all alignments that belong to + a single fragment. These can be two alignments for a pair of reads + or alignments to exons that were not spliced. +21. Reverse complemented unaligned query sequence from the beginning + of the query, or '-' if the query aligns to the left edge +22. Unaligned sequence at the end of the query, or '-' +23. Reference sequence identifier where the mate is aligned, if + different from the identifier in column 2, otherwise '-' +24. Alignment start position on the reference sequence for the mate, or + '-' if no alignment for the mate was found; a negative number + denotes a divergent pair +25. Composite alignment score for all exons that belong to the fragment + +Thank you for testing this code and providing us with feedback. Please, +let us know of any desired option, problem or difficulty. + +E-mail boratyng@ncbi.nlm.nih.gov or blast-help@ncbi.nlm.nih.gov with +questions or comments. diff --git a/c++/scripts/projects/magicblast/components.link b/c++/scripts/projects/magicblast/components.link new file mode 100644 index 00000000..86d2dd20 --- /dev/null +++ b/c++/scripts/projects/magicblast/components.link @@ -0,0 +1,9 @@ +[components] +infrastructure 18.0 +core 18.0 +dbase 18.0 +web 18.0 +objects 18.0 +objtools 18.0 +algo 18.0 +app 18.0 diff --git a/c++/scripts/projects/magicblast/post_build/blast_utils.py b/c++/scripts/projects/magicblast/post_build/blast_utils.py new file mode 100644 index 00000000..2209bef5 --- /dev/null +++ b/c++/scripts/projects/magicblast/post_build/blast_utils.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python3 +""" Various utilities/tools for BLAST """ +from __future__ import print_function + +__all__ = ["safe_exec", "update_blast_version"] + +import os +import subprocess +import platform +import unittest +import tempfile +import re + + +def safe_exec(cmd): + """ Executes a command and checks its return value, throwing an + exception if it fails. + """ + try: + msg = "Command: '" + cmd + "' " + retcode = subprocess.call(cmd, shell=True) + if retcode < 0: + msg += "Termined by signal " + str(-retcode) + raise RuntimeError(msg) + elif retcode != 0: + msg += "Failed with exit code " + str(retcode) + raise RuntimeError(msg) + except OSError as err: + msg += "Execution failed: " + err + raise RuntimeError(msg) + + +class Tester(unittest.TestCase): + '''Testing class for this script.''' + def test_one(self): + ver = "2.3.0" + line1 = "Hello BLAST" + with tempfile.NamedTemporaryFile(mode='w+t') as fp: + print(line1, file=fp) + print("BLAST_VERSION", file=fp) + print(line1, file=fp, flush=True) + + update_blast_version(fp.name, ver) + + fp.seek(0) + line = fp.readline().rstrip() + self.assertEqual(line1, line) + line = fp.readline().rstrip() + self.assertEqual(ver, line) + line = fp.readline().rstrip() + self.assertEqual(line1, line) + + +def update_blast_version(config_file, ver): + """Updates the BLAST version in the specified file. + + Assumes the specified file contains the string BLAST_VERSION, which will + be replaced by the contents of the variable passed to this function. + """ + (fd, fname) = tempfile.mkstemp() + try: + with open(config_file, "r") as infile, open(fname, "w") as out: + for line in infile: + newline = re.sub("BLAST_VERSION", ver, line.rstrip()) + print(newline, file=out) + + with open(config_file, "w") as out, open(fname, "r") as infile: + for line in infile: + print(line.rstrip(), file=out) + finally: + os.close(fd) + os.remove(fname) + + +def create_new_tarball_name(platform, program, version): + """ Converts the name of a platform as specified to the prepare_release + framework to an archive name according to BLAST release naming conventions. + + Note: the platform names come from the prepare_release script conventions, + more information can be found in http://mini.ncbi.nih.gov/3oo + """ + + retval = "ncbi-" + program + "-" + version + if program == "blast": + retval += "+" + if platform.startswith("Win"): + retval += "-x64-win64" + elif platform.startswith("Linux32"): + retval += "-ia32-linux" + elif platform.startswith("Linux64"): + retval += "-x64-linux" + elif platform.startswith("IntelMAC"): + retval += "-x64-macosx" + elif platform == "SunOSSparc": + retval += "-sparc64-solaris" + elif platform == "SunOSx86": + retval += "-x64-solaris" + else: + raise RuntimeError("Unknown platform: " + platform) + return retval + + +def determine_platform(): + """ Determines the platform (as defined in prepare_release) for the current + hostname + """ + + p = platform.platform().lower() + print("PLATFORM = " + p) + if p.find("linux") != -1: + if p.find("x86_64") != -1: + return "Linux64" + else: + return "Linux32" + elif p.find("sunos") != -1: + if p.find("sparc") != -1: + return "SunOSSparc" + else: + return "SunOSx86" + elif p.find("windows") != -1 or p.find("cygwin") != -1: + if platform.architecture()[0].find("64") != -1: + return "Win64" + else: + return "Win32" + elif p.find("darwin") != -1: + return "IntelMAC" + else: + raise RuntimeError("Unknown platform: " + p) diff --git a/c++/scripts/projects/magicblast/post_build/macosx/large-Blue_ncbi_logo.tiff b/c++/scripts/projects/magicblast/post_build/macosx/large-Blue_ncbi_logo.tiff new file mode 100644 index 0000000000000000000000000000000000000000..9408bc3f6f6c27e6e3422777f05174acc47dba19 GIT binary patch literal 5536538 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�>DLQ== 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 DZbRBc literal 0 HcmV?d00001 diff --git a/c++/scripts/projects/magicblast/post_build/macosx/ncbi-magicblast.sh b/c++/scripts/projects/magicblast/post_build/macosx/ncbi-magicblast.sh new file mode 100755 index 00000000..2d4bbcc1 --- /dev/null +++ b/c++/scripts/projects/magicblast/post_build/macosx/ncbi-magicblast.sh @@ -0,0 +1,86 @@ +#!/bin/sh -xe + +INSTALLDIR=$1 +SCRIPTDIR=$2 +BLAST_VERSION=$3 +PRODUCT="ncbi-magicblast-$BLAST_VERSION+" + +INSTALL_LOCATION1=/usr/local/ncbi/magicblast +INSTALL_LOCATION2=/etc/paths.d +STAGE_DIR1=_stage1 +STAGE_DIR2=_stage2 +RESOURCES_DIR=Resources +ID=gov.nlm.nih.ncbi.blast + +if [ $# -ne 3 ] ; then + echo "Usage: ncbi-magicblast.sh [installation directory] [MacOSX post-build script directory] [BLAST version]"; + exit 1; +fi + +setup() +{ + rm -rf $PRODUCT.dmg $PRODUCT $STAGE_DIR1 $STAGE_DIR2 $INSTALLDIR/installer $RESOURCES_DIR + mkdir -p $STAGE_DIR1/bin $STAGE_DIR1/doc $STAGE_DIR2 $PRODUCT +} + +prep_binary_component_package() +{ + BLAST_BINS="magicblast makeblastdb" + ALL_BINS="$BLAST_BINS" + + cp $INSTALLDIR/README $STAGE_DIR1/doc/README.txt + + for bin in $ALL_BINS; do + cp -p $INSTALLDIR/bin/$bin $STAGE_DIR1/bin + done + + /usr/bin/pkgbuild --root $STAGE_DIR1 --identifier $ID.binaries --version \ + $BLAST_VERSION --install-location $INSTALL_LOCATION1 binaries.pkg +} + +prep_paths_component_package() +{ + echo /usr/local/ncbi/magicblast/bin > $STAGE_DIR2/ncbi_magicblast + /usr/bin/pkgbuild --root $STAGE_DIR2 --identifier $ID.paths --version \ + $BLAST_VERSION --install-location $INSTALL_LOCATION2 paths.pkg +} + +customize_distribution_xml() +{ + sed -i.bak '/options/i\ + NCBI Magic-BLAST Command Line Applications \ + \ + \ + \ +' Distribution.xml +} + +create_product_archive() +{ + /usr/bin/productbuild --synthesize --identifier $ID --version \ + $BLAST_VERSION --package binaries.pkg --package paths.pkg Distribution.xml + + customize_distribution_xml + + mkdir $RESOURCES_DIR + cp -p $INSTALLDIR/LICENSE $RESOURCES_DIR + for f in welcome.txt large-Blue_ncbi_logo.tiff ; do + cp -p $SCRIPTDIR/$f $RESOURCES_DIR + done + + /usr/bin/productbuild --resources Resources --distribution Distribution.xml $PRODUCT/$PRODUCT.pkg + cp -p $SCRIPTDIR/uninstall_ncbi_magicblast.zip $PRODUCT +} + +create_disk_image() +{ + /usr/bin/hdiutil create $PRODUCT.dmg -srcfolder $PRODUCT + mkdir $INSTALLDIR/installer + mv $PRODUCT.dmg $INSTALLDIR/installer +} + +setup +prep_binary_component_package +prep_paths_component_package +create_product_archive +create_disk_image diff --git a/c++/scripts/projects/magicblast/post_build/macosx/uninstall_ncbi_magicblast.zip b/c++/scripts/projects/magicblast/post_build/macosx/uninstall_ncbi_magicblast.zip new file mode 100644 index 0000000000000000000000000000000000000000..679a4049081dce124890a9c44aebbaa96c17b419 GIT binary patch literal 58778 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 literal 0 HcmV?d00001 diff --git a/c++/scripts/projects/magicblast/post_build/macosx/welcome.txt b/c++/scripts/projects/magicblast/post_build/macosx/welcome.txt new file mode 100644 index 00000000..3202f0d4 --- /dev/null +++ b/c++/scripts/projects/magicblast/post_build/macosx/welcome.txt @@ -0,0 +1,2 @@ +NCBI Magic-BLAST is a specialized variant of BLAST designed for mapping +next-generation RNA or DNA sequencing runs against a genome or transcriptome. diff --git a/c++/scripts/projects/magicblast/post_build/make_installers.py b/c++/scripts/projects/magicblast/post_build/make_installers.py new file mode 100755 index 00000000..c0d9b13a --- /dev/null +++ b/c++/scripts/projects/magicblast/post_build/make_installers.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python3 +"""Driver program for post-build processing""" +# $Id: make_installers.py 513315 2016-09-09 13:58:57Z boratyng $ +# +# Author: Christiam Camacho +# + +from __future__ import print_function +import os, sys, os.path +from optparse import OptionParser +import blast_utils +import shutil + +VERBOSE = False +SCRIPTS_DIR = os.path.dirname(os.path.abspath(sys.argv[0])) + +def main(): #IGNORE:R0911 + """ Creates installers for selected platforms. """ + parser = OptionParser("%prog \ + \"\"") + parser.add_option("-v", "--verbose", action="store_true", default=False, + help="Show verbose output", dest="VERBOSE") + options, args = parser.parse_args() + if len(args) != 5: + parser.error("Incorrect number of arguments") + return 1 + + blast_version, platform, installdir, srctarball, libdir = args + + global VERBOSE #IGNORE:W0603 + VERBOSE = options.VERBOSE + if VERBOSE: + print("BLAST version", blast_version) + print("Platform:", platform) + print("Installation directory:", installdir) + print("Source tarball:", srctarball) + print("Lib directory:", libdir) + + if platform.startswith("Win"): + import glob + print("Files in libdir " + libdir + ":") + for dll in glob.glob(libdir + "/*"): + print(dll) + print("Files in install dir " + installdir + ":") + for dll in glob.glob(installdir + "/*"): + print(dll) + + + if platform.startswith("Win"): + # copy ncbi-vdb-md.dll and GNUTLS libs + shutil.copy(libdir + "ncbi-vdb-md.dll", installdir + "bin") + shutil.copy(libdir + "libgcc_s_seh-1.dll", installdir + "bin") + shutil.copy(libdir + "libgmp-10.dll", installdir + "bin") + shutil.copy(libdir + "libgnutls-30.dll", installdir + "bin") + shutil.copy(libdir + "libhogweed-4-2.dll", installdir + "bin") + shutil.copy(libdir + "libnettle-6-2.dll", installdir + "bin") + shutil.copy(libdir + "libp11-kit-0.dll", installdir + "bin") + return launch_win_installer_build(installdir, blast_version) + if platform.startswith("Linux64"): + return launch_rpm_build(installdir, blast_version, srctarball) + if platform == "FreeBSD32" or platform.startswith("SunOS") or \ + platform.startswith("Linux32"): + return do_nothing(platform) + if platform.startswith("IntelMAC"): + return mac_post_build(installdir, blast_version) + + print("Unknown OS identifier:" + platform, file=sys.stderr) + print("Exiting post build script.", file=sys.stderr) + return 2 + +def launch_win_installer_build(installdir, blast_version): + '''Windows post-build: create installer''' + if VERBOSE: + print("Packaging for Windows...") + cmd = "python " + os.path.join(SCRIPTS_DIR, "win", "make_win.py") + " " + cmd += blast_version + " " + installdir + if VERBOSE: + cmd += " -v" + blast_utils.safe_exec(cmd) + return 0 + +def launch_rpm_build(installdir, blast_version, srctarball): + '''Linux post-build: create RPM''' + if VERBOSE: + print("Packing linux RPM...") + cmd = "python3 " + os.path.join(SCRIPTS_DIR, "rpm", "make_rpm.py") + " " + cmd += blast_version + " " + installdir + " " + srctarball + if VERBOSE: + cmd += " -v" + if len(srctarball) > 2: # Skip for local builds + blast_utils.safe_exec(cmd) + return 0 + +def mac_post_build(installdir, blast_version): + '''MacOSX post-build: create installer''' + if VERBOSE: + print("Packaging for MacOSX...") + script_dir = os.path.join(SCRIPTS_DIR, "macosx") + cmd = os.path.join(script_dir, "ncbi-magicblast.sh") + " " + cmd += installdir + " " + script_dir + " " + blast_version + blast_utils.safe_exec(cmd) + return 0 + +def do_nothing(platform): + '''No op function''' + print("No post-build step necessary for", platform) + return 0 + +# The script execution entry point +if __name__ == "__main__": + sys.exit( main() ) + diff --git a/c++/scripts/projects/magicblast/post_build/rpm/make_rpm.py b/c++/scripts/projects/magicblast/post_build/rpm/make_rpm.py new file mode 100755 index 00000000..829ce9c9 --- /dev/null +++ b/c++/scripts/projects/magicblast/post_build/rpm/make_rpm.py @@ -0,0 +1,173 @@ +#!/usr/bin/env python3 +"""Script to create a source/binary RPM. +""" +# $Id: make_rpm.py 509841 2016-08-09 16:23:05Z boratyng $ + +from __future__ import print_function +import sys, os, shutil +from optparse import OptionParser +import subprocess +import tarfile +SCRIPT_DIR = os.path.dirname(os.path.abspath(sys.argv[0])) +sys.path.append(os.path.join(SCRIPT_DIR, "..")) +from blast_utils import * #IGNORE:W0401 + +VERBOSE = False + +# Name of the temporary rpmbuild directory +RPMBUILD_HOME = "rpmbuild" +PACKAGE_NAME = "" +# Name of the source TARBALL to create +TARBALL = "" +# Local RPM configuration file +RPMMACROS = os.path.join(os.path.expanduser("~"), ".rpmmacros") + +def setup_rpmbuild(): + """ Prepare local rpmbuild directory. """ + cleanup_rpm() + os.mkdir(RPMBUILD_HOME) + for directory in [ 'BUILD', 'SOURCES', 'SPECS', 'SRPMS', 'tmp', 'RPMS' ]: + os.mkdir(os.path.join(RPMBUILD_HOME, directory)) + cwd = os.getcwd() + os.chdir(os.path.join(RPMBUILD_HOME, 'RPMS')) + for subdir in [ 'i386', 'i586', 'i686', 'noarch', 'x86_64' ]: + os.mkdir(subdir) + os.chdir(cwd) + + # Create ~/.rpmmacros + with open(RPMMACROS, "w") as out: + print("%_topdir %( echo", os.path.join(cwd, RPMBUILD_HOME), ")", file=out) + print("%_tmppath %( echo", end=' ', file=out) + print(os.path.join(cwd, RPMBUILD_HOME, "tmp"), ")", file=out) + print(file=out) + print("%packager Christiam E. Camacho (camacho@ncbi.nlm.nih.gov)", file=out) + print("%debug_package %{nil}", file=out) + if VERBOSE: + print("Created", RPMMACROS) + +def cleanup_rpm(): + """ Delete rpm files """ + if os.path.exists(RPMBUILD_HOME): + shutil.rmtree(RPMBUILD_HOME) + + if os.path.exists(RPMMACROS): + os.remove(RPMMACROS) + +def cleanup_srctarball_contents(): + """ Remove unnecessary directories/files from svn checkout """ + import fnmatch + + cmd = "find " + PACKAGE_NAME + " -type d -name .svn | xargs rm -fr " + safe_exec(cmd) + + os.remove(os.path.join(PACKAGE_NAME, "Makefile")) + for path in ["builds", "scripts"]: + path = os.path.join(PACKAGE_NAME, path) + if os.path.exists(path): + shutil.rmtree(path) + if VERBOSE: + print("Deleting", path) + + projects_path = os.path.join(PACKAGE_NAME, "c++", "scripts", "projects") + for root, dirs, files in os.walk(projects_path): + for name in files: + name = os.path.join(root, name) + if fnmatch.fnmatch(name, "*blast/*"): + continue + if VERBOSE: + print("Deleting file", name) + os.remove(name) + + for name in dirs: + name = os.path.join(root, name) + if fnmatch.fnmatch(name, "*blast*"): + continue + if VERBOSE: + print("Deleting directory", name) + shutil.rmtree(name) + + +def decompress_src_tarball(srctarball): + """Decompreses the source tarball provided""" + tar = tarfile.open(srctarball) + os.mkdir(PACKAGE_NAME) + cwd = os.getcwd() + os.chdir(os.path.join(cwd, PACKAGE_NAME)) + tar.list() + tar.extractall() + os.chdir(cwd) + cleanup_srctarball_contents() + +def compress_sources(): + """Compress sources to be included in source RPM""" + tar = tarfile.open(TARBALL, "w:bz2") + tar.add(PACKAGE_NAME) + tar.close() + +def cleanup(): + """ Remove all files created. """ + if os.path.exists(TARBALL): + os.remove(TARBALL) + if os.path.exists(PACKAGE_NAME): + shutil.rmtree(PACKAGE_NAME) + +def run_rpm(blast_version): + """Run the rpmbuild command""" + shutil.rmtree(PACKAGE_NAME) + shutil.move(TARBALL, os.path.join(RPMBUILD_HOME, "SOURCES")) + rpm_spec = "ncbi-magicblast.spec" + src = os.path.join(SCRIPT_DIR, rpm_spec) + dest = os.path.join(RPMBUILD_HOME, "SPECS", rpm_spec) + shutil.copyfile(src, dest) + update_blast_version(dest, blast_version) + cmd = "/usr/bin/rpmbuild -ba " + dest + safe_exec(cmd) + +def move_rpms_to_installdir(installdir): + """Copy the resulting RPM files into the installation directory""" + installer_dir = os.path.join(installdir, "installer") + if not os.path.exists(installer_dir): + os.makedirs(installer_dir) + + args = [ "find", RPMBUILD_HOME, "-name", "*.rpm" ] + output = subprocess.Popen(args, stdout=subprocess.PIPE).communicate()[0] + for rpm in output.split(): + rpm = rpm.decode('ascii') + if VERBOSE: + print("mv", rpm, installer_dir) + shutil.move(rpm, installer_dir) + + +def main(): + """ Creates RPMs for linux. """ + parser = OptionParser("%prog \ + \"\"") + parser.add_option("-v", "--verbose", action="store_true", default=False, + help="Show verbose output", dest="VERBOSE") + options, args = parser.parse_args() + if len(args) != 3: + parser.error("Incorrect number of arguments") + return 1 + + # N.B.: srctarball may be an empty argument (i.e.: "") in case of local + # builds, but this script shouldn't be invoked in that case + blast_version, installdir, srctarball = args + global VERBOSE, PACKAGE_NAME, TARBALL #IGNORE:W0603 + VERBOSE = options.VERBOSE + if VERBOSE: + print("Installing RPM to", installdir) + + PACKAGE_NAME = "ncbi-magicblast-" + blast_version + TARBALL = PACKAGE_NAME + ".tgz" + + setup_rpmbuild() + cleanup() + decompress_src_tarball(srctarball) + compress_sources() + run_rpm(blast_version) + move_rpms_to_installdir(installdir) + cleanup_rpm() + cleanup() + +if __name__ == "__main__": + sys.exit(main()) diff --git a/c++/scripts/projects/magicblast/post_build/rpm/ncbi-magicblast.spec b/c++/scripts/projects/magicblast/post_build/rpm/ncbi-magicblast.spec new file mode 100644 index 00000000..d7cadef2 --- /dev/null +++ b/c++/scripts/projects/magicblast/post_build/rpm/ncbi-magicblast.spec @@ -0,0 +1,41 @@ +Name: ncbi-magicblast +Version: BLAST_VERSION +Release: 1 +Source0: %{name}-%{version}.tgz +Summary: NCBI Magic-BLAST is a tool for mapping next-generation RNA or DNA sequencing runs against a genome or transcriptome. +Exclusiveos: linux +Group: NCBI/BLAST +License: Public Domain +BuildArch: i686 x86_64 +BuildRoot: /var/tmp/%{name}-buildroot +Prefix: /usr + +Requires: ncbi-blast + +%description +NCBI Magic-BLAST is a specialized variant of BLAST designed for mapping +next-generation RNA or DNA sequencing runs against a genome or transcriptome. + +%prep +%setup -q + +%build +./configure +cd c++/*/build +%__make -f Makefile.flat + +%install +%__mkdir_p $RPM_BUILD_ROOT/%_bindir +%__install -m755 c++/*/bin/magicblast $RPM_BUILD_ROOT/%_bindir + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root) +%_bindir/* + +%changelog +* Fri Aug 19 2016 +- See ChangeLog file + diff --git a/c++/scripts/projects/magicblast/post_build/win/EnvVarUpdate.nsh b/c++/scripts/projects/magicblast/post_build/win/EnvVarUpdate.nsh new file mode 100644 index 00000000..4148114a --- /dev/null +++ b/c++/scripts/projects/magicblast/post_build/win/EnvVarUpdate.nsh @@ -0,0 +1,568 @@ +; Obtained from http://nsis.sourceforge.net/Path_Manipulation on 08/14/08 +!ifndef ENVVARUPDATE_FUNCTION +!define ENVVARUPDATE_FUNCTION +!verbose push +!verbose 3 +!include "LogicLib.nsh" +!include "WinMessages.NSH" + +; ---------------------------------- Macro Definitions ---------------------------------------- +!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString + Push "${EnvVarName}" + Push "${Action}" + Push "${RegLoc}" + Push "${PathString}" + Call EnvVarUpdate + Pop "${ResultVar}" +!macroend +!define EnvVarUpdate '!insertmacro "_EnvVarUpdateConstructor"' + +!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString + Push "${EnvVarName}" + Push "${Action}" + Push "${RegLoc}" + Push "${PathString}" + Call un.EnvVarUpdate + Pop "${ResultVar}" +!macroend +!define un.EnvVarUpdate '!insertmacro "_unEnvVarUpdateConstructor"' + +!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts + Push "${String}" + Push "${Separators}" + Push "${ResultPart}" + Push "${SkipEmptyParts}" + Call ${UN}StrTok + Pop "${ResultVar}" +!macroend +!define StrTok '!insertmacro "_StrTokConstructor"' + +!macro _StrContainsConstructor OUT NEEDLE HAYSTACK + Push "${HAYSTACK}" + Push "${NEEDLE}" + Call ${UN}StrContains + Pop "${OUT}" +!macroend +!define StrContains '!insertmacro "_StrContainsConstructor"' + +!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK + Push "${HAYSTACK}" + Push "${NEEDLE}" + Push "${NEEDLE2}" + Call ${UN}StrReplace + Pop "${OUT}" +!macroend +!define StrReplace '!insertmacro "_strReplaceConstructor"' + +; ---------------------------------- Macro Definitions end------------------------------------- + +;----------------------------------- EnvVarUpdate start---------------------------------------- +!define hklm_all_users 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' +!define hkcu_current_user 'HKCU "Environment"' + +!macro EnvVarUpdate UN + +Function ${UN}EnvVarUpdate + + Push $0 + Exch 4 + Exch $1 + Exch 3 + Exch $2 + Exch 2 + Exch $3 + Exch + Exch $4 + Push $5 + Push $6 + Push $7 + Push $8 + Push $9 + Push $R0 + + /* After this point: + ------------------------- + $0 = ResultVar (returned) + $1 = EnvVarName (input) + $2 = Action (input) + $3 = RegLoc (input) + $4 = PathString (input) + $5 = Orig EnvVar (read from registry) + $6 = Len of $0 (temp) + $7 = tempstr1 (temp) + $8 = Entry counter (temp) + $9 = tempstr2 (temp) + $R0 = tempChar (temp) */ + + ; Step 1: Read contents of EnvVarName from RegLoc + ; + ; Check for empty EnvVarName + ${If} $1 == "" + SetErrors + DetailPrint "ERROR: EnvVarName is blank" + Goto EnvVarUpdate_Restore_Vars + ${EndIf} + + ; Check for valid Action + ${If} $2 != "A" + ${AndIf} $2 != "P" + ${AndIf} $2 != "R" + SetErrors + DetailPrint "ERROR: Invalid Action - must be A, P, or R" + Goto EnvVarUpdate_Restore_Vars + ${EndIf} + + ${If} $3 == HKLM + ReadRegStr $5 ${hklm_all_users} $1 ; Get EnvVarName from all users into $5 + ${ElseIf} $3 == HKCU + ReadRegStr $5 ${hkcu_current_user} $1 ; Read EnvVarName from current user into $5 + ${Else} + SetErrors + DetailPrint 'ERROR: Action is [$3] but must be "HKLM" or HKCU"' + Goto EnvVarUpdate_Restore_Vars + ${EndIf} + + ; Check for empty PathString + ${If} $4 == "" + SetErrors + DetailPrint "ERROR: PathString is blank" + Goto EnvVarUpdate_Restore_Vars + ${EndIf} + + ; Make sure we've got some work to do + ${If} $5 == "" + ${AndIf} $2 == "R" + SetErrors + DetailPrint "$1 is empty - Nothing to remove" + Goto EnvVarUpdate_Restore_Vars + ${EndIf} + + ; Step 2: Scrub EnvVar + ; + StrCpy $0 $5 ; Copy the contents to $0 + ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or + ; after the last one are not removed here but instead in Step 3) + ${If} $0 != "" ; If EnvVar is not empty ... + ${Do} + ${StrContains} $7 " ;" $0 + ${If} $7 == "" + ${ExitDo} + ${EndIf} + ${StrReplace} $0 " ;" ";" $0 ; Remove ';' + ${Loop} + ${Do} + ${StrContains} $7 "; " $0 + ${If} $7 == "" + ${ExitDo} + ${EndIf} + ${StrReplace} $0 "; " ";" $0 ; Remove ';' + ${Loop} + ${Do} + ${StrContains} $7 ";;" $0 + ${If} $7 == "" + ${ExitDo} + ${EndIf} + ${StrReplace} $0 ";;" ";" $0 + ${Loop} + + ; Remove a leading or trailing semicolon from EnvVar + StrCpy $7 $0 1 0 + ${If} $7 == ";" + StrCpy $0 $0 "" 1 ; Change ';' to '' + ${EndIf} + StrLen $6 $0 + IntOp $6 $6 - 1 + StrCpy $7 $0 1 $6 + ${If} $7 == ";" + StrCpy $0 $0 $6 ; Change ';' to '' + ${EndIf} + ; DetailPrint "Scrubbed $1: [$0]" ; Uncomment to debug + ${EndIf} + + /* Step 3. Remove all instances of the target path/string (even if "A" or "P") + $6 = bool flag (1 = found and removed PathString) + $7 = a string (e.g. path) delimited by semicolon(s) + $8 = entry counter starting at 0 + $9 = copy of $0 + $R0 = tempChar */ + + ${If} $5 != "" ; If EnvVar is not empty ... + StrCpy $9 $0 + StrCpy $0 "" + StrCpy $8 0 + StrCpy $6 0 + + ${Do} + ${StrTok} $7 $9 ";" $8 "0" ; $7 = next entry, $8 = entry counter + + ${If} $7 == "" ; If we've run out of entries, + ${ExitDo} ; were done + ${EndIf} ; + + ; Remove leading and trailing spaces from this entry (critical step for Action=Remove) + ${Do} + StrCpy $R0 $7 1 + ${If} $R0 != " " + ${ExitDo} + ${EndIf} + StrCpy $7 $7 "" 1 ; Remove leading space + ${Loop} + ${Do} + StrCpy $R0 $7 1 -1 + ${If} $R0 != " " + ${ExitDo} + ${EndIf} + StrCpy $7 $7 -1 ; Remove trailing space + ${Loop} + ${If} $7 == $4 ; If string matches, remove it by not appending it + StrCpy $6 1 ; Set 'found' flag + ${ElseIf} $7 != $4 ; If string does NOT match + ${AndIf} $0 == "" ; and the 1st string being added to $0, + StrCpy $0 $7 ; copy it to $0 without a prepended semicolon + ${ElseIf} $7 != $4 ; If string does NOT match + ${AndIf} $0 != "" ; and this is NOT the 1st string to be added to $0, + StrCpy $0 $0;$7 ; append path to $0 with a prepended semicolon + ${EndIf} ; + + IntOp $8 $8 + 1 ; Bump counter + ${Loop} ; Check for duplicates until we run out of paths + ${EndIf} + + ; Step 4: Perform the requested Action + ; + ${If} $2 != "R" ; If Append or Prepend + ${If} $6 == 1 ; And if we found the target + DetailPrint "Target is already present in $1. It will be removed and" + ${EndIf} + ${If} $0 == "" ; If EnvVar is (now) empty + StrCpy $0 $4 ; just copy PathString to EnvVar + ${If} $6 == 0 ; If found flag is either 0 + ${OrIf} $6 == "" ; or blank (if EnvVarName is empty) + DetailPrint "$1 was empty and has been updated with the target" + ${EndIf} + ${ElseIf} $2 == "A" ; If Append (and EnvVar is not empty), + StrCpy $0 $0;$4 ; append PathString + ${If} $6 == 1 + DetailPrint "appended to $1" + ${Else} + DetailPrint "Target was appended to $1" + ${EndIf} + ${Else} ; If Prepend (and EnvVar is not empty), + StrCpy $0 $4;$0 ; prepend PathString + ${If} $6 == 1 + DetailPrint "prepended to $1" + ${Else} + DetailPrint "Target was prepended to $1" + ${EndIf} + ${EndIf} + ${Else} ; If Action = Remove + ${If} $6 == 1 ; and we found the target + DetailPrint "Target was found and removed from $1" + ${Else} + DetailPrint "Target was NOT found in $1 (nothing to remove)" + ${EndIf} + ${If} $0 == "" + DetailPrint "$1 is now empty" + ${EndIf} + ${EndIf} + + ; Step 5: Update the registry at RegLoc with the updated EnvVar and announce the change + ; + ClearErrors + ${If} $3 == HKLM + WriteRegExpandStr ${hklm_all_users} $1 $0 ; Write it in all users section + ${ElseIf} $3 == HKCU + WriteRegExpandStr ${hkcu_current_user} $1 $0 ; Write it to current user section + ${EndIf} + + IfErrors 0 +4 + MessageBox MB_OK|MB_ICONEXCLAMATION "Could not write updated $1 to $3" + DetailPrint "Could not write updated $1 to $3" + Goto EnvVarUpdate_Restore_Vars + + ; "Export" our change + SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 + + EnvVarUpdate_Restore_Vars: + ; + ; Restore the user's variables and return ResultVar + Pop $R0 + Pop $9 + Pop $8 + Pop $7 + Pop $6 + Pop $5 + Pop $4 + Pop $3 + Pop $2 + Pop $1 + Push $0 ; Push my $0 (ResultVar) + Exch + Pop $0 ; Restore his $0 + +FunctionEnd + +!macroend ; EnvVarUpdate UN +!insertmacro EnvVarUpdate "" +!insertmacro EnvVarUpdate "un." +;----------------------------------- EnvVarUpdate end---------------------------------------- + + +;-------------------------------------- StrTok start ------------------------------------------ +; Written by Diego Pedroso (deguix) +; +!macro StrTok UN + +Function ${UN}StrTok + +/*After this point: + ------------------------------------------ + $0 = SkipEmptyParts (input) + $1 = ResultPart (input) + $2 = Separators (input) + $3 = String (input) + $4 = SeparatorsLen (temp) + $5 = StrLen (temp) + $6 = StartCharPos (temp) + $7 = TempStr (temp) + $8 = CurrentLoop + $9 = CurrentSepChar + $R0 = CurrentSepCharNum */ + + ;Get input from user + Exch $0 + Exch + Exch $1 + Exch + Exch 2 + Exch $2 + Exch 2 + Exch 3 + Exch $3 + Exch 3 + Push $4 + Push $5 + Push $6 + Push $7 + Push $8 + Push $9 + Push $R0 + + ;Parameter defaults + ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|} + ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|} + ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|} + + ;Get "String" and "Separators" length + StrLen $4 $2 + StrLen $5 $3 + ;Start "StartCharPos" and "ResultPart" counters + StrCpy $6 0 + StrCpy $8 -1 + + ;Loop until "ResultPart" is met, "Separators" is found or + ;"String" reaches its end + ResultPartLoop: ;"CurrentLoop" Loop + + ;Increase "CurrentLoop" counter + IntOp $8 $8 + 1 + + StrSearchLoop: + ${Do} ;"String" Loop + ;Remove everything before and after the searched part ("TempStr") + StrCpy $7 $3 1 $6 + + ;Verify if it's the "String" end + ${If} $6 >= $5 + ;If "CurrentLoop" is what the user wants, remove the part + ;after "TempStr" and itself and get out of here + ${If} $8 == $1 + ${OrIf} $1 == `L` + StrCpy $3 $3 $6 + ${Else} ;If not, empty "String" and get out of here + StrCpy $3 `` + ${EndIf} + StrCpy $R0 `End` + ${ExitDo} + ${EndIf} + + ;Start "CurrentSepCharNum" counter (for "Separators" Loop) + StrCpy $R0 0 + + ${Do} ;"Separators" Loop + ;Use one "Separators" character at a time + ${If} $R0 <> 0 + StrCpy $9 $2 1 $R0 + ${Else} + StrCpy $9 $2 1 + ${EndIf} + + ;Go to the next "String" char if it's "Separators" end + ${IfThen} $R0 >= $4 ${|} ${ExitDo} ${|} + + ;Or, if "TempStr" equals "CurrentSepChar", then... + ${If} $7 == $9 + StrCpy $7 $3 $6 + + ;If "String" is empty because this result part doesn't + ;contain data, verify if "SkipEmptyParts" is activated, + ;so we don't return the output to user yet + + ${If} $7 == `` + ${AndIf} $0 = 1 ;${TRUE} + IntOp $6 $6 + 1 + StrCpy $3 $3 `` $6 + StrCpy $6 0 + Goto StrSearchLoop + ${ElseIf} $8 == $1 + StrCpy $3 $3 $6 + StrCpy $R0 "End" + ${ExitDo} + ${EndIf} ;If not, go to the next result part + IntOp $6 $6 + 1 + StrCpy $3 $3 `` $6 + StrCpy $6 0 + Goto ResultPartLoop + ${EndIf} + + ;Increase "CurrentSepCharNum" counter + IntOp $R0 $R0 + 1 + ${Loop} + ${IfThen} $R0 == "End" ${|} ${ExitDo} ${|} + + ;Increase "StartCharPos" counter + IntOp $6 $6 + 1 + ${Loop} + + /*After this point: + ------------------------------------------ + $3 = ResultVar (output)*/ + + ;Return output to user + Pop $R0 + Pop $9 + Pop $8 + Pop $7 + Pop $6 + Pop $5 + Pop $4 + Pop $0 + Pop $1 + Pop $2 + Exch $3 +FunctionEnd + +!macroend ; StrTok UN +!insertmacro StrTok "" +!insertmacro StrTok "un." + +;----------------------------------------- StrTok end ------------------------------------------- + + +;---------------------------------------- StrContains start ------------------------------------- +; StrContains +; This function does a case sensitive searches for an occurrence of a substring in a string. +; It returns the substring if it is found; otherwise, it returns null(""). +; Usage: ${StrContains} "$result_var" "Needle" "Haystack" +; Written by kenglish_hi +; Adapted from StrReplace written by dandaman32 + +Var STR_HAYSTACK +Var STR_NEEDLE +Var STR_CONTAINS_VAR_1 +Var STR_CONTAINS_VAR_2 +Var STR_CONTAINS_VAR_3 +Var STR_CONTAINS_VAR_4 +Var STR_RETURN_VAR + +!macro StrContains UN + +Function ${UN}StrContains + + Exch $STR_NEEDLE + Exch + Exch $STR_HAYSTACK + ; Uncomment to debug + ;MessageBox MB_OK 'STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK ' + StrCpy $STR_RETURN_VAR "" + StrCpy $STR_CONTAINS_VAR_1 -1 + StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE + StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK + loop: + IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1 + StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1 + StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found + StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done + Goto loop + found: + StrCpy $STR_RETURN_VAR $STR_NEEDLE + Goto done + done: + Pop $STR_HAYSTACK ;Prevent "invalid opcode" errors and keep the stack intact + Exch $STR_RETURN_VAR +FunctionEnd + +!macroend +!insertmacro StrContains "" +!insertmacro StrContains "un." +;--------------------------------------- StrContains end --------------------------------------- + + +;--------------------------------------- StrReplace start -------------------------------------- +; NOTE: Do not substitute 'StrReplaceV4' for this function. It will fail due to the way I call it. +; +; StrReplace +; Replaces all occurences of a given needle within a haystack with another string +; Usage: ${StrReplace} "$result_var" "SubString" "RepString" "String" +; Written by dandaman32 + +Var STR_REPLACE_VAR_0 +Var STR_REPLACE_VAR_1 +Var STR_REPLACE_VAR_2 +Var STR_REPLACE_VAR_3 +Var STR_REPLACE_VAR_4 +Var STR_REPLACE_VAR_5 +Var STR_REPLACE_VAR_6 +Var STR_REPLACE_VAR_7 +Var STR_REPLACE_VAR_8 + +!macro StrReplace UN + +Function ${UN}StrReplace + + Exch $STR_REPLACE_VAR_2 + Exch 1 + Exch $STR_REPLACE_VAR_1 + Exch 2 + Exch $STR_REPLACE_VAR_0 + StrCpy $STR_REPLACE_VAR_3 -1 + StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1 + StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0 + loop: + IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1 + StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3 + StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found + StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done + Goto loop + found: + StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3 + IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4 + StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 "" $STR_REPLACE_VAR_8 + StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7 + StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0 + Goto loop + done: + Pop $STR_REPLACE_VAR_1 ; Prevent "invalid opcode" errors and keep the + Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called + Exch $STR_REPLACE_VAR_0 + +FunctionEnd + +!macroend ; StrContains UN +!insertmacro StrReplace "" +!insertmacro StrReplace "un." + +;----------------------------------------- StrReplace end --------------------------------------- + +!verbose pop +!endif \ No newline at end of file diff --git a/c++/scripts/projects/magicblast/post_build/win/make_win.py b/c++/scripts/projects/magicblast/post_build/win/make_win.py new file mode 100644 index 00000000..86b3bad9 --- /dev/null +++ b/c++/scripts/projects/magicblast/post_build/win/make_win.py @@ -0,0 +1,91 @@ +#! /usr/bin/env python3 +"""Script to create the Windows installer for BLAST command line applications""" +# $Id: make_win.py 513315 2016-09-09 13:58:57Z boratyng $ +# +# Author: Christiam camacho + +from __future__ import print_function +import os, sys, os.path +import shutil +from optparse import OptionParser +SCRIPT_DIR = os.path.dirname(os.path.abspath(sys.argv[0])) +sys.path.append(os.path.join(SCRIPT_DIR, "..")) +from blast_utils import safe_exec, update_blast_version + +VERBOSE = False + +# NSIS Configuration file +NSIS_CONFIG = os.path.join(SCRIPT_DIR, "ncbi-blast.nsi") + +def extract_installer(): + """Extract name of the installer file from NSIS configuration file""" + from fileinput import FileInput + + retval = "unknown" + for line in FileInput(NSIS_CONFIG): + if line.find("OutFile") != -1: + retval = line.split()[1] + return retval.strip('"') + +def main(): + """ Creates NSIS installer for BLAST command line binaries """ + global VERBOSE #IGNORE:W0603 + parser = OptionParser("%prog ") + parser.add_option("-v", "--verbose", action="store_true", default=False, + help="Show verbose output", dest="VERBOSE") + options, args = parser.parse_args() + if len(args) != 2: + parser.error("Incorrect number of arguments") + return 1 + + blast_version, installdir = args + VERBOSE = options.VERBOSE + + apps = [ "magicblast.exe", + "ncbi-vdb-md.dll", + "makeblastdb.exe", + "libgcc_s_seh-1.dll", + "libgmp-10.dll", + "libgnutls-30.dll", + "libhogweed-4-2.dll", + "libnettle-6-2.dll", + "libp11-kit-0.dll" ] + + cwd = os.getcwd() + for app in apps: + app = os.path.join(installdir, "bin", app) + if VERBOSE: + print("Copying", app, "to", cwd) + shutil.copy(app, cwd) + + + update_blast_version(NSIS_CONFIG, blast_version) + # Copy necessary files to the current working directory + shutil.copy(NSIS_CONFIG, cwd) + license_file = os.path.join(SCRIPT_DIR, "..", "..", "LICENSE") + shutil.copy(license_file, cwd) + + # Copy the README file from the parent directory + readme_file = os.path.join(SCRIPT_DIR, "..", "..", "README") + shutil.copy(readme_file, cwd) + + for aux_file in ("EnvVarUpdate.nsh", "ncbilogo.ico", "unix2dos.nsh"): + src = os.path.join(SCRIPT_DIR, aux_file) + if VERBOSE: + print("Copying", src, "to", cwd) + shutil.copy(src, cwd) + + # makensis is in the path of the script courtesy of the release framework + cmd = "makensis " + os.path.basename(NSIS_CONFIG) + safe_exec(cmd) + + installer_dir = os.path.join(installdir, "installer") + if not os.path.exists(installer_dir): + os.makedirs(installer_dir) + + installer = extract_installer() + shutil.copy(installer, installer_dir) + +if __name__ == "__main__": + sys.exit(main()) + diff --git a/c++/scripts/projects/magicblast/post_build/win/ncbi-blast.nsi b/c++/scripts/projects/magicblast/post_build/win/ncbi-blast.nsi new file mode 100755 index 00000000..04360961 --- /dev/null +++ b/c++/scripts/projects/magicblast/post_build/win/ncbi-blast.nsi @@ -0,0 +1,102 @@ +;NSIS Modern User Interface + +;-------------------------------- +;Include Modern UI + + !include "MUI.nsh" + !include "EnvVarUpdate.nsh" + !include "x64.nsh" + !include "unix2dos.nsh" + +;-------------------------------- +; Initialization function to properly set the installation directory +Function .onInit + ${If} ${RunningX64} + StrCpy $INSTDIR "$PROGRAMFILES64\NCBI\magicblast-BLAST_VERSION" + ${EndIf} +FunctionEnd + +;-------------------------------- +;General + + ;Name and file + Name "NCBI Magic-BLAST BLAST_VERSION" + OutFile "ncbi-magicblast-BLAST_VERSION.exe" + ; Install/uninstall icons + !define MUI_ICON "ncbilogo.ico" + !define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\nsis1-uninstall.ico" + + ;Default installation folder + InstallDir "$PROGRAMFILES\NCBI\magicblast-BLAST_VERSION" + + ;Get installation folder from registry if available + InstallDirRegKey HKCU "Software\NCBI\magicblast-BLAST_VERSION" "" + +;-------------------------------- +;Interface Settings + + !define MUI_ABORTWARNING + +;-------------------------------- +;Pages + + !insertmacro MUI_PAGE_LICENSE "LICENSE" + !insertmacro MUI_PAGE_DIRECTORY + !insertmacro MUI_PAGE_INSTFILES + ;!insertmacro MUI_PAGE_FINISH + + !insertmacro MUI_UNPAGE_CONFIRM + !insertmacro MUI_UNPAGE_INSTFILES + +;-------------------------------- +;Languages + + !insertmacro MUI_LANGUAGE "English" + +;-------------------------------- +;Installer Sections + +Section "DefaultSection" SecDflt + + SetOutPath "$INSTDIR\bin" + + File "magicblast.exe" + File "ncbi-vdb-md.dll" + File "makeblastdb.exe" + File "libgcc_s_seh-1.dll" + File "libgmp-10.dll" + File "libgnutls-30.dll" + File "libhogweed-4-2.dll" + File "libnettle-6-2.dll" + File "libp11-kit-0.dll" + + SetOutPath "$INSTDIR\doc" + File "README" + Push "$INSTDIR\doc\README" + Push "$INSTDIR\doc\README.txt" + Call unix2dos + + ;Store installation folder + WriteRegStr HKCU "Software\NCBI\magicblast-BLAST_VERSION" "" $INSTDIR + + ;Create uninstaller + WriteUninstaller "$INSTDIR\Uninstall-ncbi-magicblast-BLAST_VERSION.exe" + + ;Update PATH + ${EnvVarUpdate} $0 "PATH" "P" "HKCU" "$INSTDIR\bin" + +SectionEnd + +;-------------------------------- +;Uninstaller Section + +Section "Uninstall" + Delete "$INSTDIR\Uninstall-ncbi-magicblast-BLAST_VERSION.exe" + RMDir /r "$INSTDIR" + + DeleteRegKey /ifempty HKCU "Software\NCBI\magicblast-BLAST_VERSION" + + ; Remove installation directory from PATH + ${un.EnvVarUpdate} $0 "PATH" "R" "HKCU" "$INSTDIR\bin" + +SectionEnd diff --git a/c++/scripts/projects/magicblast/post_build/win/ncbilogo.ico b/c++/scripts/projects/magicblast/post_build/win/ncbilogo.ico new file mode 100644 index 0000000000000000000000000000000000000000..247e28fe95b615c6f1d1a8e603570404fda48714 GIT binary patch literal 25214 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 or /log/srv. CXX-3423 - Add support for $NCBI_CONFIG_LOG_FILE, allow extracting SID from the token. CXX-3818 - Alow to specify posting timestamp. CXX-3933 diff --git a/c++/scripts/projects/ncbi_applog/Manifest b/c++/scripts/projects/ncbi_applog/Manifest index eb61824e..7e5b2615 100644 --- a/c++/scripts/projects/ncbi_applog/Manifest +++ b/c++/scripts/projects/ncbi_applog/Manifest @@ -1,7 +1,7 @@ # # Filename: Manifest # -# $Id: Manifest 486339 2015-12-03 15:52:01Z fukanchi $ +# $Id: Manifest 519350 2016-11-15 14:55:24Z ivanov $ # # Author: Alexey Rafanovich # @@ -15,6 +15,7 @@ APP: ncbi_applog POSTBUILD: cp $srcdir/src/misc/clog/app/ncbi_applog.cgi $installdir/bin POSTBUILD: cp $srcdir/src/misc/clog/app/test_ncbi_applog.sh $installdir/bin +POSTBUILD: cp $srcdir/src/misc/clog/app/ncbi_applog_run_app.sh $installdir/bin # The -t key prevents inclusion of the tree builder into the release # SVN_TAG_RELEASE_ADD_FLAGS: -t @@ -31,9 +32,8 @@ Linux64-Centos : plain : GCC.sh --without-debug --without-mt --with-static -- Linux64-Ubuntu : plain : GCC.sh --without-debug --with-mt --with-static --without-runpath --with-flat-makefile FreeBSD64 : plain : Clang.sh --without-debug --without-mt --with-static --without-runpath --with-flat-makefile IntelMAC : plain : GCC.sh --without-debug --without-mt --with-static --without-runpath --with-flat-makefile -Win32_13 : plain : static 32 ReleaseMT +Win64_13 : plain : static 64 ReleaseMT -#XCode : plain : Xcode.sh 30 --without-debug --with-universal=i386,x86_64 #USE_COMPONENTS # diff --git a/c++/scripts/projects/ncbi_applog/project.lst b/c++/scripts/projects/ncbi_applog/project.lst index 45ceb63e..85dc7ca3 100644 --- a/c++/scripts/projects/ncbi_applog/project.lst +++ b/c++/scripts/projects/ncbi_applog/project.lst @@ -7,3 +7,5 @@ util/xregexp$ misc$ misc/clog$ misc/clog/app$ +misc/third_party +misc/third_party_static diff --git a/c++/scripts/projects/ncbi_gui_base.lst b/c++/scripts/projects/ncbi_gui_base.lst index 6cbb1684..913ebd1b 100644 --- a/c++/scripts/projects/ncbi_gui_base.lst +++ b/c++/scripts/projects/ncbi_gui_base.lst @@ -34,6 +34,7 @@ misc/hydra_client$ misc/discrepancy$ misc/discrepancy_report$ misc/biosample_util$ +misc/data_loaders_util$ objects objmgr objtools diff --git a/c++/scripts/projects/netcache/ChangeLog b/c++/scripts/projects/netcache/ChangeLog index 04037a54..8ec5a0b8 100644 --- a/c++/scripts/projects/netcache/ChangeLog +++ b/c++/scripts/projects/netcache/ChangeLog @@ -162,5 +162,40 @@ March 01, 2016 version 6.9.5 (CXX-7908) Changed to do blob synchronization after quorum requirement is met. +June 13, 2016 +version 6.9.6 (CXX-8233) +Corrected task scheduling. + +June 17, 2016 +version 6.9.7 (CXX-8248) +Corrected periodic synchronization bugs. + +September 21, 2016 +version 6.9.8 (CXX-8613) +Fixed handling of SearchOnRead setting. + +October 13, 2016 +version 6.10.0 (CXX-8706) +Implemented server credentials configuration. +Made visible log severity configurable. +Removed unstructured information from applog. + +November 10, 2016 +version 6.11.0 (CXX-8801) +Added option to re-cache blob without prolonging its life. +Added ncbi_role info into logs. +Added option to enumerate blobs in a given cache using various metadata filters. +Corrected blob caching information. + +November 17, 2016 +version 6.11.1 (CXX-8817) +Changed blob filtering conditions. +Changed data separator in BLIST2 command output. +Changed to treat cache and key names as precise matches in BLIST2 command. + +November 21, 2016 +version 6.11.2 (CXX-8749) +Corrected blob list separator and filters. + diff --git a/c++/scripts/projects/netschedule/ChangeLog b/c++/scripts/projects/netschedule/ChangeLog index 84aae252..d6fba5a9 100644 --- a/c++/scripts/projects/netschedule/ChangeLog +++ b/c++/scripts/projects/netschedule/ChangeLog @@ -1,3 +1,42 @@ +Release 4.28.2 cloned from 4.28.1 (2016-10-31) + +Improvements: + * Extra '0' in STAT output (JIRA: CXX-8768) + + +Release 4.28.1 cloned from 4.28.0 (2016-10-26) + +Improvements: + * netschedule socket leak (JIRA: CXX-8727) + * NetSchedule: tries to write into a socket when it is already closed + (JIRA: CXX-8740) + * NetSchedule: incorrect logging of the timed out connections + (JIRA: CXX-8754) + + +Release 4.28.0 cloned from 4.27.0 (2016-10-14) + +Improvements: + * NetSchedule: new performance record Pending_Deleted (JIRA: CXX-8643) + * NS -- Allow to (re)run a job (JIRA: CXX-8694) + * NetSchedule: remove AFLS command support (JIRA: CXX-5216) + + +Release 4.27.0 cloned from 4.26.0 (2016-09-19) + +Improvements: + * NetSchedule: let prioritized affinities work together with any affinity + flag (JIRA: CXX-8587) + * NetSchedule: shutdown sockets on client close (JIRA: CXX-8286) + * NetSchedule: extend with IServer_ConnectionHandler::OnError() callback + (JIRA: CXX-8287) + * NS -- use status code 404 (NotFound) for non-existing jobs + (JIRA: CXX-8251) + * NS -- log connection ID on establishing the connection; change method of + ID creation (JIRA: CXX-8253) + * NetSchedule: not initialized member (JIRA: CXX-8359) + + Release 4.26.0 cloned from 4.25.0 (2016-05-04) Improvements: diff --git a/c++/scripts/projects/netschedule/Manifest b/c++/scripts/projects/netschedule/Manifest index 9afa218c..312c4b00 100644 --- a/c++/scripts/projects/netschedule/Manifest +++ b/c++/scripts/projects/netschedule/Manifest @@ -1,7 +1,7 @@ # # Filename: Manifest # -# $Id: Manifest 472057 2015-07-06 19:39:16Z satskyse $ +# $Id: Manifest 517704 2016-10-26 20:59:02Z satskyse $ # # Author: Sergey Satskiy # @@ -30,9 +30,10 @@ DEFAULT_CONFIGURATIONS: Linux64-Centos:Bdb6126-O2g # Release configurator assumes that this script will eventually call standard configure script and pass all options # to it. So some standard options may be added by release configurator, such as --build-root-sfx, --with-projects, # --with-distcc, --with-action etc. -Linux64-Centos : Bdb6126-Release : GCC.sh 4.8.1 --without-debug --with-mt --with-flat-makefile --with-bdb=$NCBI/BerkeleyDB-6.1.26 -Linux64-Centos : Bdb6126-Debug : GCC.sh 4.8.1 --with-debug --with-mt --with-flat-makefile --with-bdb=$NCBI/BerkeleyDB-6.1.26 -Linux64-Centos : Bdb6126-O2g : GCC.sh 4.8.1 --without-debug --with-symbols --with-mt --with-flat-makefile --with-bdb=$NCBI/BerkeleyDB-6.1.26 +Linux64-Centos : Bdb6126-Release : GCC.sh 4.8.1 --without-debug --with-mt --with-flat-makefile --with-bdb=$NCBI/BerkeleyDB-6.1.26 +Linux64-Centos : Bdb6126-Debug : GCC.sh 4.8.1 --with-debug --with-mt --with-flat-makefile --with-bdb=$NCBI/BerkeleyDB-6.1.26 +Linux64-Centos : Bdb6126-O2g : GCC.sh 4.8.1 --without-debug --with-symbols --with-mt --with-flat-makefile --with-bdb=$NCBI/BerkeleyDB-6.1.26 +Linux64-Centos7 : Bdb6126-O2g : GCC.sh 4.8.1 --without-debug --with-symbols --with-mt --with-flat-makefile --with-bdb=$NCBI/BerkeleyDB-6.1.26 USE_COMPONENTS diff --git a/c++/scripts/projects/netstorage/Manifest b/c++/scripts/projects/netstorage/Manifest index d088e1ae..2d4a4ad2 100644 --- a/c++/scripts/projects/netstorage/Manifest +++ b/c++/scripts/projects/netstorage/Manifest @@ -1,7 +1,7 @@ # # Filename: Manifest # -# $Id: Manifest 466301 2015-04-30 18:18:56Z satskyse $ +# $Id: Manifest 521097 2016-12-05 21:32:38Z fukanchi $ # # Author: Sergey Satskiy # @@ -16,6 +16,8 @@ # It is allowed to have more than one of each statements APP: netstoraged ETC: src/app/netstorage/netstoraged.ini +APP: netstorage_gc +ETC: src/app/netstorage/utils/netstorage_gc.ini DEFAULT_CONFIGURATIONS: Linux64-Centos:O2g diff --git a/c++/scripts/projects/netstorage/components.link b/c++/scripts/projects/netstorage/components.link index 50b59f24..9d27c5b5 100644 --- a/c++/scripts/projects/netstorage/components.link +++ b/c++/scripts/projects/netstorage/components.link @@ -1,6 +1,5 @@ [components] -infrastructure 17.0 -core 17.0 -dbase 17.0 -misc 17.0 - +infrastructure 18.0 +core 18.0 +dbase 18.0 +misc 18.0 diff --git a/c++/scripts/projects/netstorage/project.lst b/c++/scripts/projects/netstorage/project.lst index f1e51028..c0e52ca7 100644 --- a/c++/scripts/projects/netstorage/project.lst +++ b/c++/scripts/projects/netstorage/project.lst @@ -2,7 +2,6 @@ corelib$ util$ util/regexp$ util/compress -util/fileblobstorage$ util/qparse$ util/bitset$ update-only util/cache$ update-only diff --git a/c++/scripts/projects/netstorage_gc/project.lst b/c++/scripts/projects/netstorage_gc/project.lst index b50eb094..3ae078cc 100644 --- a/c++/scripts/projects/netstorage_gc/project.lst +++ b/c++/scripts/projects/netstorage_gc/project.lst @@ -29,5 +29,14 @@ dbapi/driver/ftds64$ dbapi/driver/ftds64/impl$ dbapi/driver/ftds64/freetds dbapi/driver/ftds64/ctlib$ +dbapi/driver/ftds95$ +dbapi/driver/ftds95/freetds$ +dbapi/driver/ftds95/freetds/freetds update-only +dbapi/driver/ftds95/freetds/replacements update-only +dbapi/driver/ftds95/freetds/tds$ +dbapi/driver/ftds95/freetds/ctlib$ +dbapi/driver/ftds95/ctlib$ +dbapi/driver/ftds95/impl update-only +dbapi/driver/ftds95/freetds/replacements$ dbapi/driver/ftds-default dbapi/simple$ diff --git a/c++/scripts/projects/project_tree_builder/ChangeLog b/c++/scripts/projects/project_tree_builder/ChangeLog index 1fbac9f3..d9c85eeb 100644 --- a/c++/scripts/projects/project_tree_builder/ChangeLog +++ b/c++/scripts/projects/project_tree_builder/ChangeLog @@ -302,3 +302,11 @@ Added analysis and reporting of cyclic library dependencies. March 09, 2016 version 4.1.3, CXX-7917 Added support for VS2015 + +May 11, 2016 +version 4.1.4, CXX-8128 +Implemented library order analysis and generation. + +August 05, 2016 +version 4.1.5, CXX-8435 +Bug fixes. diff --git a/c++/scripts/projects/project_tree_builder/Manifest b/c++/scripts/projects/project_tree_builder/Manifest index 29b59ee1..050db130 100644 --- a/c++/scripts/projects/project_tree_builder/Manifest +++ b/c++/scripts/projects/project_tree_builder/Manifest @@ -1,7 +1,7 @@ # # Filename: Manifest # -# $Id: Manifest 486339 2015-12-03 15:52:01Z fukanchi $ +# $Id: Manifest 508788 2016-08-01 16:12:18Z fukanchi $ # # Author: Sergey Satskiy # @@ -35,11 +35,10 @@ Linux64-Ubuntu : plain : GCC.sh --without-debug --without-mt --with FreeBSD64 : plain : Clang.sh --without-debug --without-mt --with-static --without-runpath --with-flat-makefile --without-ncbi-c --without-pcre IntelMAC : plain : GCC.sh --without-debug --without-mt --with-static --without-runpath --with-flat-makefile --without-ncbi-c -#IntelMAC : universal : GCC.sh --without-debug --without-mt --with-static --with-universal=i386,x86_64 --with-flat-makefile --without-ncbi-c Win32_13 : msvc-13-static-32 : static 32 ReleaseMT -XCode : plain : Xcode.sh 30 --without-debug --with-universal=i386,x86_64 --without-ncbi-c +XCode : plain : Xcode.sh 30 --without-debug --without-ncbi-c USE_COMPONENTS diff --git a/c++/scripts/projects/public/Manifest b/c++/scripts/projects/public/Manifest index aed31426..07a94854 100644 --- a/c++/scripts/projects/public/Manifest +++ b/c++/scripts/projects/public/Manifest @@ -1,7 +1,7 @@ # # Filename: Manifest # -# $Id: Manifest 500492 2016-05-04 22:25:11Z fukanchi $ +# $Id: Manifest 521307 2016-12-07 18:54:25Z fukanchi $ # # Author: # @@ -24,22 +24,23 @@ TAG_PRE_COMMIT: tagprecommit/use_embedded_ptb.py Win32_13 : MSVC13-32 : dll 32 ReleaseDLL Win64_13 : MSVC13-64 : static 64 ReleaseDLL -Cygwin64 : GCC : GCC.sh --without-debug --with-mt --with-flat-makefile +Cygwin64 : GCC : GCC.sh --without-debug --with-mt --with-flat-makefile --without-ncbi-c -Linux64-Centos : GCC481 : GCC.sh 4.8.1 --without-debug --without-flat-makefile -Linux64-Centos : GCC493d : GCC.sh 4.9.3 --with-debug --with-mt --with-flat-makefile -Linux64-Centos : GCC510 : GCC.sh 5.1.0 --without-debug --with-mt --with-flat-makefile -Linux64-Centos : GCC530 : GCC.sh 5.3.0 --without-debug --with-mt --with-flat-makefile -Linux64-Centos : ICC150 : ICC.sh 15.0 --without-debug --with-mt --with-dll -Linux64-Centos : ICC150d : ICC.sh 15.0 --with-debug --with-mt --with-3psw=system -Linux64-Centos7 : Clang : Clang.sh 3.8.0 --with-debug --with-mt --with-flat-makefile +Linux64-Centos : GCC481 : GCC.sh 4.8.1 --without-debug --without-flat-makefile --without-ncbi-c +Linux64-Centos : GCC493d : GCC.sh 4.9.3 --with-debug --with-mt --with-flat-makefile --without-ncbi-c +Linux64-Centos : GCC510 : GCC.sh 5.1.0 --without-debug --with-mt --with-flat-makefile --without-ncbi-c +Linux64-Centos : GCC530 : GCC.sh 5.3.0 --without-debug --with-mt --with-flat-makefile --without-ncbi-c +Linux64-Centos : ICC150 : ICC.sh 15.0 --without-debug --with-mt --with-dll --with-runpath --without-ncbi-c +Linux64-Centos : ICC150d : ICC.sh 15.0 --with-debug --with-mt --with-3psw=system --with-runpath --without-ncbi-c +Linux64-Centos7 : Clang : Clang.sh 3.8.0 --with-debug --with-mt --with-flat-makefile --without-ncbi-c -Linux64-Ubuntu : plain-GCC : GCC.sh --without-debug --with-mt --with-flat-makefile -Linux32-Ubuntu : plain-GCC : GCC.sh --without-debug --with-mt --with-flat-makefile +Linux64-Ubuntu : plain-GCC : GCC.sh --without-debug --with-mt --with-flat-makefile --without-ncbi-c +Linux32-Ubuntu : plain-GCC : GCC.sh --without-debug --with-mt --with-flat-makefile --without-ncbi-c -FreeBSD64 : plain : Clang.sh --without-debug --with-mt --with-flat-makefile +FreeBSD64 : plain : Clang.sh --without-debug --with-mt --with-flat-makefile --with-runpath --without-ncbi-c -IntelMAC : Debug : GCC.sh --with-debug --with-dll --with-mt --with-universal=i386,x86_64 --with-flat-makefile -IntelMAC : Release : GCC.sh --without-debug --with-dll --with-mt --with-universal=i386,x86_64 --with-flat-makefile +IntelMAC : Debug : GCC.sh --with-debug --with-dll --with-mt --with-flat-makefile --without-gcrypt --without-mysql --without-pcre --without-ncbi-c +IntelMAC : Release : GCC.sh --without-debug --with-dll --with-mt --with-flat-makefile --without-gcrypt --without-mysql --without-pcre --without-ncbi-c + +XCode : plain : Xcode.sh 30 --without-debug --with-64 --without-ncbi-c -XCode : plain : Xcode.sh 30 --without-debug --with-64 diff --git a/c++/scripts/projects/public/components.link b/c++/scripts/projects/public/components.link index 60b57d04..078e2e7c 100644 --- a/c++/scripts/projects/public/components.link +++ b/c++/scripts/projects/public/components.link @@ -1,12 +1,13 @@ [components] -algo 17.0 -app 17.0 -core 17.0 -dbase 17.0 -infrastructure 17.0 -misc 17.0 -objects 17.0 -objtools 17.0 -sample 17.0 -sra 17.0 -web 17.0 +algo 18.0 +app 18.0 +core 18.0 +dbase 18.0 +infrastructure 18.0 +misc 18.0 +objects 18.0 +objtools 18.0 +sample 18.0 +sra 18.0 +web 18.0 + diff --git a/c++/scripts/projects/python_ncbi_dbapi/ChangeLog b/c++/scripts/projects/python_ncbi_dbapi/ChangeLog index 4eceb852..736734e0 100644 --- a/c++/scripts/projects/python_ncbi_dbapi/ChangeLog +++ b/c++/scripts/projects/python_ncbi_dbapi/ChangeLog @@ -1,3 +1,11 @@ +Version 1.18.0 (2016-10-13): +* Advance to version 18.0 of the stable C++ Toolkit components, with + ftds95 as default ftds and support for contacting dispd over HTTPS. + +Version 1.17.0 (2016-06-23): +* Advance to version 17.0 of the stable C++ Toolkit components, complete + with an ftds95 driver in addition to ftds(64). + Version 1.16.1 (2016-01-15): * Cover Python 3.4 in addition to 2.7. diff --git a/c++/scripts/projects/python_ncbi_dbapi/components.link b/c++/scripts/projects/python_ncbi_dbapi/components.link index b1e583c1..33d657df 100644 --- a/c++/scripts/projects/python_ncbi_dbapi/components.link +++ b/c++/scripts/projects/python_ncbi_dbapi/components.link @@ -1,4 +1,4 @@ [components] -infrastructure 16.1 -core 16.1 -dbase 16.1 +infrastructure 18.0 +core 18.0 +dbase 18.0 diff --git a/c++/scripts/projects/python_ncbi_dbapi/project.lst b/c++/scripts/projects/python_ncbi_dbapi/project.lst index 5d5fd666..6af5f98d 100644 --- a/c++/scripts/projects/python_ncbi_dbapi/project.lst +++ b/c++/scripts/projects/python_ncbi_dbapi/project.lst @@ -13,10 +13,20 @@ dbapi/driver/odbc/unix_odbc$ update-only dbapi/driver/ctlib$ dbapi/driver/dblib$ dbapi/driver/ftds64$ +dbapi/driver/ftds64/impl$ update-only dbapi/driver/ftds64/freetds$ dbapi/driver/ftds64/freetds/tds$ dbapi/driver/ftds64/freetds/replacements$ dbapi/driver/ftds64/freetds/ctlib$ dbapi/driver/ftds64/ctlib$ +dbapi/driver/ftds95$ +dbapi/driver/ftds95/impl$ update-only +dbapi/driver/ftds95/freetds$ +dbapi/driver/ftds95/freetds/freetds$ update-only +dbapi/driver/ftds95/freetds/tds$ +dbapi/driver/ftds95/freetds/replacements$ +dbapi/driver/ftds95/freetds/ctlib$ +dbapi/driver/ftds95/ctlib$ +dbapi/driver/ftds-default$ dbapi/lang_bind$ dbapi/lang_bind/python diff --git a/c++/scripts/projects/rmblastn/Manifest b/c++/scripts/projects/rmblastn/Manifest index f528d2ab..508bdf23 100644 --- a/c++/scripts/projects/rmblastn/Manifest +++ b/c++/scripts/projects/rmblastn/Manifest @@ -1,7 +1,7 @@ # # Filename: Manifest # -# $Id: Manifest 483955 2015-11-05 15:16:36Z fukanchi $ +# $Id: Manifest 508788 2016-08-01 16:12:18Z fukanchi $ # # Author: Christiam Camacho # @@ -38,6 +38,6 @@ DEFAULT_CONFIGURE_FLAGS: --without-debug --with-strip --with-mt --with-build-roo Win32_13 : plain : static 32 ReleaseMT Win64_13 : plain : static 64 ReleaseMT -IntelMAC : universal : GCC.sh 4.0 --without-debug --without-pcre --with-mt --with-flat-makefile --with-universal=i386,x86_64 --with-ncbi-public +IntelMAC : plain : GCC.sh 4.0 --without-debug --without-pcre --with-mt --with-flat-makefile --with-ncbi-public USE_COMPONENTS diff --git a/c++/scripts/projects/testres-kernel/ChangeLog b/c++/scripts/projects/testres-kernel/ChangeLog index 36905c3a..2b3bc8d3 100644 --- a/c++/scripts/projects/testres-kernel/ChangeLog +++ b/c++/scripts/projects/testres-kernel/ChangeLog @@ -1,4 +1,3 @@ -Oct 21, 2013 -First release -Jun 2, 2015 -Version 1.3.0. Multiple bugfixes, improvements +Oct 21, 2013 First release +Jun 2, 2015 Version 1.3.0 Multiple bugfixes, improvements +Dec 1, 2016 Version 1.3.4 less resource hogging, new test modules, https transition, bugfixes diff --git a/c++/scripts/projects/testres-kernel/Manifest b/c++/scripts/projects/testres-kernel/Manifest index 58b21081..52a489cd 100644 --- a/c++/scripts/projects/testres-kernel/Manifest +++ b/c++/scripts/projects/testres-kernel/Manifest @@ -1,7 +1,7 @@ # # Filename: Manifest # -# $Id: Manifest 481816 2015-10-15 22:41:22Z fukanchi $ +# $Id: Manifest 520935 2016-12-02 23:17:37Z zakharov $ # # Author: Mikhail Zakharov (template by Sergey Satskiy) # @@ -21,7 +21,10 @@ POSTBUILD: $packagedir/copy_modules.py $srcdir $bindir $installdir #ini file COPY: $srcdir/src/internal/cppcore/testres/kernel/testres_kernel.ini $installdir/bin -Linux64-Centos : GCC481 : GCC.sh 4.8.1 --without-debug --with-mt --with-static --without-runpath --with-flat-makefile --without-ncbi-c +Linux64-Centos : O2g : GCC.sh 4.9.3 --without-debug --with-symbols --with-mt --with-static --without-runpath --with-flat-makefile --without-ncbi-c + +Linux64-Centos : dbg : GCC.sh 4.9.3 --with-debug --with-symbols --with-mt --with-static --without-runpath --with-flat-makefile --without-ncbi-c +Linux64-Centos : O2 : GCC.sh 4.9.3 --without-debug --with-mt --with-static --without-runpath --with-flat-makefile --without-ncbi-c diff --git a/c++/scripts/projects/testres-kernel/components.link b/c++/scripts/projects/testres-kernel/components.link index bbb94f0d..99d5fc81 100644 --- a/c++/scripts/projects/testres-kernel/components.link +++ b/c++/scripts/projects/testres-kernel/components.link @@ -1,6 +1,6 @@ [components] #infrastructure 16.1 #core 16.1 -web 16.1 -misc 16.1 -app 16.1 +web 18.0 +misc 18.0 +app 18.0 diff --git a/c++/scripts/projects/testres-scheduler/ChangeLog b/c++/scripts/projects/testres-scheduler/ChangeLog index 5841b7b7..3a84301e 100644 --- a/c++/scripts/projects/testres-scheduler/ChangeLog +++ b/c++/scripts/projects/testres-scheduler/ChangeLog @@ -2,3 +2,6 @@ Oct 21, 2013 First release Jun 2, 2015 Release 1.3.0, Multiple bugfixes, performance improvements +Dec 1, 2016 +Release 1.3.4, make Netcache communications more efficient, multiple kernel +management diff --git a/c++/scripts/projects/testres-scheduler/Manifest b/c++/scripts/projects/testres-scheduler/Manifest index b101bf56..d73148fd 100644 --- a/c++/scripts/projects/testres-scheduler/Manifest +++ b/c++/scripts/projects/testres-scheduler/Manifest @@ -1,7 +1,7 @@ # # Filename: Manifest # -# $Id: Manifest 432272 2014-04-10 20:51:27Z zakharov $ +# $Id: Manifest 520936 2016-12-02 23:17:48Z zakharov $ # # Author: Mikhail Zakharov (template by Sergey Satskiy) # @@ -22,6 +22,8 @@ COPY: $srcdir/src/internal/cppcore/testres/web/presenters/ $installdir #ini file COPY: $srcdir/src/internal/cppcore/testres/scheduler/testres_scheduler.ini $installdir/bin -Linux64-Centos : plain : GCC.sh --without-debug --with-mt --with-static --without-runpath --with-flat-makefile --without-ncbi-c +Linux64-Centos : O2g : GCC.sh 4.9.3 --without-debug --with-symbols --with-mt --with-static --without-runpath --with-flat-makefile --without-ncbi-c +Linux64-Centos : dbg : GCC.sh 4.9.3 --with-debug --with-symbols --with-mt --with-static --without-runpath --with-flat-makefile --without-ncbi-c +Linux64-Centos : O2 : GCC.sh 4.9.3 --without-debug --with-mt --with-static --without-runpath --with-flat-makefile --without-ncbi-c diff --git a/c++/scripts/projects/testres-scheduler/components.link b/c++/scripts/projects/testres-scheduler/components.link index bbb94f0d..99d5fc81 100644 --- a/c++/scripts/projects/testres-scheduler/components.link +++ b/c++/scripts/projects/testres-scheduler/components.link @@ -1,6 +1,6 @@ [components] #infrastructure 16.1 #core 16.1 -web 16.1 -misc 16.1 -app 16.1 +web 18.0 +misc 18.0 +app 18.0 diff --git a/c++/scripts/projects/xmlwrapp/Manifest b/c++/scripts/projects/xmlwrapp/Manifest index 2d8df7fa..0635797e 100644 --- a/c++/scripts/projects/xmlwrapp/Manifest +++ b/c++/scripts/projects/xmlwrapp/Manifest @@ -1,7 +1,7 @@ # # Filename: Manifest # -# $Id: Manifest 491986 2016-02-10 22:03:08Z fukanchi $ +# $Id: Manifest 517162 2016-10-20 22:47:37Z fukanchi $ # # Author: Sergey Satskiy # @@ -31,24 +31,26 @@ FreeBSD64 : plain : Clang.sh --without-debug --with-mt Linux64-Centos : plain-GCC : GCC.sh --without-debug --with-mt --without-runpath --with-flat-makefile Linux64-Centos : GCC-nomt : GCC.sh --without-debug --without-mt --without-runpath --with-flat-makefile -Linux64-Centos : ICC-13 : ICC.sh 13.0 --without-debug --with-mt --without-runpath --with-flat-makefile -Linux64-Centos : ICC-135 : ICC.sh 13.5 --without-debug --with-mt --without-runpath --with-flat-makefile -Linux64-Centos : ICC-15 : ICC.sh 15.0 --without-debug --with-mt --without-runpath --with-flat-makefile -Linux64-Centos : plain-ICC : ICC.sh --without-debug --with-mt --without-runpath --with-flat-makefile +Linux64-Centos : ICC-13 : ICC.sh 13.0 --without-debug --with-mt --without-runpath --with-flat-makefile +Linux64-Centos : ICC-135 : ICC.sh 13.5 --without-debug --with-mt --without-runpath --with-flat-makefile +Linux64-Centos : ICC-15 : ICC.sh 15.0 --without-debug --with-mt --without-runpath --with-flat-makefile +Linux64-Centos : plain-ICC : ICC.sh --without-debug --with-mt --without-runpath --with-flat-makefile Linux64-Ubuntu : plain-GCC : GCC.sh --without-debug --with-mt --without-runpath --with-flat-makefile Linux32-Ubuntu : plain-GCC : GCC.sh --without-debug --with-mt --without-runpath --with-flat-makefile Cygwin64 : GCC : GCC.sh --without-debug --with-mt --without-runpath --with-flat-makefile -IntelMAC : GCC-universal : GCC.sh --without-debug --with-mt --without-runpath --with-flat-makefile --with-universal=i386,x86_64 --with-3psw=system:netopt --without-ncbi-public +IntelMAC : plain : GCC.sh --without-debug --with-mt --without-runpath --with-flat-makefile --with-3psw=system:netopt --without-ncbi-public IntelMAC : GCC : GCC.sh --without-debug --with-mt --without-runpath --with-flat-makefile -Win32_13 : 13-static-32 : static 32 ReleaseDLL +Win64_13 : 13-debug-64 : static 64 DebugDLL Win64_13 : 13-static-64 : static 64 ReleaseDLL XCode : plain : Xcode.sh 30 -IntelMAC-Clang36 : clang : Clang.sh --without-debug --with-mt --without-runpath --with-flat-makefile --with-universal=i386,x86_64 --with-3psw=system:netopt --without-ncbi-public +IntelMAC-Clang36 : clang : Clang.sh --without-debug --with-mt --without-runpath --with-flat-makefile --with-3psw=system:netopt --without-ncbi-public + +Linux64-Centos7 : Release : GCC.sh --without-debug --with-mt --without-runpath --with-flat-makefile diff --git a/c++/src/Makefile.in b/c++/src/Makefile.in index 86fd134a..f44cbac1 100644 --- a/c++/src/Makefile.in +++ b/c++/src/Makefile.in @@ -1,4 +1,4 @@ -# $Id: Makefile.in 500618 2016-05-05 19:15:27Z blastadm $ +# $Id: Makefile.in 521318 2016-12-07 19:37:59Z blastadm $ # Master (top-level) makefile for all NCBI C++ projects ################################################################## diff --git a/c++/src/algo/blast/Makefile.blast_macros.mk b/c++/src/algo/blast/Makefile.blast_macros.mk index d9ca4a33..7870c5ec 100644 --- a/c++/src/algo/blast/Makefile.blast_macros.mk +++ b/c++/src/algo/blast/Makefile.blast_macros.mk @@ -1,5 +1,5 @@ ################################# -# $Id: Makefile.blast_macros.mk 457267 2015-01-21 19:46:09Z boratyng $ +# $Id: Makefile.blast_macros.mk 499473 2016-04-26 14:40:22Z camacho $ # This file contains macro definitions for using libraries maintained by the # BLAST TEAM # Author: Christiam Camacho (camacho@ncbi.nlm.nih.gov) @@ -10,7 +10,7 @@ BLAST_FORMATTER_MINIMAL_LIBS = xblastformat align_format taxon1 blastdb_format \ gene_info $(XFORMAT_LIBS) xalnmgr blastxml blastxml2 xcgi xhtml # BLAST_FORMATTER_LIBS = $(BLAST_FORMATTER_MINIMAL_LIBS) BLAST_FORMATTER_LIBS = $(BLAST_INPUT_LIBS) -BLAST_DB_DATA_LOADER_LIBS = ncbi_xloader_blastdb ncbi_xloader_blastdb_rmt +BLAST_DB_DATA_LOADER_LIBS = ncbi_xloader_blastdb_rmt ncbi_xloader_blastdb BLAST_INPUT_LIBS = blastinput \ $(BLAST_DB_DATA_LOADER_LIBS) $(BLAST_FORMATTER_MINIMAL_LIBS) @@ -19,6 +19,6 @@ BLAST_SRA_LIBS=blast_sra $(SRAXF_LIBS) vxf $(SRA_LIBS) # BLAST_FORMATTER_LIBS and BLAST_INPUT_LIBS need $BLAST_LIBS BLAST_LIBS = xblast xalgoblastdbindex composition_adjustment \ - xalgodustmask xalgowinmask seqmasks_io seqdb blast_services xobjutil \ - $(OBJREAD_LIBS) xnetblastcli xnetblast blastdb scoremat tables xalnmgr + xalgodustmask xalgowinmask seqmasks_io seqdb blast_services xalnmgr \ + xobjutil $(OBJREAD_LIBS) xnetblastcli xnetblast blastdb scoremat tables # BLAST additionally needs xconnect $(SOBJMGR_LIBS) or $(OBJMGR_LIBS) diff --git a/c++/src/algo/blast/Makefile.in b/c++/src/algo/blast/Makefile.in index 14e720d3..054e7569 100644 --- a/c++/src/algo/blast/Makefile.in +++ b/c++/src/algo/blast/Makefile.in @@ -1,10 +1,10 @@ -# $Id: Makefile.in 319820 2011-07-25 20:22:28Z maning $ +# $Id: Makefile.in 507884 2016-07-22 02:13:25Z ucko $ # Meta-makefile ("BLAST" project) ################################# -SUB_PROJ = composition_adjustment core dbindex dbindex_search api format blastinput \ - igblast gumbel_params unit_tests +SUB_PROJ = composition_adjustment core dbindex dbindex_search api format \ + blastinput blast_sra_input igblast gumbel_params unit_tests WATCHERS = camacho madden diff --git a/c++/src/algo/blast/api/Makefile.xblast.lib b/c++/src/algo/blast/api/Makefile.xblast.lib index 18108c14..52c95d77 100644 --- a/c++/src/algo/blast/api/Makefile.xblast.lib +++ b/c++/src/algo/blast/api/Makefile.xblast.lib @@ -1,4 +1,4 @@ -# $Id: Makefile.xblast.lib 427427 2014-02-20 13:40:13Z gouriano $ +# $Id: Makefile.xblast.lib 504861 2016-06-20 15:45:40Z boratyng $ include $(srcdir)/../core/Makefile.blast.lib @@ -72,7 +72,9 @@ rpsblast_local \ seedtop \ cdd_pssm_input \ deltablast_options \ -deltablast +deltablast \ +magicblast_options \ +magicblast SRC = $(SRC_C:%=.core_%) $(SRC_CXX) diff --git a/c++/src/algo/blast/api/bioseq_extract_data_priv.cpp b/c++/src/algo/blast/api/bioseq_extract_data_priv.cpp index 6a7e63a0..baa24f5c 100644 --- a/c++/src/algo/blast/api/bioseq_extract_data_priv.cpp +++ b/c++/src/algo/blast/api/bioseq_extract_data_priv.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: bioseq_extract_data_priv.cpp 144802 2008-11-03 20:57:20Z camacho $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * @@ -56,6 +52,9 @@ static char const rcsid[] = #include #include #include +#include // for has_pair +#include +#include // Private BLAST API headers #include "blast_setup.hpp" @@ -372,6 +371,50 @@ CBlastQuerySourceBioseqSet::GetTitle(int index) const return retval; } +bool +CBlastQuerySourceBioseqSet::IsFirstOfAPair(int index) const +{ + return GetSegmentInfo(index) == eFirstSegment; +} + + +int +CBlastQuerySourceBioseqSet::GetSegmentInfo(int index) const +{ + // FIXME: this is a hack, a better field in Bioseq may be needed to store + // this information + CConstRef bioseq = m_Bioseqs[index]; + int retval = 0; + if (!bioseq->CanGetDescr()) { + return retval; + } + const CSeq_descr::Tdata& descr = bioseq->GetDescr().Get(); + ITERATE(CSeq_descr::Tdata, desc, descr) { + if ((*desc)->Which() == CSeqdesc::e_User) { + + if (!(*desc)->GetUser().IsSetType() || + !(*desc)->GetUser().GetType().IsStr() || + (*desc)->GetUser().GetType().GetStr() != "Mapping") { + continue; + } + + if (!(*desc)->GetUser().HasField("has_pair")) { + break; + } + + const CUser_field& field = (*desc)->GetUser().GetField("has_pair"); + if (!field.GetData().IsInt()) { + break; + } + + retval = field.GetData().GetInt(); + } + } + + return retval; +} + + void CBlastQuerySourceBioseqSet::x_BioseqSanityCheck(const objects::CBioseq& bs) { diff --git a/c++/src/algo/blast/api/bioseq_extract_data_priv.hpp b/c++/src/algo/blast/api/bioseq_extract_data_priv.hpp index b7fd3810..35364bd7 100644 --- a/c++/src/algo/blast/api/bioseq_extract_data_priv.hpp +++ b/c++/src/algo/blast/api/bioseq_extract_data_priv.hpp @@ -1,4 +1,4 @@ -/* $Id: bioseq_extract_data_priv.hpp 144802 2008-11-03 20:57:20Z camacho $ +/* $Id: bioseq_extract_data_priv.hpp 517499 2016-10-25 17:20:41Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -179,6 +179,13 @@ public: /// @param index index of the sequence in the sequence container [in] virtual string GetTitle(int index) const; + /// Is this sequence followed by a mate (for mapping short reads) + NCBI_DEPRECATED virtual bool IsFirstOfAPair(int index) const; + + /// Get segment information (for mapping paired short reads) + virtual int GetSegmentInfo(int index) const; + + private: /// True if the data contained in this object is protein bool m_IsProt; diff --git a/c++/src/algo/blast/api/blast_aux.cpp b/c++/src/algo/blast/api/blast_aux.cpp index 1d740832..956d0b99 100644 --- a/c++/src/algo/blast/api/blast_aux.cpp +++ b/c++/src/algo/blast/api/blast_aux.cpp @@ -1,4 +1,4 @@ -/* $Id: blast_aux.cpp 437219 2014-06-04 13:04:32Z camacho $ +/* $Id: blast_aux.cpp 509279 2016-08-04 16:02:34Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -53,6 +53,11 @@ #include "blast_setup.hpp" #include "blast_aux_priv.hpp" +#include +#include +#include +#include + #include #include @@ -686,6 +691,7 @@ string EProgramToTaskName(EProgram p) case ePHIBlastn: retval.assign("phiblastn"); break; case eDeltaBlast: retval.assign("deltablast"); break; case eVecScreen: retval.assign("vecscreen"); break; + case eMapper: retval.assign("mapr2g"); break; default: cerr << "Invalid EProgram value: " << (int)p << endl; abort(); @@ -707,6 +713,9 @@ EProgramToEBlastProgramType(EProgram p) case eDiscMegablast: case eVecScreen: return eBlastTypeBlastn; + + case eMapper: + return eBlastTypeMapping; case eBlastp: return eBlastTypeBlastp; @@ -784,6 +793,16 @@ EProgram ProgramNameToEnum(const std::string& program_name) return eDeltaBlast; } else if (lowercase_program_name == "vecscreen") { return eVecScreen; + // FIXME: mapper is used in core as a single program name for all tasks, + // we may need a better approach to mapping tasks with fewer program names + } else if (lowercase_program_name == "mapper") { + return eMapper; + } else if (lowercase_program_name == "mapr2g") { + return eMapper; + } else if (lowercase_program_name == "mapr2r") { + return eMapper; + } else if (lowercase_program_name == "mapg2g") { + return eMapper; } else { NCBI_THROW(CBlastException, eNotSupported, "Program type '" + program_name + "' not supported"); @@ -898,7 +917,7 @@ Blast_GetSeqLocInfoVector(EBlastProgramType program, NCBI_THROW(CBlastException, eInvalidArgument, msg); } - if (program == eBlastTypeBlastn) { + if (program == eBlastTypeBlastn || program == eBlastTypeMapping) { s_ConvertBlastnMasks(query_intervals, mask, mask_v); return; } @@ -1087,6 +1106,51 @@ IsLocalId(const objects::CSeq_id* seqid) return retval; } +void +LoadSequencesToScope(CScope::TIds& ids, vector& ranges, CRef & scope) +{ + CScope::TBioseqHandles bhs = scope->GetBioseqHandles(ids); + + // Per Eugene Vasilchenko's suggestion, via email on 6/8/10: + // "With the current API you can make artificial delta sequence + // referencing several other sequences and use its CSeqMap to load them + // all in one call. There is no straightforward way to do this, sorry." + + // Create virtual delta sequence + CRef top_seq(new CBioseq); + CSeq_inst& inst = top_seq->SetInst(); + inst.SetRepr(CSeq_inst::eRepr_virtual); + inst.SetMol(CSeq_inst::eMol_not_set); + CDelta_ext& delta = inst.SetExt().SetDelta(); + int i = 0; + ITERATE(CScope::TBioseqHandles, it, bhs) { + CRef seq(new CDelta_seq); + CSeq_interval& interval = seq->SetLoc().SetInt(); + interval.SetId(*SerialClone(*it->GetAccessSeq_id_Handle().GetSeqId())); + if (ranges[i].GetFrom() > ranges[i].GetToOpen()) { + TSeqPos length = it->GetBioseqLength(); + interval.SetFrom(length - ranges[i].GetFrom()); + interval.SetTo(length - ranges[i].GetTo()); + } else { + interval.SetFrom(ranges[i].GetFrom()); + interval.SetTo(ranges[i].GetTo()); + } + i++; + delta.Set().push_back(seq); + } + + // Add it to the scope + CBioseq_Handle top_bh = scope->AddBioseq(*top_seq); + + // prepare selector. SetLinkUsedTSE() is necessary for batch loading + SSeqMapSelector sel(CSeqMap::fFindAnyLeaf, kInvalidSeqPos); + sel.SetLinkUsedTSE(top_bh.GetTSE_Handle()); + + // and get all sequence data in batch mode + _TRACE("Fetching " << ids.size() << " sequences"); + top_bh.GetSeqMap().CanResolveRange(&*scope, sel); +} + END_SCOPE(blast) END_NCBI_SCOPE diff --git a/c++/src/algo/blast/api/blast_aux_priv.cpp b/c++/src/algo/blast/api/blast_aux_priv.cpp index d2382cb4..8e4be3e1 100644 --- a/c++/src/algo/blast/api/blast_aux_priv.cpp +++ b/c++/src/algo/blast/api/blast_aux_priv.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_aux_priv.cpp 443924 2014-08-20 15:03:37Z fongah2 $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * @@ -173,11 +169,12 @@ BlastSetupPreliminarySearchEx(CRef qf, // 4. Create the BlastScoreBlk BlastSeqLoc* lookup_segments = NULL; BlastScoreBlk* sbp = NULL; + bool is_mapper = (options->GetProgram() == eMapper); try { sbp = CSetupFactory::CreateScoreBlock(opts_memento.get(), query_data, &lookup_segments, retval->m_Messages, - &retval->m_Masks, + (is_mapper ? NULL : &retval->m_Masks), retval->m_InternalData->m_RpsData); } catch (CBlastException & e) { const string kCatchThisError (kBlastErrMsg_CantCalculateUngappedKAParams); @@ -229,6 +226,7 @@ BlastSetupPreliminarySearchEx(CRef qf, CSetupFactory::CreateHspStream(opts_memento.get(), query_data->GetNumQueries(), CSetupFactory::CreateHspWriter(opts_memento.get(), + retval->m_InternalData->m_Queries, query_data->GetQueryInfo())); if (is_multi_threaded) diff --git a/c++/src/algo/blast/api/blast_mtlock.cpp b/c++/src/algo/blast/api/blast_mtlock.cpp index bedea6e0..286e89d8 100644 --- a/c++/src/algo/blast/api/blast_mtlock.cpp +++ b/c++/src/algo/blast/api/blast_mtlock.cpp @@ -1,4 +1,4 @@ -/* $Id: blast_mtlock.cpp 103491 2007-05-04 17:18:18Z kazimird $ +/* $Id: blast_mtlock.cpp 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -31,11 +31,6 @@ * Initialization for the mutex locking interface. */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_mtlock.cpp 103491 2007-05-04 17:18:18Z kazimird $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include diff --git a/c++/src/algo/blast/api/blast_nucl_options.cpp b/c++/src/algo/blast/api/blast_nucl_options.cpp index 2d1f83a5..c3754b28 100644 --- a/c++/src/algo/blast/api/blast_nucl_options.cpp +++ b/c++/src/algo/blast/api/blast_nucl_options.cpp @@ -1,4 +1,4 @@ -/* $Id: blast_nucl_options.cpp 456407 2015-01-12 15:47:18Z fongah2 $ +/* $Id: blast_nucl_options.cpp 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -139,6 +139,7 @@ CBlastNucleotideOptionsHandle::SetLookupTableDefaults() SetLookupTableType(eNaLookupTable); SetWordSize(BLAST_WORDSIZE_NUCL); m_Opts->SetWordThreshold(BLAST_WORD_THRESHOLD_BLASTN); + m_Opts->SetLookupTableStride(0); } void @@ -147,6 +148,7 @@ CBlastNucleotideOptionsHandle::SetMBLookupTableDefaults() SetLookupTableType(eMBLookupTable); SetWordSize(BLAST_WORDSIZE_MEGABLAST); m_Opts->SetWordThreshold(BLAST_WORD_THRESHOLD_MEGABLAST); + m_Opts->SetLookupTableStride(0); } void diff --git a/c++/src/algo/blast/api/blast_objmgr_priv.hpp b/c++/src/algo/blast/api/blast_objmgr_priv.hpp index 9a714450..d0b7f0c9 100644 --- a/c++/src/algo/blast/api/blast_objmgr_priv.hpp +++ b/c++/src/algo/blast/api/blast_objmgr_priv.hpp @@ -1,4 +1,4 @@ -/* $Id: blast_objmgr_priv.hpp 151315 2009-02-03 18:13:26Z camacho $ +/* $Id: blast_objmgr_priv.hpp 517499 2016-10-25 17:20:41Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -149,6 +149,17 @@ public: /// Return the title of a sequence /// @param index index of the sequence in the sequence container [in] virtual string GetTitle(int index) const; + + /// Is this sequence followed by a mate (for mapping short reads) + NCBI_DEPRECATED virtual bool IsFirstOfAPair(int index) const + { NCBI_THROW(CException, eInvalid, "Function " + "CBlasyQuerySourceOM::IsFirstOfAPair was not implemented");} + + /// Get segment information (for mapping paired short reads) + virtual int GetSegmentInfo(int index) const + { NCBI_THROW(CException, eInvalid, "Function " + "CBlasyQuerySourceOM::GetSegmentInfo was not implemented");} + protected: /// Reference to input CBlastQueryVector (or empty if not used) diff --git a/c++/src/algo/blast/api/blast_objmgr_tools.cpp b/c++/src/algo/blast/api/blast_objmgr_tools.cpp index 200f2165..45f84d11 100644 --- a/c++/src/algo/blast/api/blast_objmgr_tools.cpp +++ b/c++/src/algo/blast/api/blast_objmgr_tools.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_objmgr_tools.cpp 495292 2016-03-16 14:52:49Z ivanov $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * diff --git a/c++/src/algo/blast/api/blast_options_builder.cpp b/c++/src/algo/blast/api/blast_options_builder.cpp index 97b701aa..e80995b6 100644 --- a/c++/src/algo/blast/api/blast_options_builder.cpp +++ b/c++/src/algo/blast/api/blast_options_builder.cpp @@ -1,4 +1,4 @@ -/* $Id: blast_options_builder.cpp 482563 2015-10-23 20:19:28Z fongah2 $ +/* $Id: blast_options_builder.cpp 513039 2016-09-06 19:42:59Z fukanchi $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -109,6 +109,9 @@ CBlastOptionsBuilder::ComputeProgram(const string & program, p = "psitblastn"; found = true; } + if ((s == "sra") || (s == "wgs")) { + found = true; + } } else if (p == "tblastx") { found = true; } else if (p == "blastx") { @@ -258,7 +261,17 @@ x_ProcessOneOption(CBlastOptionsHandle & opts, } m_GiList = gi_list; #elif defined(NCBI_INT8_GI) - m_GiList = v.GetBig_integer_list(); + if(v.IsBig_integer_list()) { + m_GiList = v.GetBig_integer_list(); + } + else { + const list& int_list = v.GetInteger_list(); + list gi_list; + ITERATE ( list, it, int_list ) { + gi_list.push_back(GI_FROM(int, *it)); + } + m_GiList = gi_list; + } #else m_GiList = v.GetInteger_list(); #endif @@ -364,7 +377,17 @@ x_ProcessOneOption(CBlastOptionsHandle & opts, } m_NegativeGiList = gi_list; #elif defined(NCBI_INT8_GI) - m_NegativeGiList = v.GetBig_integer_list(); + if (v.IsBig_integer_list()) { + m_NegativeGiList = v.GetBig_integer_list(); + } + else { + const list& int_list = v.GetInteger_list(); + list gi_list; + ITERATE ( list, it, int_list ) { + gi_list.push_back(GI_FROM(int, *it)); + } + m_NegativeGiList = gi_list; + } #else m_NegativeGiList = v.GetInteger_list(); #endif diff --git a/c++/src/algo/blast/api/blast_options_cxx.cpp b/c++/src/algo/blast/api/blast_options_cxx.cpp index e6bf3a1b..2f9f845f 100644 --- a/c++/src/algo/blast/api/blast_options_cxx.cpp +++ b/c++/src/algo/blast/api/blast_options_cxx.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_options_cxx.cpp 456407 2015-01-12 15:47:18Z fongah2 $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * @@ -919,6 +915,37 @@ CBlastOptions::SetWordSize(int ws) } } +Uint4 CBlastOptions::GetLookupTableStride() const +{ + if (!m_Local) { + x_Throwx("Error: GetLookupTableStride not available."); + } + return m_Local->GetLookupTableStride(); +} +void CBlastOptions::SetLookupTableStride(Uint4 val) +{ + if (!m_Local) { + x_Throwx("Error: SetLookupTableStride not available."); + } + m_Local->SetLookupTableStride(val); +} + +bool CBlastOptions::GetLookupDbFilter() const +{ + if (!m_Local) { + x_Throwx("Error: GetLookupDbFilter not available."); + } + return m_Local->GetLookupDbFilter(); +} + +void CBlastOptions::SetLookupDbFilter(bool val) +{ + if (!m_Local) { + x_Throwx("Error: SetLookupDbFilter not yet available."); + } + m_Local->SetLookupDbFilter(val); +} + /// Megablast only lookup table options unsigned char CBlastOptions::GetMBTemplateLength() const @@ -1583,6 +1610,49 @@ CBlastOptions::SetUnifiedP(int u) m_Remote->SetValue(eBlastOpt_UnifiedP, u); } } + +int +CBlastOptions::GetMaxMismatches() const +{ + if (! m_Local) { + x_Throwx("Error: GetMaxMismatches() not available."); + } + + return m_Local->GetMaxMismatches(); +} + +void +CBlastOptions::SetMaxMismatches(int m) +{ + if (m_Local) { + m_Local->SetMaxMismatches(m); + } + else { + x_Throwx("Error: GetMaxMismatches() not supported for remote searches"); + } +} + + +int +CBlastOptions::GetMismatchWindow() const +{ + if (! m_Local) { + x_Throwx("Error: GetMismatchWindow() not available."); + } + + return m_Local->GetMismatchWindow(); +} + +void +CBlastOptions::SetMismatchWindow(int w) +{ + if (m_Local) { + m_Local->SetMismatchWindow(w); + } + else { + x_Throwx("Error: GetMismatchWindow() not supported for remote searches"); + } +} /******************* Hit saving options *************************/ @@ -1913,6 +1983,47 @@ CBlastOptions::SetLowScorePerc(double p) } +bool +CBlastOptions::GetPaired() const +{ + if (! m_Local) { + x_Throwx("Error: GetPaired() not available."); + } + return m_Local->GetPaired(); +} + +void +CBlastOptions::SetPaired(bool p) +{ + if (m_Local) { + m_Local->SetPaired(p); + } + else { + x_Throwx("Error: SetPaired() not available."); + } +} + + +bool +CBlastOptions::GetSpliceAlignments() const +{ + if (! m_Local) { + x_Throwx("Error: GetSplice() not available."); + } + return m_Local->GetSplice(); +} + +void +CBlastOptions::SetSpliceAlignments(bool s) +{ + if (m_Local) { + m_Local->SetSplice(s); + } + else { + x_Throwx("Error: SetSplice() not available."); + } +} + /************************ Scoring options ************************/ const char* diff --git a/c++/src/algo/blast/api/blast_options_handle.cpp b/c++/src/algo/blast/api/blast_options_handle.cpp index 0a0bd1ed..1845678c 100644 --- a/c++/src/algo/blast/api/blast_options_handle.cpp +++ b/c++/src/algo/blast/api/blast_options_handle.cpp @@ -1,4 +1,4 @@ -/* $Id: blast_options_handle.cpp 442215 2014-07-31 14:00:16Z fongah2 $ +/* $Id: blast_options_handle.cpp 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -47,6 +47,7 @@ #include #include #include +#include /** @addtogroup AlgoBlast * @@ -186,6 +187,10 @@ CBlastOptionsFactory::Create(EProgram program, EAPILocality locality) break; } + case eMapper: + retval = new CMagicBlastOptionsHandle(locality); + break; + case eBlastNotSet: NCBI_THROW(CBlastException, eInvalidArgument, "eBlastNotSet may not be used as argument"); @@ -233,6 +238,13 @@ CBlastOptionsFactory::GetTasks(ETaskSets choice /* = eAll */) retval.insert("tblastx"); } + if (choice == eMapping || choice == eAll) { + retval.insert("mapper"); + retval.insert("mapr2g"); + retval.insert("mapr2r"); + retval.insert("mapg2g"); + } + return retval; } @@ -298,6 +310,14 @@ CBlastOptionsFactory::GetDocumentation(const string& task_name) } else if (task == "deltablast") { retval.assign("DELTA-BLAST builds profile using conserved domain "); retval += "and uses this profile to search protein database"; + } else if (task == "mapper") { + retval.assign("Map short reads to a genome"); + } else if (task == "mapr2g") { + retval.assign("Map RNA-seq sequence to a genome"); + } else if (task == "mapr2r") { + retval.assign("Map RNA-seq sequences to an mRNA database"); + } else if (task == "mapg2g") { + retval.assign("Map genomic reads to a genome"); } else { retval.assign("Unknown task"); } @@ -424,6 +444,27 @@ CBlastOptionsFactory::CreateTask(string task, EAPILocality locality) { retval = CBlastOptionsFactory::Create(eDeltaBlast, locality); } + else if (!NStr::CompareNocase(task, "mapper") || + !NStr::CompareNocase(task, "mapr2g") || + !NStr::CompareNocase(task, "mapr2r") || + !NStr::CompareNocase(task, "mapg2g")) { + + CMagicBlastOptionsHandle* opts = + dynamic_cast + (CBlastOptionsFactory::Create(eMapper, locality)); + + if (!NStr::CompareNocase(task, "mapr2g")) { + opts->SetRNAToGenomeDefaults(); + } + else if (!NStr::CompareNocase(task, "mapr2r")) { + opts->SetRNAToRNADefaults(); + } + else { + opts->SetGenomeToGenomeDefaults(); + } + + retval = opts; + } else { abort(); // should never get here diff --git a/c++/src/algo/blast/api/blast_options_local_priv.cpp b/c++/src/algo/blast/api/blast_options_local_priv.cpp index 4603df72..1c38b5ce 100644 --- a/c++/src/algo/blast/api/blast_options_local_priv.cpp +++ b/c++/src/algo/blast/api/blast_options_local_priv.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_options_local_priv.cpp 463310 2015-03-26 17:00:09Z boukn $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * @@ -383,7 +379,8 @@ CBlastOptionsLocal::Validate() const else // Index validation. if( m_UseMBIndex && - (m_Program != eMegablast && m_Program != eBlastn) ) { + (m_Program != eMegablast && m_Program != eBlastn + && m_Program != eMapper) ) { NCBI_THROW(CBlastException, eInvalidOptions, "Database index can be used only with contiguous megablast." ); } diff --git a/c++/src/algo/blast/api/blast_options_local_priv.hpp b/c++/src/algo/blast/api/blast_options_local_priv.hpp index 4c40d0ab..38e2277b 100644 --- a/c++/src/algo/blast/api/blast_options_local_priv.hpp +++ b/c++/src/algo/blast/api/blast_options_local_priv.hpp @@ -1,4 +1,4 @@ -/* $Id: blast_options_local_priv.hpp 460349 2015-02-26 16:10:16Z fongah2 $ +/* $Id: blast_options_local_priv.hpp 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -87,6 +87,11 @@ public: int GetWordSize() const; void SetWordSize(int ws); + /// Skip words after each collected one while creating a lookup table + /// (currently only for megablast) + Uint4 GetLookupTableStride() const; + void SetLookupTableStride(Uint4 val); + /// Megablast only lookup table options unsigned char GetMBTemplateLength() const; void SetMBTemplateLength(unsigned char len); @@ -94,6 +99,9 @@ public: unsigned char GetMBTemplateType() const; void SetMBTemplateType(unsigned char type); + bool GetLookupDbFilter(void) const; + void SetLookupDbFilter(bool val); + /******************* Query setup options ************************/ char* GetFilterString() const; void SetFilterString(const char* f); @@ -175,6 +183,12 @@ public: int GetUnifiedP() const; void SetUnifiedP(int u = 0); + int GetMaxMismatches() const; + void SetMaxMismatches(int m); + + int GetMismatchWindow() const; + void SetMismatchWindow(int w); + /******************* Hit saving options *************************/ int GetHitlistSize() const; void SetHitlistSize(int s); @@ -230,6 +244,14 @@ public: double GetLowScorePerc() const; void SetLowScorePerc(double p = 0.0); + // Paired reads only if set to true + bool GetPaired() const; + void SetPaired(bool p); + + /// Splice HSPs for each query + bool GetSplice() const; + void SetSplice(bool p); + /// Returns true if cross_match-like complexity adjusted // scoring is required, false otherwise. -RMH- bool GetComplexityAdjMode() const; @@ -572,6 +594,18 @@ CBlastOptionsLocal::SetWordSize(int ws) m_LutOpts->lut_type = eCompressedAaLookupTable; } +inline Uint4 +CBlastOptionsLocal::GetLookupTableStride() const +{ + return m_LutOpts->stride; +} + +inline void +CBlastOptionsLocal::SetLookupTableStride(Uint4 val) +{ + m_LutOpts->stride = val; +} + inline unsigned char CBlastOptionsLocal::GetMBTemplateLength() const { @@ -596,6 +630,18 @@ CBlastOptionsLocal::SetMBTemplateType(unsigned char type) m_LutOpts->mb_template_type = type; } +inline bool +CBlastOptionsLocal::GetLookupDbFilter(void) const +{ + return m_LutOpts->db_filter; +} + +inline void +CBlastOptionsLocal::SetLookupDbFilter(bool val) +{ + m_LutOpts->db_filter = val; +} + /******************* Query setup options ************************/ inline char* @@ -638,7 +684,8 @@ CBlastOptionsLocal::SetFilterString(const char* f) } // Repeat filtering is only allowed for blastn. - if (GetProgramType() != eBlastTypeBlastn && + if (GetProgramType() != eBlastTypeBlastn && + GetProgramType() != eBlastTypeMapping && m_QueryOpts->filtering_options->repeatFilterOptions) m_QueryOpts->filtering_options->repeatFilterOptions = SRepeatFilterOptionsFree(m_QueryOpts->filtering_options->repeatFilterOptions); @@ -1077,6 +1124,30 @@ CBlastOptionsLocal::SetUnifiedP(int u) m_ExtnOpts->unifiedP = u; } +inline int +CBlastOptionsLocal::GetMaxMismatches() const +{ + return m_ExtnOpts->max_mismatches; +} + +inline void +CBlastOptionsLocal::SetMaxMismatches(int m) +{ + m_ExtnOpts->max_mismatches = m; +} + +inline int +CBlastOptionsLocal::GetMismatchWindow() const +{ + return m_ExtnOpts->mismatch_window; +} + +inline void +CBlastOptionsLocal::SetMismatchWindow(int w) +{ + m_ExtnOpts->mismatch_window = w; +} + /******************* Hit saving options *************************/ inline int CBlastOptionsLocal::GetHitlistSize() const @@ -1335,6 +1406,30 @@ CBlastOptionsLocal::SetLowScorePerc(double p) m_HitSaveOpts->low_score_perc = p; } +inline bool +CBlastOptionsLocal::GetPaired() const +{ + return m_HitSaveOpts->paired; +} + +inline void +CBlastOptionsLocal::SetPaired(bool p) +{ + m_HitSaveOpts->paired = p; +} + +inline bool +CBlastOptionsLocal::GetSplice() const +{ + return m_HitSaveOpts->splice; +} + +inline void +CBlastOptionsLocal::SetSplice(bool s) +{ + m_HitSaveOpts->splice = s; +} + /* Flag to indicate if cross_match-like complexity adjusted scoring is in use. Currently only used by RMBlastN. -RMH- */ inline bool diff --git a/c++/src/algo/blast/api/blast_results.cpp b/c++/src/algo/blast/api/blast_results.cpp index 04f695b2..3e06e358 100644 --- a/c++/src/algo/blast/api/blast_results.cpp +++ b/c++/src/algo/blast/api/blast_results.cpp @@ -1,4 +1,4 @@ -/* $Id: blast_results.cpp 475845 2015-08-12 14:12:44Z fongah2 $ +/* $Id: blast_results.cpp 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -32,11 +32,6 @@ * search */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_results.cpp 475845 2015-08-12 14:12:44Z fongah2 $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include diff --git a/c++/src/algo/blast/api/blast_seqalign.cpp b/c++/src/algo/blast/api/blast_seqalign.cpp index 0276ad28..ce423ca3 100644 --- a/c++/src/algo/blast/api/blast_seqalign.cpp +++ b/c++/src/algo/blast/api/blast_seqalign.cpp @@ -1,4 +1,4 @@ -/* $Id: blast_seqalign.cpp 499810 2016-04-28 15:43:25Z ivanov $ +/* $Id: blast_seqalign.cpp 520431 2016-11-28 18:26:12Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -41,8 +41,10 @@ #include #include #include +#include #include #include +#include "../core/jumper.h" #include @@ -393,6 +395,123 @@ s_CorrectUASequence(BlastHSP* hsp) return; } + +void MakeSplicedSeg(CSpliced_seg& spliced_seg, + CRef product_id, + CRef genomic_id, + int product_length, + const BlastHSPChain* chain) +{ + spliced_seg.SetProduct_id(*product_id); + spliced_seg.SetGenomic_id(*genomic_id); + + _ASSERT(chain->num_hsps > 0); + _ASSERT(chain->hsp_array[0]); + ENa_strand product_strand = s_Frame2Strand(chain->hsp_array[0]->query.frame); + ENa_strand genomic_strand = s_Frame2Strand( + chain->hsp_array[0]->subject.frame); + + spliced_seg.SetProduct_type(CSpliced_seg::eProduct_type_transcript); + spliced_seg.SetProduct_length(product_length); + + CSpliced_seg::TExons& exons = spliced_seg.SetExons(); + const Uint1 kGap = 15; // Gap in BLASTNA + + for (int k=0;k < chain->num_hsps;k++) { + BlastHSP* hsp = chain->hsp_array[k]; + _ASSERT(hsp); + + _ASSERT(hsp->gap_info->size > 1 || + hsp->query.end - hsp->query.offset == + hsp->subject.end - hsp->subject.offset); + + CRef exon(new CSpliced_exon); + exon->SetProduct_start().SetNucpos(hsp->query.offset); + exon->SetProduct_end().SetNucpos(hsp->query.end - 1); + exon->SetGenomic_start(hsp->subject.offset); + exon->SetGenomic_end(hsp->subject.end - 1); + + exon->SetProduct_strand(product_strand); + exon->SetGenomic_strand(genomic_strand); + + const JumperEditsBlock* hsp_edits = hsp->map_info->edits; + int query_pos = hsp->query.offset; + int subject_pos = hsp->subject.offset; + int num_matches = 0; + + // save splice signal before next exon + if (hsp->map_info->left_edge & MAPPER_SPLICE_SIGNAL) { + CSpliced_exon::TAcceptor_before_exon::TBases l_bases(2u, ' '); + l_bases[0] = BLASTNA_TO_IUPACNA[ + (int)((hsp->map_info->left_edge >> 2) & 3)]; + l_bases[1] = BLASTNA_TO_IUPACNA[ + (int)(hsp->map_info->left_edge & 3)]; + exon->SetAcceptor_before_exon().SetBases(l_bases); + } + + // save splice signal after exon + if (hsp->map_info->right_edge & MAPPER_SPLICE_SIGNAL) { + CSpliced_exon::TDonor_after_exon::TBases r_bases(2u, ' '); + r_bases[0] = BLASTNA_TO_IUPACNA[ + (int)((hsp->map_info->right_edge >> 2) & 3)]; + r_bases[1] = BLASTNA_TO_IUPACNA[ + (int)(hsp->map_info->right_edge & 3)]; + exon->SetDonor_after_exon().SetBases(r_bases); + } + + for (int i=0;i < hsp_edits->num_edits;i++) { + num_matches = hsp_edits->edits[i].query_pos - query_pos; + query_pos += num_matches; + subject_pos += num_matches; + _ASSERT(num_matches >= 0); + if (num_matches > 0) { + // record number of matches + CRef chunk(new CSpliced_exon_chunk); + chunk->SetMatch(num_matches); + exon->SetParts().push_back(chunk); + } + + // record mismatch or gap + CRef chunk(new CSpliced_exon_chunk); + _ASSERT(hsp_edits->edits[i].query_base != kGap || + hsp_edits->edits[i].subject_base != kGap); + + if (hsp_edits->edits[i].query_base == kGap) { + chunk->SetGenomic_ins(1); + subject_pos++; + } + else if (hsp_edits->edits[i].subject_base == kGap) { + chunk->SetProduct_ins(1); + query_pos++; + } + else { + chunk->SetMismatch(1); + query_pos++; + subject_pos++; + } + + exon->SetParts().push_back(chunk); + } + + num_matches = MAX(hsp->query.end - query_pos, 0); + _ASSERT(hsp->query.end - query_pos >= -1); + // an HSP may end with a mismatch or a gap, if a splice signal was + // found and HSP extent was updated (mapping reads to a genome) + _ASSERT(num_matches >= 0); + if (num_matches > 0) { + CRef chunk(new CSpliced_exon_chunk); + chunk->SetMatch(num_matches); + exon->SetParts().push_back(chunk); + } + + exons.push_back(exon); + } + +#if _DEBUG + spliced_seg.Validate(true); +#endif +} + /// Creates a Seq-align for a single HSP from precalculated vectors of start /// positions, lengths and strands of segments, sequence identifiers and other /// information. @@ -528,8 +647,11 @@ s_BlastHSP2SeqAlign(EBlastProgramType program, BlastHSP* hsp, strands, query_length, subject_length, translate1, translate2); - return s_CreateSeqAlign(id1, id2, starts, lengths, strands, - translate1, translate2); + CRef retval = s_CreateSeqAlign(id1, id2, starts, lengths, + strands, translate1, + translate2); + + return retval; } } @@ -889,9 +1011,9 @@ s_MakeScore(const string& ident_string, double d, int i, bool is_integer) /// Computes the exact size of a CSeq_align::TScore for a given HSP /// @param hsp HSP for which the score objects will be built, must be non-NULL /// [in] -/// @param gi_list list of GIs associated with this HSP [in] +/// @param seqid_list list of IDs associated with this HSP [in] static size_t -s_CalculateScoreVectorSize(const BlastHSP* hsp, const vector & gi_list) +s_CalculateScoreVectorSize(const BlastHSP* hsp, const vector & seqid_list) { _ASSERT(hsp); // query coverage hsp @@ -926,8 +1048,8 @@ s_CalculateScoreVectorSize(const BlastHSP* hsp, const vector & gi_list) retval++; } - if ( !gi_list.empty() ) { - retval += gi_list.size(); + if ( !seqid_list.empty() ) { + retval += seqid_list.size(); } return retval; } @@ -935,17 +1057,17 @@ s_CalculateScoreVectorSize(const BlastHSP* hsp, const vector & gi_list) /// Creates a list of score objects for a Seq-align, given an HSP structure. /// @param hsp Structure containing HSP information [in] /// @param scores Linked list of score objects to put into a Seq-align [out] -/// @param gi_list List of GIs for the subject sequence. +/// @param seqid_list List of GIs for the subject sequence. static void s_BuildScoreList(const BlastHSP * hsp, CSeq_align::TScore & scores, - const vector & gi_list, + const vector & seqid_list, Int4 query_length) { if (!hsp) return; - scores.reserve(s_CalculateScoreVectorSize(hsp, gi_list)); + scores.reserve(s_CalculateScoreVectorSize(hsp, seqid_list)); if (hsp->score) { static const string kScore("score"); @@ -985,10 +1107,9 @@ s_BuildScoreList(const BlastHSP * hsp, hsp->comp_adjustment_method, true)); } - if ( !gi_list.empty() ) { - static const string kUseThisGi("use_this_gi"); - ITERATE(vector, gi, gi_list) { - scores.push_back(s_MakeScore(kUseThisGi, 0.0, *gi, true)); + if ( !seqid_list.empty() ) { + ITERATE(vector, sid, seqid_list) { + scores.push_back(s_MakeScore(*sid, 0.0, 0, true)); } } @@ -1005,6 +1126,22 @@ s_BuildScoreList(const BlastHSP * hsp, return; } +/// Produce UserObject with Seq-ids to limit formatting to ("use_this_gi") +/// @param seqalign Seq-align object to fill in [in][out] +/// @param seqid_list list of strings with seqids [in] +static void +s_AddUserObjectToSeqAlign(CRef & seqalign, + const vector & seqid_list) +{ + if (seqid_list.empty()) + return; + + CRef userObject(new CUser_object()); + userObject->SetType().SetStr("use_this_seqid"); + userObject->AddField("SEQIDS", seqid_list); + seqalign->SetExt().push_back(userObject); +} + /// Given an HSP structure, creates a list of scores and inserts them into /// a Seq-align. @@ -1014,12 +1151,12 @@ s_BuildScoreList(const BlastHSP * hsp, static void s_AddScoresToSeqAlign(CRef & seqalign, const BlastHSP * hsp, - const vector & gi_list, + const vector & seqid_list, Int4 query_length) { // Add the scores for this HSP CSeq_align::TScore& score_list = seqalign->SetScore(); - s_BuildScoreList(hsp, score_list, gi_list, query_length); + s_BuildScoreList(hsp, score_list, seqid_list, query_length); } @@ -1036,7 +1173,7 @@ CRef x_UngappedHSPToDenseDiag(BlastHSP* hsp, CRef query_id, CRef subject_id, Int4 query_length, Int4 subject_length, - const vector & gi_list) + const vector & seqid_list) { CRef retval(new CDense_diag()); @@ -1068,7 +1205,7 @@ x_UngappedHSPToDenseDiag(BlastHSP* hsp, CRef query_id, } CSeq_align::TScore& score_list = retval->SetScores(); - s_BuildScoreList(hsp, score_list, gi_list, query_length); + s_BuildScoreList(hsp, score_list, seqid_list, query_length); return retval; } @@ -1086,7 +1223,7 @@ CRef x_UngappedHSPToStdSeg(BlastHSP* hsp, CRef query_id, CRef subject_id, Int4 query_length, Int4 subject_length, - const vector & gi_list) + const vector & seqid_list) { CRef retval(new CStd_seg()); @@ -1142,7 +1279,7 @@ x_UngappedHSPToStdSeg(BlastHSP* hsp, CRef query_id, retval->SetLoc().push_back(subject_loc); CSeq_align::TScore& score_list = retval->SetScores(); - s_BuildScoreList(hsp, score_list, gi_list, query_length); + s_BuildScoreList(hsp, score_list, seqid_list, query_length); return retval; } @@ -1162,7 +1299,7 @@ BLASTUngappedHspListToSeqAlign(EBlastProgramType program, CRef subject_id, Int4 query_length, Int4 subject_length, - const vector & gi_list, + const vector & seqid_list, vector > & sa_vector) { CRef seqalign(new CSeq_align()); @@ -1175,6 +1312,7 @@ BLASTUngappedHspListToSeqAlign(EBlastProgramType program, hsp_array = hsp_list->hsp_array; + vector emptyList; // FIXME: change prototypes below. /* All HSPs are put in one seqalign, containing a list of * DenseDiag for same molecule search, or StdSeg for translated searches. */ @@ -1189,7 +1327,7 @@ BLASTUngappedHspListToSeqAlign(EBlastProgramType program, subject_id, query_length, subject_length, - gi_list)); + emptyList)); } } else { // Translated search for (index=0; indexhspcnt; index++) { @@ -1200,9 +1338,10 @@ BLASTUngappedHspListToSeqAlign(EBlastProgramType program, subject_id, query_length, subject_length, - gi_list)); + emptyList)); } } + s_AddUserObjectToSeqAlign(seqalign, seqid_list); sa_vector.push_back(seqalign); return; } @@ -1221,7 +1360,7 @@ void BLASTHspListToSeqAlign(EBlastProgramType program, BlastHSPList* hsp_list, CRef query_id, CRef subject_id, Int4 query_length, Int4 subject_length, bool is_ooframe, - const vector & gi_list, + const vector & seqid_list, vector > & sa_vector) { // Process the list of HSPs corresponding to one subject sequence and @@ -1231,6 +1370,7 @@ BLASTHspListToSeqAlign(EBlastProgramType program, BlastHSPList* hsp_list, sa_vector.clear(); sa_vector.reserve(hsp_list->hspcnt); + vector emptyList; for (int index = 0; index < hsp_list->hspcnt; index++) { BlastHSP* hsp = hsp_array[index]; @@ -1253,14 +1393,17 @@ BLASTHspListToSeqAlign(EBlastProgramType program, BlastHSPList* hsp_list, if(hsp->num_ident == 0) hsp->num_ident = -1; } - s_AddScoresToSeqAlign(seqalign, hsp, gi_list, query_length); + // Pass in empty list until removed. + s_AddScoresToSeqAlign(seqalign, hsp, emptyList, query_length); + + s_AddUserObjectToSeqAlign(seqalign, seqid_list); sa_vector.push_back(seqalign); } return; } -CRef CreateEmptySeq_align_set() +CRef CreateEmptySeq_align_set(void) { CRef retval(new CSeq_align_set); retval->Set().clear(); @@ -1348,9 +1491,9 @@ BlastHitList2SeqAlign_OMF(const BlastHitList * hit_list, subj_masks.push_back(masks); } - // Get GIs for entrez query restriction. - vector gi_list; - GetFilteredRedundantGis(*seqinfo_src, hsp_list->oid, gi_list); + // Get SeqIds for entrez query restriction. + vector seqid_list; + GetFilteredRedundantSeqids(*seqinfo_src, hsp_list->oid, seqid_list, subject_id->IsGi()); // stores a CSeq_align for each matching sequence vector > hit_align; @@ -1362,7 +1505,7 @@ BlastHitList2SeqAlign_OMF(const BlastHitList * hit_list, query_length, subj_length, is_ooframe, - gi_list, + seqid_list, hit_align); } else { BLASTUngappedHspListToSeqAlign(prog, @@ -1371,7 +1514,7 @@ BlastHitList2SeqAlign_OMF(const BlastHitList * hit_list, subject_id, query_length, subj_length, - gi_list, + seqid_list, hit_align); } @@ -1477,7 +1620,8 @@ static void s_AdjustNegativeSubjFrameInBlastn(ENa_strand subj_strand, BlastHSPList* hsp_list) { _ASSERT(hsp_list); - if (subj_strand != eNa_strand_minus || program != eBlastTypeBlastn) + if (subj_strand != eNa_strand_minus || + (program != eBlastTypeBlastn && program != eBlastTypeMapping)) return; for (int index = 0; index < hsp_list->hspcnt; index++) { @@ -1556,8 +1700,9 @@ s_BLAST_OneSubjectResults2CSeqAlign(const BlastHSPResults* results, TSeqPos query_length = query_data.GetSeqLength(qindex); s_AdjustNegativeSubjFrameInBlastn(kSubjStrand, prog, hsp_list); - vector gi_list; - GetFilteredRedundantGis(seqinfo_src, hsp_list->oid, gi_list); + vector seqid_list; + GetFilteredRedundantSeqids(seqinfo_src, hsp_list->oid, seqid_list, subject_id->IsGi()); + // Union subject sequence ranges vector ranges; @@ -1585,7 +1730,7 @@ s_BLAST_OneSubjectResults2CSeqAlign(const BlastHSPResults* results, query_length, subj_length, is_ooframe, - gi_list, + seqid_list, hit_align); } else { BLASTUngappedHspListToSeqAlign(prog, @@ -1594,7 +1739,7 @@ s_BLAST_OneSubjectResults2CSeqAlign(const BlastHSPResults* results, subject_id, query_length, subj_length, - gi_list, + seqid_list, hit_align); } seq_aligns.Reset(new CSeq_align_set()); @@ -1791,7 +1936,7 @@ CRef x_NonTranslatedHSPToStdSeg(BlastHSP* hsp, CRef query_id, CRef subject_id, Int4 query_length, Int4 subject_length, - const vector & gi_list) + const vector & seqid_list) { CRef retval(new CStd_seg()); @@ -1832,7 +1977,7 @@ x_NonTranslatedHSPToStdSeg(BlastHSP* hsp, CRef query_id, retval->SetLoc().push_back(subject_loc); CSeq_align::TScore& score_list = retval->SetScores(); - s_BuildScoreList(hsp, score_list, gi_list, query_length); + s_BuildScoreList(hsp, score_list, seqid_list, query_length); return retval; } @@ -1854,7 +1999,7 @@ BLASTPrelminSearchHitListToStdSeg(EBlastProgramType program, CRef (*fun_ptr) (BlastHSP* , CRef , CRef , Int4 , Int4 , - const vector & ) = NULL; + const vector & ) = NULL; if((TRANSLATED_QUERY_MASK | TRANSLATED_SUBJECT_MASK) & program ) fun_ptr = x_UngappedHSPToStdSeg; @@ -1871,12 +2016,11 @@ BLASTPrelminSearchHitListToStdSeg(EBlastProgramType program, if(hsp_list->hspcnt > 0) { - const Uint4 oid = hsp_list->oid; TSeqPos subject_length = 0; CRef subject_id; - vector gi_list; - GetFilteredRedundantGis(*subject_seqinfo, oid, gi_list); - GetSequenceLengthAndId(subject_seqinfo, oid, subject_id, &subject_length); + vector seqid_list; + GetSequenceLengthAndId(subject_seqinfo, hsp_list->oid, subject_id, &subject_length); + GetFilteredRedundantSeqids(*subject_seqinfo, hsp_list->oid, seqid_list, subject_id->IsGi()); for (int j = 0; j < hsp_list->hspcnt; j++) { @@ -1886,7 +2030,7 @@ BLASTPrelminSearchHitListToStdSeg(EBlastProgramType program, continue; seg_list.push_back((*fun_ptr) (hsp, query_id, subject_id, - query_length, subject_length, gi_list)); + query_length, subject_length, seqid_list)); } } } diff --git a/c++/src/algo/blast/api/blast_seqalign.hpp b/c++/src/algo/blast/api/blast_seqalign.hpp index 86f803db..efcbf3ca 100644 --- a/c++/src/algo/blast/api/blast_seqalign.hpp +++ b/c++/src/algo/blast/api/blast_seqalign.hpp @@ -1,4 +1,4 @@ -/* $Id: blast_seqalign.hpp 358152 2012-03-29 14:42:07Z fongah2 $ +/* $Id: blast_seqalign.hpp 520431 2016-11-28 18:26:12Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -67,8 +67,8 @@ RemapToQueryLoc(CRef sar, const CSeq_loc & query); /// @param sas Pointer to a Seq-align-set, to which new object should be /// appended (if not NULL). /// @return Resulting Seq-align-set. -CSeq_align_set* -CreateEmptySeq_align_set(CSeq_align_set* sas); +CRef +CreateEmptySeq_align_set(void); void BLASTHspListToSeqAlign(EBlastProgramType program, @@ -78,7 +78,7 @@ BLASTHspListToSeqAlign(EBlastProgramType program, Int4 query_length, Int4 subject_length, bool is_ooframe, - const vector & gi_list, + const vector & seqid_list, vector > & sa_vector); void @@ -88,7 +88,7 @@ BLASTUngappedHspListToSeqAlign(EBlastProgramType program, CRef subject_id, Int4 query_length, Int4 subject_length, - const vector & gi_list, + const vector & seqid_list, vector > & sa_vector); /// Convert traceback output into Seq-align format. @@ -150,6 +150,19 @@ BLASTPrelminSearchHitListToStdSeg(EBlastProgramType program, const IBlastSeqInfoSrc * subject_seqinfo, list > & seg_list); + +/// Convert a spliced alignmeny in BlastHSPChain into Spliced_seg +/// @param spliced_seg Spliced_seg object [in] [out] +/// @param product_id Sequence id of a read/query [in] +/// @param genomic_id Sequence id a genome/subject [in] +/// @param chain Alignment to be converted [in] +void MakeSplicedSeg(CSpliced_seg& spliced_seg, + CRef product_id, + CRef genomic_id, + int product_length, + const BlastHSPChain* chain); + + END_SCOPE(blast) END_NCBI_SCOPE diff --git a/c++/src/algo/blast/api/blast_seqinfosrc_aux.cpp b/c++/src/algo/blast/api/blast_seqinfosrc_aux.cpp index 95b1cca3..941b0999 100644 --- a/c++/src/algo/blast/api/blast_seqinfosrc_aux.cpp +++ b/c++/src/algo/blast/api/blast_seqinfosrc_aux.cpp @@ -1,4 +1,4 @@ -/* $Id: blast_seqinfosrc_aux.cpp 440917 2014-07-17 21:22:41Z rackerst $ +/* $Id: blast_seqinfosrc_aux.cpp 520431 2016-11-28 18:26:12Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -68,7 +68,7 @@ void GetSequenceLengthAndId(const blast::IBlastSeqInfoSrc * seqinfo_src, void GetFilteredRedundantGis(const IBlastSeqInfoSrc & seqinfo_src, int oid, - vector & gis) + vector & gis) { gis.resize(0); @@ -81,13 +81,52 @@ void GetFilteredRedundantGis(const IBlastSeqInfoSrc & seqinfo_src, ITERATE(list< CRef >, id, seqid_list) { if ((**id).IsGi()) { - gis.push_back(GI_TO(int, (**id).GetGi())); + gis.push_back((**id).GetGi()); } } sort(gis.begin(), gis.end()); } +void GetFilteredRedundantSeqids(const IBlastSeqInfoSrc & seqinfo_src, + int oid, + vector & seqids, + bool use_gi) +{ + seqids.resize(0); + + if (! seqinfo_src.HasGiList()) { + return; + } + + list< CRef > seqid_list = seqinfo_src.GetId(oid); + + ITERATE(list< CRef >, id, seqid_list) { + if (use_gi) + { + if ((**id).IsGi()) + { + string sid_string = "gi:" + (*id)->GetSeqIdString(true); + seqids.push_back(sid_string); + } + } + else + { + const CTextseq_id* tsid = (*id)->GetTextseq_Id(); + if (tsid && tsid->IsSetAccession()) + { + string sid_string = "seqid:" + (*id)->GetSeqIdString(true); + seqids.push_back(sid_string); + } + else if ((*id)->IsPdb()) + { + string sid_string = "seqid:" + (*id)->GetSeqIdString(true); + seqids.push_back(sid_string); + } + } + } +} + END_SCOPE(blast) END_NCBI_SCOPE diff --git a/c++/src/algo/blast/api/blast_setup.hpp b/c++/src/algo/blast/api/blast_setup.hpp index 9641c263..36d5c503 100644 --- a/c++/src/algo/blast/api/blast_setup.hpp +++ b/c++/src/algo/blast/api/blast_setup.hpp @@ -1,4 +1,4 @@ -/* $Id: blast_setup.hpp 144802 2008-11-03 20:57:20Z camacho $ +/* $Id: blast_setup.hpp 517499 2016-10-25 17:20:41Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -156,6 +156,12 @@ public: /// @param index index of the sequence in the sequence container [in] /// @return the sequence title or kEmptyStr if not available virtual string GetTitle(int index) const = 0; + + /// Is this sequence followed by a mate (for mapping short reads) + NCBI_DEPRECATED virtual bool IsFirstOfAPair(int index) const = 0; + + /// Get segment information (for mapping paired short reads) + virtual int GetSegmentInfo(int index) const = 0; }; /// Choose between a Seq-loc specified query strand and the strand obtained diff --git a/c++/src/algo/blast/api/blast_setup_cxx.cpp b/c++/src/algo/blast/api/blast_setup_cxx.cpp index 9f44c7bb..06fc926f 100644 --- a/c++/src/algo/blast/api/blast_setup_cxx.cpp +++ b/c++/src/algo/blast/api/blast_setup_cxx.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_setup_cxx.cpp 500367 2016-05-04 12:06:01Z ivanov $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * @@ -136,7 +132,8 @@ s_AdjustFirstContext(BlastQueryInfo* query_info, _ASSERT(query_info); #if _DEBUG /* to eliminate compiler warning in release mode */ - bool is_na = (prog == eBlastTypeBlastn) ? true : false; + bool is_na = (prog == eBlastTypeBlastn || prog == eBlastTypeMapping) + ? true : false; #endif bool translate = Blast_QueryIsTranslated(prog) ? true : false; @@ -165,7 +162,9 @@ SetupQueryInfo_OMF(const IBlastQuerySource& queries, } const unsigned int kNumContexts = GetNumberOfContexts(prog); - bool is_na = (prog == eBlastTypeBlastn) ? true : false; + bool is_na = (prog == eBlastTypeBlastn || prog == eBlastTypeMapping) + ? true : false; + bool translate = Blast_QueryIsTranslated(prog) ? true : false; if (is_na || translate) { @@ -177,6 +176,7 @@ SetupQueryInfo_OMF(const IBlastQuerySource& queries, unsigned int ctx_index = 0; // index into BlastQueryInfo::contexts array // Longest query length, to be saved in the query info structure Uint4 max_length = 0; + Uint4 min_length = INT4_MAX; for(TSeqPos j = 0; j < queries.Size(); j++) { TSeqPos length = 0; @@ -194,6 +194,7 @@ SetupQueryInfo_OMF(const IBlastQuerySource& queries, unsigned int prot_length = BLAST_GetTranslatedProteinLength(length, i); max_length = MAX(max_length, prot_length); + min_length = MIN(min_length, prot_length); Uint4 ctx_len(0); @@ -201,11 +202,15 @@ SetupQueryInfo_OMF(const IBlastQuerySource& queries, case eNa_strand_plus: ctx_len = (i<3) ? prot_length : 0; s_QueryInfo_SetContext(query_info, ctx_index + i, ctx_len); + // the missing frame is present in query_info as + // zero-lenghth context + min_length = 0; break; case eNa_strand_minus: ctx_len = (i<3) ? 0 : prot_length; s_QueryInfo_SetContext(query_info, ctx_index + i, ctx_len); + min_length = 0; break; case eNa_strand_both: @@ -220,17 +225,22 @@ SetupQueryInfo_OMF(const IBlastQuerySource& queries, } } else { max_length = MAX(max_length, length); + min_length = MIN(min_length, length); if (is_na) { switch (strand) { case eNa_strand_plus: s_QueryInfo_SetContext(query_info, ctx_index, length); s_QueryInfo_SetContext(query_info, ctx_index+1, 0); + // the missing strand is present in query_info as + // zero-lenghth context + min_length = 0; break; case eNa_strand_minus: s_QueryInfo_SetContext(query_info, ctx_index, 0); s_QueryInfo_SetContext(query_info, ctx_index+1, length); + min_length = 0; break; case eNa_strand_both: @@ -246,9 +256,19 @@ SetupQueryInfo_OMF(const IBlastQuerySource& queries, s_QueryInfo_SetContext(query_info, ctx_index, length); } } + + // mark queries that have pairs (for mapping) + if (Blast_ProgramIsMapping(prog)) { + _ASSERT(!translate); + + int seg_flags = queries.GetSegmentInfo(j); + query_info->contexts[ctx_index].segment_flags = seg_flags; + query_info->contexts[ctx_index + 1].segment_flags = seg_flags; + } ctx_index += kNumContexts; } query_info->max_length = max_length; + query_info->min_length = min_length; *qinfo = query_info.Release(); } @@ -485,7 +505,9 @@ SetupQueries_OMF(IBlastQuerySource& queries, "Query sequence buffer"); } - bool is_na = (prog == eBlastTypeBlastn) ? true : false; + bool is_na = (prog == eBlastTypeBlastn || prog == eBlastTypeMapping) + ? true : false; + bool translate = Blast_QueryIsTranslated(prog) ? true : false; unsigned int ctx_index = 0; // index into context_offsets array @@ -863,15 +885,8 @@ GetSequenceProtein(IBlastSeqVector& sv, string* warnings = 0) safe_buf.reset(buf); *buf_var++ = GetSentinelByte(eBlastEncodingProtein); for (i = 0; i < sv.size(); i++) { - // Silently change Selenocysteine (U) to Cysteine (C) - // This is needed because composition based stats works with 20 amino - // acids, and computes residue frequencies for a query before - // converting U to C. - if (sv[i] == AMINOACID_TO_NCBISTDAA[(int)'U']) { - *buf_var++ = AMINOACID_TO_NCBISTDAA[(int)'C']; - // Change unsupported residues to X - } else if (sv[i] == AMINOACID_TO_NCBISTDAA[(int)'O']) { + if (sv[i] == AMINOACID_TO_NCBISTDAA[(int)'O']) { replaced_residues.push_back(i); *buf_var++ = AMINOACID_TO_NCBISTDAA[(int)'X']; } else if (!s_IsValidResidue(sv[i])) { @@ -896,7 +911,7 @@ GetSequenceProtein(IBlastSeqVector& sv, string* warnings = 0) *buf_var++ = GetSentinelByte(eBlastEncodingProtein); if (warnings && replaced_residues.size() > 0) { - *warnings += "One or more U or O characters replaced by X for "; + *warnings += "One or more O characters replaced by X for "; *warnings += "alignment score calculations at positions "; *warnings += NStr::IntToString(replaced_residues[0]); for (i = 1; i < min(kMaxResiduesToWarnAbout, replaced_residues.size()); @@ -1072,6 +1087,7 @@ GetQueryEncoding(EBlastProgramType program) switch (program) { case eBlastTypeBlastn: case eBlastTypePhiBlastn: + case eBlastTypeMapping: retval = eBlastEncodingNucleotide; break; @@ -1104,6 +1120,7 @@ GetSubjectEncoding(EBlastProgramType program) switch (program) { case eBlastTypeBlastn: + case eBlastTypeMapping: retval = eBlastEncodingNucleotide; break; @@ -1407,10 +1424,12 @@ FindBlastDbPath(const char* dbname, bool is_prot) } // Obtain the matrix path from the ncbi configuration file - CMetaRegistry::SEntry sentry; - sentry = CMetaRegistry::Load("ncbi", CMetaRegistry::eName_RcOrIni); - string path = - sentry.registry ? sentry.registry->Get("BLAST", "BLASTDB") : ""; + string path; + if (app) { + const CNcbiRegistry& registry = app->GetConfig(); + if (registry.HasEntry("BLAST", "BLASTDB")) + CDirEntry::NormalizePath(registry.Get("BLAST", "BLASTDB"), eFollowLinks); + } full_path = CFile::MakePath(path, database); if (BlastDbFileExists(full_path, is_prot)) { @@ -1641,6 +1660,7 @@ void CBlastQueryFilteredFrames::x_VerifyFrame(int frame) break; case eBlastTypeBlastn: + case eBlastTypeMapping: if ((frame != CSeqLocInfo::eFramePlus1) && (frame != CSeqLocInfo::eFrameMinus1)) { okay = false; @@ -1689,6 +1709,7 @@ bool CBlastQueryFilteredFrames::QueryHasMultipleFrames() const case eBlastTypeBlastx: case eBlastTypeTblastx: case eBlastTypeRpsTblastn: + case eBlastTypeMapping: return true; default: @@ -1703,7 +1724,9 @@ void CBlastQueryFilteredFrames::AddSeqLoc(const objects::CSeq_interval & intv, int frame) { _ASSERT( m_Frames.empty() ); - if ((frame == 0) && (m_Program == eBlastTypeBlastn)) { + if ((frame == 0) && (m_Program == eBlastTypeBlastn + || m_Program == eBlastTypeMapping)) { + x_VerifyFrame(CSeqLocInfo::eFramePlus1); x_VerifyFrame(CSeqLocInfo::eFrameMinus1); static const CSeqLocInfo::ETranslationFrame kFrames[] = { diff --git a/c++/src/algo/blast/api/cdd_pssm_input.cpp b/c++/src/algo/blast/api/cdd_pssm_input.cpp index 04aee13a..591e7192 100644 --- a/c++/src/algo/blast/api/cdd_pssm_input.cpp +++ b/c++/src/algo/blast/api/cdd_pssm_input.cpp @@ -1,8 +1,5 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: cdd_pssm_input.cpp 347562 2011-12-19 19:26:47Z boratyng $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ -/* =========================================================================== +/* $Id: cdd_pssm_input.cpp 500404 2016-05-04 14:59:01Z camacho $ + * =========================================================================== * * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information @@ -34,7 +31,6 @@ static char const rcsid[] = * Implementation of the concrete strategy to obtain PSSM input data for * PSI-BLAST. */ - #include // BLAST includes diff --git a/c++/src/algo/blast/api/deltablast.cpp b/c++/src/algo/blast/api/deltablast.cpp index 64c045ab..4c855dd7 100644 --- a/c++/src/algo/blast/api/deltablast.cpp +++ b/c++/src/algo/blast/api/deltablast.cpp @@ -1,8 +1,5 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - ""; -#endif /* SKIP_DOXYGEN_PROCESSING */ -/* =========================================================================== +/* $Id: deltablast.cpp 500404 2016-05-04 14:59:01Z camacho $ + * =========================================================================== * * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information @@ -33,7 +30,6 @@ static char const rcsid[] = /** @file deltablast.cpp * Implementation of CDeltaBlast. */ - #include #include #include @@ -54,7 +50,7 @@ static char const rcsid[] = BEGIN_NCBI_SCOPE USING_SCOPE(objects); -BEGIN_SCOPE(blast); +BEGIN_SCOPE(blast) CDeltaBlast::CDeltaBlast(CRef query_factory, CRef blastdb, diff --git a/c++/src/algo/blast/api/dust_filter.cpp b/c++/src/algo/blast/api/dust_filter.cpp index 91651186..927e1cc3 100644 --- a/c++/src/algo/blast/api/dust_filter.cpp +++ b/c++/src/algo/blast/api/dust_filter.cpp @@ -1,4 +1,4 @@ -/* $Id: dust_filter.cpp 500379 2016-05-04 13:50:05Z ivanov $ +/* $Id: dust_filter.cpp 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -32,11 +32,6 @@ /// @file dust_filter.cpp /// Calls sym dust lib in algo/dustmask and returns CSeq_locs for use by BLAST. - -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = "$Id: dust_filter.cpp 500379 2016-05-04 13:50:05Z ivanov $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include "dust_filter.hpp" #include diff --git a/c++/src/algo/blast/api/local_blast.cpp b/c++/src/algo/blast/api/local_blast.cpp index 1ecbe889..384923b5 100644 --- a/c++/src/algo/blast/api/local_blast.cpp +++ b/c++/src/algo/blast/api/local_blast.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: local_blast.cpp 500119 2016-05-02 16:12:14Z ivanov $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -71,6 +67,7 @@ SplitQuery_GetChunkSize(EProgram program) break; case eMegablast: case eDiscMegablast: + case eMapper: retval = 5000000; break; case eTblastn: diff --git a/c++/src/algo/blast/api/local_db_adapter.cpp b/c++/src/algo/blast/api/local_db_adapter.cpp index e00919d2..11db59cd 100644 --- a/c++/src/algo/blast/api/local_db_adapter.cpp +++ b/c++/src/algo/blast/api/local_db_adapter.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: local_db_adapter.cpp 478540 2015-09-10 12:56:25Z madden $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/algo/blast/api/local_search.cpp b/c++/src/algo/blast/api/local_search.cpp index f97e03c1..5a19681f 100644 --- a/c++/src/algo/blast/api/local_search.cpp +++ b/c++/src/algo/blast/api/local_search.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: local_search.cpp 327673 2011-07-28 14:30:03Z camacho $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/algo/blast/api/magicblast.cpp b/c++/src/algo/blast/api/magicblast.cpp new file mode 100644 index 00000000..2836779e --- /dev/null +++ b/c++/src/algo/blast/api/magicblast.cpp @@ -0,0 +1,346 @@ +/* $Id: magicblast.cpp 505553 2016-06-27 14:10:27Z boratyng $ + * =========================================================================== + * + * PUBLIC DOMAIN NOTICE + * National Center for Biotechnology Information + * + * This software/database is a "United States Government Work" under the + * terms of the United States Copyright Act. It was written as part of + * the author's official duties as a United States Government employee and + * thus cannot be copyrighted. This software/database is freely available + * to the public for use. The National Library of Medicine and the U.S. + * Government have not placed any restriction on its use or reproduction. + * + * Although all reasonable efforts have been taken to ensure the accuracy + * and reliability of the software and data, the NLM and the U.S. + * Government do not and cannot warrant the performance or results that + * may be obtained by using this software or data. The NLM and the U.S. + * Government disclaim all warranties, express or implied, including + * warranties of performance, merchantability or fitness for any particular + * purpose. + * + * Please cite the author in any work or product based on this material. + * + * =========================================================================== + * + * Author: Greg Boratyn + * + */ + +/** @file magicblast.cpp + * Implementation of CMagicBlast. + */ + +#include +#include +#include +#include + +#include "blast_seqalign.hpp" +#include "blast_aux_priv.hpp" +#include "../core/jumper.h" + +/** @addtogroup AlgoBlast + * + * @{ + */ + +BEGIN_NCBI_SCOPE +USING_SCOPE(objects); +BEGIN_SCOPE(blast); + +CMagicBlast::CMagicBlast(CRef query_factory, + CRef blastdb, + CRef options) + : m_Queries(query_factory), + m_LocalDbAdapter(blastdb), + m_Options(&options->SetOptions()) +{ + x_Validate(); +} + + +CRef CMagicBlast::Run(void) +{ + CRef prelim_search(new CBlastPrelimSearch(m_Queries, + m_Options, + m_LocalDbAdapter)); + + int status = prelim_search->CheckInternalData(); + if (status != 0) + { + // Search was not run, but we send back an empty CSearchResultSet. + CRef local_query_data = + m_Queries->MakeLocalQueryData(m_Options); + + vector< CConstRef > seqid_vec; + vector< CRef > ancill_vec; + TSeqAlignVector sa_vec; + size_t index; + unsigned int num_subjects = 0; + if (m_LocalDbAdapter.NotEmpty() && !m_LocalDbAdapter->IsBlastDb() && + !m_LocalDbAdapter->IsDbScanMode()) { + + IBlastSeqInfoSrc * subject_infosrc = + m_LocalDbAdapter->MakeSeqInfoSrc(); + + if(subject_infosrc != NULL) { + num_subjects = subject_infosrc->Size(); + } + } + TSearchMessages msg_vec; + for (index=0; indexGetNumQueries(); index++) + { + CConstRef query_id( + local_query_data->GetSeq_loc(index)->GetId()); + + TQueryMessages q_msg; + local_query_data->GetQueryMessages(index, q_msg); + msg_vec.push_back(q_msg); + seqid_vec.push_back(query_id); + CRef tmp_align; + sa_vec.push_back(tmp_align); + pair tmp_pair(-1.0, -1.0); + CRef tmp_ancillary_data( + new CBlastAncillaryData(tmp_pair, tmp_pair, + tmp_pair, 0)); + + ancill_vec.push_back(tmp_ancillary_data); + + for(unsigned int i=1; i < num_subjects; i++) { + TQueryMessages msg; + msg_vec.push_back(msg); + seqid_vec.push_back(query_id); + CRef tmp_align; + sa_vec.push_back(tmp_align); + CRef tmp_ancillary_data( + new CBlastAncillaryData(tmp_pair, tmp_pair, tmp_pair, 0)); + ancill_vec.push_back(tmp_ancillary_data); + } + } + msg_vec.Combine(prelim_search->GetSearchMessages()); + + // FIXME: Report search messages + } + + try { + prelim_search->SetNumberOfThreads(GetNumberOfThreads()); + // do mapping + m_InternalData = prelim_search->Run(); + + } + catch( CIndexedDbException & ) { + throw; + } + catch (CBlastException & e) { + if(e.GetErrCode() == CBlastException::eCoreBlastError) { + throw; + } + } + catch (...) { + + } + + // close HSP stream and create internal results structure + BlastMappingResults* results = Blast_MappingResultsNew(); + CRef< CStructWrapper > wrapped_results; + wrapped_results.Reset(WrapStruct(results, Blast_MappingResultsFree)); + + BlastHSPStreamMappingClose(m_InternalData->m_HspStream->GetPointer(), + results); + + // create and return results as ASN.1 objects + return x_CreateSeqAlignSet(results); +} + + +void CMagicBlast::x_Validate(void) +{ + if (m_Options.Empty()) { + NCBI_THROW(CBlastException, eInvalidArgument, "Missing options"); + } + + if (m_Queries.Empty()) { + NCBI_THROW(CBlastException, eInvalidArgument, "Missing query"); + } + + if (m_LocalDbAdapter.Empty()) { + NCBI_THROW(CBlastException, eInvalidArgument, + "Missing database or subject sequences"); + } +} + +// Compute BTOP string and percent identity from JumperEdits structure that +// contains base mismatch infotmation +static void s_ComputeBtopAndIdentity(const BlastHSPChain* chain, + string& btop, + double& perc_id) +{ + _ASSERT(chain); + _ASSERT(chain->hsp_array[0]); + const Uint1 kGap = 15; + + int num_identical = 0; + int len = 0; + for (int k=0;k < chain->num_hsps;k++) { + const BlastHSP* hsp = chain->hsp_array[k]; + const JumperEditsBlock* hsp_edits = hsp->map_info->edits; + + if (k > 0) { + const BlastHSP* prev = chain->hsp_array[k - 1]; + int intron = hsp->subject.offset - prev->subject.end; + if (intron > 0) { + btop += (string)"^" + NStr::IntToString(intron) + "^"; + } + + int query_gap = hsp->query.offset - prev->query.end; + if (query_gap > 0) { + btop += (string)"_" + NStr::IntToString(query_gap) + "_"; + } + else if (query_gap < 0) { + btop += (string)"(" + NStr::IntToString(-query_gap) + ")"; + } + + // gap in query on exon edge + if (hsp->query.offset > prev->query.end) { + btop += (string)"_" + + NStr::IntToString(hsp->query.offset - prev->query.end) + + "_"; + + len += hsp->query.offset - prev->query.end; + } + } + + int query_pos = hsp->query.offset; + int num_matches = 0; + for (int i=0;i < hsp_edits->num_edits;i++) { + num_matches = hsp_edits->edits[i].query_pos - query_pos; + query_pos += num_matches; + + _ASSERT(num_matches >= 0); + num_identical += num_matches; + if (num_matches > 0) { + btop += NStr::IntToString(num_matches); + } + + char buff[3]; + buff[0] = BLASTNA_TO_IUPACNA[(int)hsp_edits->edits[i].query_base]; + buff[1] = BLASTNA_TO_IUPACNA[(int)hsp_edits->edits[i].subject_base]; + buff[2] = 0; + btop += (string)buff; + len++; + if (hsp_edits->edits[i].query_base != kGap) { + query_pos++; + } + } + num_matches = hsp->query.end - query_pos; + num_identical += num_matches; + if (num_matches > 0) { + btop += NStr::IntToString(num_matches); + } + } + len += num_identical; + + perc_id = (double)(num_identical * 100) / (double)len; +} + + +static CRef s_CreateSeqAlign(const BlastHSPChain* chain, + CRef& qdata, + CRef& seqinfo_src) +{ + CRef align(new CSeq_align); + align->SetType(CSeq_align::eType_partial); + align->SetDim(2); + + CConstRef query_loc = qdata->GetSeq_loc(chain->query_index); + CRef query_id(new CSeq_id); + SerialAssign(*query_id, CSeq_loc_CI(*query_loc).GetSeq_id()); + _ASSERT(query_id); + TSeqPos query_length = qdata->GetSeqLength(chain->query_index); + + CRef subject_id; + TSeqPos subj_length; + GetSequenceLengthAndId(seqinfo_src, chain->oid, subject_id, + &subj_length); + + + MakeSplicedSeg(align->SetSegs().SetSpliced(), query_id, subject_id, + query_length, chain); + + // alignment score + align->SetNamedScore(CSeq_align::eScore_Score, chain->score); + + // user objec stores auxiliary information needed for various output + // formats + CRef user_object(new CUser_object); + user_object->SetType().SetStr("Mapper Info"); + align->SetExt().push_back(user_object); + // for SAM + // context is needed mostly for printing query sequences, mostly for + // convinience and fast lookup + user_object->AddField("context", chain->hsp_array[0]->context); + user_object->AddField("num_hits", chain->multiplicity); + + // for tabular + string btop; + double perc_id; + s_ComputeBtopAndIdentity(chain, btop, perc_id); + user_object->AddField("btop", btop); + align->SetNamedScore(CSeq_align::eScore_PercentIdentity_Gapped, + perc_id); + + return align; +} + +CRef CMagicBlast::x_CreateSeqAlignSet( + BlastMappingResults* results) +{ + CRef seq_aligns = CreateEmptySeq_align_set(); + + CRef qdata = m_Queries->MakeLocalQueryData(m_Options); + + CRef seqinfo_src; + seqinfo_src.Reset(m_LocalDbAdapter->MakeSeqInfoSrc()); + _ASSERT(seqinfo_src); + seqinfo_src->GarbageCollect(); + + for (int i=0;i < results->num_results;i++) { + // single spliced alignment + BlastHSPChain* chain = results->chain_array[i]; + + // mate pairs are processed together when the first one is encountered, + // so skip the second of the pair + if (chain->pair && chain->query_index > chain->pair->query_index) { + continue; + } + + CRef align; + + // pairs are reported as disc seg alignment composed of two + // spliced segs + if (chain->pair) { + align.Reset(new CSeq_align); + align->SetType(CSeq_align::eType_partial); + align->SetDim(2); + + CSeq_align::TSegs::TDisc& disc = align->SetSegs().SetDisc(); + disc.Set().push_back(s_CreateSeqAlign(chain, qdata, seqinfo_src)); + disc.Set().push_back(s_CreateSeqAlign(chain->pair, qdata, + seqinfo_src)); + } + else { + align = s_CreateSeqAlign(chain, qdata, seqinfo_src); + } + + seq_aligns->Set().push_back(align); + } + + return seq_aligns; +} + + +END_SCOPE(blast) +END_NCBI_SCOPE + +/* @} */ diff --git a/c++/src/algo/blast/api/magicblast_options.cpp b/c++/src/algo/blast/api/magicblast_options.cpp new file mode 100644 index 00000000..dabfb74b --- /dev/null +++ b/c++/src/algo/blast/api/magicblast_options.cpp @@ -0,0 +1,224 @@ +/* $Id: magicblast_options.cpp 506101 2016-07-01 15:47:17Z boratyng $ + * =========================================================================== + * + * PUBLIC DOMAIN NOTICE + * National Center for Biotechnology Information + * + * This software/database is a "United States Government Work" under the + * terms of the United States Copyright Act. It was written as part of + * the author's official duties as a United States Government employee and + * thus cannot be copyrighted. This software/database is freely available + * to the public for use. The National Library of Medicine and the U.S. + * Government have not placed any restriction on its use or reproduction. + * + * Although all reasonable efforts have been taken to ensure the accuracy + * and reliability of the software and data, the NLM and the U.S. + * Government do not and cannot warrant the performance or results that + * may be obtained by using this software or data. The NLM and the U.S. + * Government disclaim all warranties, express or implied, including + * warranties of performance, merchantability or fitness for any particular + * purpose. + * + * Please cite the author in any work or product based on this material. + * + * =========================================================================== + * + * Authors: Greg Boratyn + * + */ + +/// @file blast_mapper_options.cpp +/// Implements the CMagicBlastOptionsHandle class. + +#include +//#include +#include +//#include +//#include "blast_setup.hpp" + +/** @addtogroup AlgoBlast + * + * @{ + */ + + +BEGIN_NCBI_SCOPE +BEGIN_SCOPE(blast) + +CMagicBlastOptionsHandle::CMagicBlastOptionsHandle(EAPILocality locality) + : CBlastOptionsHandle(locality) +{ + SetDefaults(); +} + + +CMagicBlastOptionsHandle::CMagicBlastOptionsHandle(CRef opt) + : CBlastOptionsHandle(opt) +{ +} + + +void +CMagicBlastOptionsHandle::SetDefaults() +{ + m_Opts->SetDefaultsMode(true); + SetRNAToGenomeDefaults(); + m_Opts->SetDefaultsMode(false); +} + +void +CMagicBlastOptionsHandle::SetRNAToGenomeDefaults() +{ + m_Opts->SetDefaultsMode(true); + m_Opts->SetProgram(eMapper); + SetLookupTableDefaults(); + SetQueryOptionDefaults(); + SetInitialWordOptionsDefaults(); + SetGappedExtensionDefaults(); + SetScoringOptionsDefaults(); + SetHitSavingOptionsDefaults(); + SetEffectiveLengthsOptionsDefaults(); + SetSubjectSequenceOptionsDefaults(); + m_Opts->SetDefaultsMode(false); +} + +void +CMagicBlastOptionsHandle::SetRNAToRNADefaults() +{ + m_Opts->SetDefaultsMode(true); + m_Opts->SetProgram(eMapper); + SetLookupTableDefaults(); + SetQueryOptionDefaults(); + SetInitialWordOptionsDefaults(); + SetGappedExtensionDefaults(); + SetScoringOptionsDefaults(); + SetHitSavingOptionsDefaults(); + SetEffectiveLengthsOptionsDefaults(); + SetSubjectSequenceOptionsDefaults(); + + SetMismatchPenalty(-4); + SetGapExtensionCost(4); + SetLookupDbFilter(false); + SetSpliceAlignments(false); + SetWordSize(30); + SetCutoffScore(70); + + m_Opts->SetDefaultsMode(false); +} + + +void +CMagicBlastOptionsHandle::SetGenomeToGenomeDefaults() +{ + m_Opts->SetDefaultsMode(true); + m_Opts->SetProgram(eMapper); + SetLookupTableDefaults(); + SetQueryOptionDefaults(); + SetInitialWordOptionsDefaults(); + SetGappedExtensionDefaults(); + SetScoringOptionsDefaults(); + SetHitSavingOptionsDefaults(); + SetEffectiveLengthsOptionsDefaults(); + SetSubjectSequenceOptionsDefaults(); + + SetMismatchPenalty(-4); + SetGapExtensionCost(4); + SetLookupDbFilter(true); + SetSpliceAlignments(false); + SetWordSize(28); + SetCutoffScore(70); + + m_Opts->SetDefaultsMode(false); +} + +void +CMagicBlastOptionsHandle::SetLookupTableDefaults() +{ + if (getenv("MAPPER_MB_LOOKUP")) { + m_Opts->SetLookupTableType(eMBLookupTable); + } + else { + m_Opts->SetLookupTableType(eNaHashLookupTable); + } + SetWordSize(BLAST_WORDSIZE_MAPPER); + m_Opts->SetWordThreshold(BLAST_WORD_THRESHOLD_BLASTN); + SetLookupTableStride(0); +} + + +void +CMagicBlastOptionsHandle::SetQueryOptionDefaults() +{ + m_Opts->SetDustFiltering(false); + m_Opts->SetMaskAtHash(false); + m_Opts->SetStrandOption(objects::eNa_strand_both); + SetLookupDbFilter(true); + SetPaired(false); +} + +void +CMagicBlastOptionsHandle::SetInitialWordOptionsDefaults() +{ +} + +void +CMagicBlastOptionsHandle::SetGappedExtensionDefaults() +{ + m_Opts->SetGapExtnAlgorithm(eJumperWithTraceback); + m_Opts->SetMaxMismatches(5); + m_Opts->SetMismatchWindow(10); + SetSpliceAlignments(true); +} + + +void +CMagicBlastOptionsHandle::SetScoringOptionsDefaults() +{ + m_Opts->SetMatrixName(NULL); + SetGapOpeningCost(BLAST_GAP_OPEN_MAPPER); + SetGapExtensionCost(BLAST_GAP_EXTN_MAPPER); + m_Opts->SetMatchReward(BLAST_REWARD_MAPPER); + SetMismatchPenalty(BLAST_PENALTY_MAPPER); + m_Opts->SetGappedMode(); + m_Opts->SetComplexityAdjMode(false); + + // set out-of-frame options to invalid? values + m_Opts->SetOutOfFrameMode(false); + m_Opts->SetFrameShiftPenalty(INT2_MAX); +} + +void +CMagicBlastOptionsHandle::SetHitSavingOptionsDefaults() +{ + m_Opts->SetHitlistSize(500); + m_Opts->SetEvalueThreshold(BLAST_EXPECT_VALUE); + m_Opts->SetPercentIdentity(0); + // set some default here, allow INT4MAX to mean infinity + m_Opts->SetMaxNumHspPerSequence(0); + m_Opts->SetMaxHspsPerSubject(0); + SetCutoffScore(20); + SetLongestIntronLength(2000); + + // do not compute each query's ungapped alignment score threshold to + // trigger gapped alignment + m_Opts->SetLowScorePerc(0.0); + m_Opts->SetQueryCovHspPerc(0); +} + +void +CMagicBlastOptionsHandle::SetEffectiveLengthsOptionsDefaults() +{ + m_Opts->SetDbLength(0); + m_Opts->SetDbSeqNum(0); + m_Opts->SetEffectiveSearchSpace(0); +} + +void +CMagicBlastOptionsHandle::SetSubjectSequenceOptionsDefaults() +{} + +END_SCOPE(blast) +END_NCBI_SCOPE + + +/* @} */ diff --git a/c++/src/algo/blast/api/msa_pssm_input.cpp b/c++/src/algo/blast/api/msa_pssm_input.cpp index f7490138..6887ab45 100644 --- a/c++/src/algo/blast/api/msa_pssm_input.cpp +++ b/c++/src/algo/blast/api/msa_pssm_input.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: msa_pssm_input.cpp 483145 2015-10-28 17:43:30Z boratyng $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/algo/blast/api/objmgr_query_data.cpp b/c++/src/algo/blast/api/objmgr_query_data.cpp index 7fb8cbf7..3f7e0f50 100644 --- a/c++/src/algo/blast/api/objmgr_query_data.cpp +++ b/c++/src/algo/blast/api/objmgr_query_data.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: objmgr_query_data.cpp 382043 2012-12-03 13:33:06Z madden $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * diff --git a/c++/src/algo/blast/api/objmgrfree_query_data.cpp b/c++/src/algo/blast/api/objmgrfree_query_data.cpp index 78d728c9..365d7784 100644 --- a/c++/src/algo/blast/api/objmgrfree_query_data.cpp +++ b/c++/src/algo/blast/api/objmgrfree_query_data.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: objmgrfree_query_data.cpp 103491 2007-05-04 17:18:18Z kazimird $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * diff --git a/c++/src/algo/blast/api/prelim_search_runner.hpp b/c++/src/algo/blast/api/prelim_search_runner.hpp index c906c548..98326448 100644 --- a/c++/src/algo/blast/api/prelim_search_runner.hpp +++ b/c++/src/algo/blast/api/prelim_search_runner.hpp @@ -1,4 +1,4 @@ -/* $Id: prelim_search_runner.hpp 369355 2012-07-18 17:07:15Z morgulis $ +/* $Id: prelim_search_runner.hpp 516335 2016-10-12 17:31:18Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -113,23 +113,30 @@ public: : m_InternalData(internal_data), m_OptsMemento(opts_memento) { // The following fields need to be copied to ensure MT-safety - BlastSeqSrc* seqsrc = + BlastSeqSrc* seqsrc = BlastSeqSrcCopy(m_InternalData.m_SeqSrc->GetPointer()); - m_InternalData.m_SeqSrc.Reset(new TBlastSeqSrc(seqsrc, + m_InternalData.m_SeqSrc.Reset(new TBlastSeqSrc(seqsrc, BlastSeqSrcFree)); // The progress field must be copied to ensure MT-safety if (m_InternalData.m_ProgressMonitor->Get()) { - SBlastProgress* bp = + SBlastProgress* bp = SBlastProgressNew(m_InternalData.m_ProgressMonitor->Get()->user_data); m_InternalData.m_ProgressMonitor.Reset(new CSBlastProgress(bp)); } + // The BlastQueryInfo field needs to be copied to silence Thread + // Sanitizer warnings, and probably to ensure MT-safety too. + BlastQueryInfo* queryInfo = + BlastQueryInfoDup(m_InternalData.m_QueryInfo); + m_InternalData.m_QueryInfo = queryInfo; } protected: - virtual ~CPrelimSearchThread(void) {} + virtual ~CPrelimSearchThread(void) { + BlastQueryInfoFree(m_InternalData.m_QueryInfo); + } virtual void* Main(void) { - return (void*) + return (void*) ((intptr_t) CPrelimSearchRunner(m_InternalData, m_OptsMemento)()); } diff --git a/c++/src/algo/blast/api/prelim_stage.cpp b/c++/src/algo/blast/api/prelim_stage.cpp index 32ad3996..a357550d 100644 --- a/c++/src/algo/blast/api/prelim_stage.cpp +++ b/c++/src/algo/blast/api/prelim_stage.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: prelim_stage.cpp 479444 2015-09-21 13:43:44Z fongah2 $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/algo/blast/api/psi_pssm_input.cpp b/c++/src/algo/blast/api/psi_pssm_input.cpp index 28007f46..c8346c36 100644 --- a/c++/src/algo/blast/api/psi_pssm_input.cpp +++ b/c++/src/algo/blast/api/psi_pssm_input.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: psi_pssm_input.cpp 347205 2011-12-14 20:08:44Z boratyng $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/algo/blast/api/psibl2seq.cpp b/c++/src/algo/blast/api/psibl2seq.cpp index 2dd285bc..89c6763d 100644 --- a/c++/src/algo/blast/api/psibl2seq.cpp +++ b/c++/src/algo/blast/api/psibl2seq.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: psibl2seq.cpp 413493 2013-09-16 17:55:21Z boratyng $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/algo/blast/api/psiblast.cpp b/c++/src/algo/blast/api/psiblast.cpp index cfb9c509..248997d9 100644 --- a/c++/src/algo/blast/api/psiblast.cpp +++ b/c++/src/algo/blast/api/psiblast.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: psiblast.cpp 219104 2011-01-06 13:31:19Z madden $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/algo/blast/api/psiblast_aux_priv.cpp b/c++/src/algo/blast/api/psiblast_aux_priv.cpp index 14b117a1..e88e4c78 100644 --- a/c++/src/algo/blast/api/psiblast_aux_priv.cpp +++ b/c++/src/algo/blast/api/psiblast_aux_priv.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: psiblast_aux_priv.cpp 488748 2016-01-05 16:40:40Z ivanov $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * diff --git a/c++/src/algo/blast/api/psiblast_impl.cpp b/c++/src/algo/blast/api/psiblast_impl.cpp index 2e3d4c02..afbd5b0a 100644 --- a/c++/src/algo/blast/api/psiblast_impl.cpp +++ b/c++/src/algo/blast/api/psiblast_impl.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: psiblast_impl.cpp 327673 2011-07-28 14:30:03Z camacho $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * diff --git a/c++/src/algo/blast/api/psiblast_iteration.cpp b/c++/src/algo/blast/api/psiblast_iteration.cpp index 863d87a7..f6e51812 100644 --- a/c++/src/algo/blast/api/psiblast_iteration.cpp +++ b/c++/src/algo/blast/api/psiblast_iteration.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: psiblast_iteration.cpp 161402 2009-05-27 17:35:47Z camacho $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * diff --git a/c++/src/algo/blast/api/pssm_engine.cpp b/c++/src/algo/blast/api/pssm_engine.cpp index 4a15780c..884ccd7e 100644 --- a/c++/src/algo/blast/api/pssm_engine.cpp +++ b/c++/src/algo/blast/api/pssm_engine.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: pssm_engine.cpp 347205 2011-12-14 20:08:44Z boratyng $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/algo/blast/api/query_data.cpp b/c++/src/algo/blast/api/query_data.cpp index 4ae2e5da..b225f583 100644 --- a/c++/src/algo/blast/api/query_data.cpp +++ b/c++/src/algo/blast/api/query_data.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: query_data.cpp 315260 2011-07-22 13:48:03Z camacho $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * diff --git a/c++/src/algo/blast/api/remote_blast.cpp b/c++/src/algo/blast/api/remote_blast.cpp index 67465177..a2bc58c6 100644 --- a/c++/src/algo/blast/api/remote_blast.cpp +++ b/c++/src/algo/blast/api/remote_blast.cpp @@ -1,4 +1,4 @@ -/* $Id: remote_blast.cpp 495288 2016-03-16 14:51:11Z ivanov $ +/* $Id: remote_blast.cpp 505424 2016-06-24 16:19:35Z merezhuk $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -2493,11 +2494,9 @@ CRemoteBlast::x_GetSearchResultsHTTP(void) bool l_cached_ok = true; auto_ptr tmp_stream( CDirEntry::CreateTmpFile() ); - do{ - ios.readsome(incoming_buffer, read_max); - n_read = ios.gcount(); - if( n_read >= 0 ){ + n_read = CStreamUtils::Readsome(ios,incoming_buffer, read_max); + if( n_read > 0 ){ l_total_bytes += n_read; try{ tmp_stream->write(incoming_buffer,n_read); @@ -2513,10 +2512,11 @@ CRemoteBlast::x_GetSearchResultsHTTP(void) LOG_POST(Error << "CRemoteBlast::x_GetSearchResultsHTTP CAN'T WRITE CACHED DATA: "<seekg(0); // read cached answer swatch.Restart(); - { + try { auto_ptr in_stream( CObjectIStream::Open(eSerial_AsnBinary, *tmp_stream) ); in_stream->Read(ObjectInfo(*one_reply), CObjectIStream::eNoFileHeader); } - + catch(...){ + LOG_POST(Info << "CRemoteBlast::x_GetSearchResultsHTTP: DISABLE CACHE, CAN'T READ CACHED FILE, RE-READ"); + m_use_disk_cache = false; + m_disk_cache_error_flag = true; + return x_GetSearchResults(); + } swatch.Stop(); return one_reply ; diff --git a/c++/src/algo/blast/api/remote_search.cpp b/c++/src/algo/blast/api/remote_search.cpp index dea41f1b..ebec4548 100644 --- a/c++/src/algo/blast/api/remote_search.cpp +++ b/c++/src/algo/blast/api/remote_search.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: remote_search.cpp 481634 2015-10-14 15:21:43Z fongah2 $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/algo/blast/api/repeats_filter_cxx.cpp b/c++/src/algo/blast/api/repeats_filter_cxx.cpp index 443a68fa..da3d3edc 100644 --- a/c++/src/algo/blast/api/repeats_filter_cxx.cpp +++ b/c++/src/algo/blast/api/repeats_filter_cxx.cpp @@ -1,4 +1,4 @@ -/* $Id: repeats_filter_cxx.cpp 378639 2012-10-23 15:05:33Z camacho $ +/* $Id: repeats_filter_cxx.cpp 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -35,11 +35,6 @@ /// @file repeats_filter_cxx.cpp /// C++ version of repeats filtering - -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = "$Id: repeats_filter_cxx.cpp 378639 2012-10-23 15:05:33Z camacho $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include diff --git a/c++/src/algo/blast/api/rps_aux.cpp b/c++/src/algo/blast/api/rps_aux.cpp index 3ed17a09..cea4c256 100644 --- a/c++/src/algo/blast/api/rps_aux.cpp +++ b/c++/src/algo/blast/api/rps_aux.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: rps_aux.cpp 382056 2012-12-03 15:31:14Z boratyng $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/algo/blast/api/rpstblastn_options.cpp b/c++/src/algo/blast/api/rpstblastn_options.cpp index 7e7c7c4e..699bb8a8 100644 --- a/c++/src/algo/blast/api/rpstblastn_options.cpp +++ b/c++/src/algo/blast/api/rpstblastn_options.cpp @@ -1,4 +1,4 @@ -/* $Id: rpstblastn_options.cpp 440360 2014-07-11 17:28:33Z madden $ +/* $Id: rpstblastn_options.cpp 505234 2016-06-23 13:16:57Z fongah2 $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -54,14 +54,12 @@ void CRPSTBlastnOptionsHandle::SetGappedExtensionDefaults() { CBlastRPSOptionsHandle::SetGappedExtensionDefaults(); - SetCompositionBasedStats(false); } void CRPSTBlastnOptionsHandle::SetQueryOptionDefaults() { - SetSegFiltering(true); m_Opts->SetQueryGeneticCode(BLAST_GENETIC_CODE); } diff --git a/c++/src/algo/blast/api/seedtop.cpp b/c++/src/algo/blast/api/seedtop.cpp index 3e16f4b3..cec7ec2c 100644 --- a/c++/src/algo/blast/api/seedtop.cpp +++ b/c++/src/algo/blast/api/seedtop.cpp @@ -1,4 +1,4 @@ -/* $Id: seedtop.cpp 442850 2014-08-07 17:34:09Z camacho $ +/* $Id: seedtop.cpp 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -86,7 +86,7 @@ void CSeedTop::x_MakeLookupTable() // Lookup segments, scoreblk, and rps info arguments are irrelevant // and passed as NULL. LookupTableWrapInit(NULL, lookup_options, NULL, NULL, - m_ScoreBlk, &m_Lookup, NULL, NULL); + m_ScoreBlk, &m_Lookup, NULL, NULL, NULL); } void CSeedTop::x_MakeScoreBlk() diff --git a/c++/src/algo/blast/api/seqinfosrc_bioseq.cpp b/c++/src/algo/blast/api/seqinfosrc_bioseq.cpp index dbefe014..bc4a1b91 100644 --- a/c++/src/algo/blast/api/seqinfosrc_bioseq.cpp +++ b/c++/src/algo/blast/api/seqinfosrc_bioseq.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: seqinfosrc_bioseq.cpp 170794 2009-09-16 18:53:03Z maning $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/algo/blast/api/seqinfosrc_bioseq.hpp b/c++/src/algo/blast/api/seqinfosrc_bioseq.hpp index 1f6e70b7..35b4a61b 100644 --- a/c++/src/algo/blast/api/seqinfosrc_bioseq.hpp +++ b/c++/src/algo/blast/api/seqinfosrc_bioseq.hpp @@ -1,7 +1,7 @@ #ifndef ALGO_BLAST_API__SEQINFOSRC_BIOSEQ__HPP #define ALGO_BLAST_API__SEQINFOSRC_BIOSEQ__HPP -/* $Id: seqinfosrc_bioseq.hpp 499810 2016-04-28 15:43:25Z ivanov $ +/* $Id: seqinfosrc_bioseq.hpp 499693 2016-04-27 17:19:56Z madden $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/algo/blast/api/seqinfosrc_seqdb.cpp b/c++/src/algo/blast/api/seqinfosrc_seqdb.cpp index 483222ad..a2203814 100644 --- a/c++/src/algo/blast/api/seqinfosrc_seqdb.cpp +++ b/c++/src/algo/blast/api/seqinfosrc_seqdb.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: seqinfosrc_seqdb.cpp 315260 2011-07-22 13:48:03Z camacho $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/algo/blast/api/seqinfosrc_seqvec.cpp b/c++/src/algo/blast/api/seqinfosrc_seqvec.cpp index a4c5f316..4d3e2856 100644 --- a/c++/src/algo/blast/api/seqinfosrc_seqvec.cpp +++ b/c++/src/algo/blast/api/seqinfosrc_seqvec.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: seqinfosrc_seqvec.cpp 435182 2014-05-14 14:05:21Z fongah2 $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/algo/blast/api/seqsrc_seqdb.cpp b/c++/src/algo/blast/api/seqsrc_seqdb.cpp index 92054bcf..e4b0a9a9 100644 --- a/c++/src/algo/blast/api/seqsrc_seqdb.cpp +++ b/c++/src/algo/blast/api/seqsrc_seqdb.cpp @@ -1,4 +1,4 @@ -/* $Id: seqsrc_seqdb.cpp 481634 2015-10-14 15:21:43Z fongah2 $ +/* $Id: seqsrc_seqdb.cpp 510159 2016-08-11 11:28:47Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -56,44 +56,46 @@ struct SSeqDB_SeqSrc_Data { : copied(false) { } - + /// Constructor. SSeqDB_SeqSrc_Data(CSeqDB * ptr, int id, ESubjectMaskingType type) - : seqdb((CSeqDBExpert*) ptr), + : seqdb((CSeqDBExpert*) ptr), mask_algo_id(id), mask_type(type), - copied(false) + copied(false), + isProtein(seqdb->GetSequenceType() == CSeqDB::eProtein) { } - + /// Make a copy of this object, sharing the same SeqDB object. SSeqDB_SeqSrc_Data * clone() { return new SSeqDB_SeqSrc_Data(&* seqdb, mask_algo_id, mask_type); } - + /// Convenience to allow datap->method to use SeqDB methods. CSeqDBExpert * operator->() { _ASSERT(! seqdb.Empty()); return &*seqdb; } - + /// Convenience to allow datap->method to use SeqDB methods. CSeqDBExpert & operator*() { _ASSERT(! seqdb.Empty()); return *seqdb; } - + /// SeqDB object. CRef seqdb; - + /// Algorithm ID and type for mask data fetching. int mask_algo_id; ESubjectMaskingType mask_type; bool copied; - + bool isProtein; + #if ((!defined(NCBI_COMPILER_WORKSHOP) || (NCBI_COMPILER_VERSION > 550)) && \ (!defined(NCBI_COMPILER_MIPSPRO)) ) /// Ranges of the sequence to include (for masking). @@ -111,9 +113,9 @@ static Blast_GiList* s_SeqDbGetGiList(void* seqdb_handle, void* args) { CSeqDB & seqdb = **(TSeqDBData *) seqdb_handle; - + Int4* oid = (Int4*) args; - + if (!datap || !oid) return NULL; @@ -131,7 +133,7 @@ s_SeqDbGetGiList(void* seqdb_handle, void* args) /// Retrieves the length of the longest sequence in the BlastSeqSrc. /// @param seqdb_handle Pointer to initialized CSeqDB object [in] -static Int4 +static Int4 s_SeqDbGetMaxLength(void* seqdb_handle, void*) { CSeqDB & seqdb = **(TSeqDBData *) seqdb_handle; @@ -140,7 +142,7 @@ s_SeqDbGetMaxLength(void* seqdb_handle, void*) /// Retrieves the length of the shortest sequence in the BlastSeqSrc. /// @param seqdb_handle Pointer to initialized CSeqDB object [in] -static Int4 +static Int4 s_SeqDbGetMinLength(void* seqdb_handle, void*) { CSeqDB & seqdb = **(TSeqDBData *) seqdb_handle; @@ -158,7 +160,7 @@ s_SeqDbSetNumberOfThreads(void* seqdb_handle, int n) /// Retrieves the number of sequences in the BlastSeqSrc. /// @param seqdb_handle Pointer to initialized CSeqDB object [in] -static Int4 +static Int4 s_SeqDbGetNumSeqs(void* seqdb_handle, void*) { CSeqDB & seqdb = **(TSeqDBData *) seqdb_handle; @@ -168,7 +170,7 @@ s_SeqDbGetNumSeqs(void* seqdb_handle, void*) /// Retrieves the number of sequences from alias file to be used for // search-space calculations. /// @param seqdb_handle Pointer to initialized CSeqDB object [in] -static Int4 +static Int4 s_SeqDbGetNumSeqsStats(void* seqdb_handle, void*) { CSeqDB & seqdb = **(TSeqDBData *) seqdb_handle; @@ -177,7 +179,7 @@ s_SeqDbGetNumSeqsStats(void* seqdb_handle, void*) /// Retrieves the total length of all sequences in the BlastSeqSrc. /// @param seqdb_handle Pointer to initialized CSeqDB object [in] -static Int8 +static Int8 s_SeqDbGetTotLen(void* seqdb_handle, void*) { CSeqDB & seqdb = **(TSeqDBData *) seqdb_handle; @@ -187,17 +189,17 @@ s_SeqDbGetTotLen(void* seqdb_handle, void*) /// Retrieves the total length of all sequences from alias file // to be used for search space calculations. /// @param seqdb_handle Pointer to initialized CSeqDB object [in] -static Int8 +static Int8 s_SeqDbGetTotLenStats(void* seqdb_handle, void*) { CSeqDB & seqdb = **(TSeqDBData *) seqdb_handle; - return seqdb.GetTotalLengthStats(); + return seqdb.GetTotalLengthStats(); } /// Retrieves the average length of sequences in the BlastSeqSrc. /// @param seqdb_handle Pointer to initialized CSeqDB object [in] /// @param ignoreme Unused by this implementation [in] -static Int4 +static Int4 s_SeqDbGetAvgLength(void* seqdb_handle, void* ignoreme) { Int8 total_length = s_SeqDbGetTotLen(seqdb_handle, ignoreme); @@ -208,7 +210,7 @@ s_SeqDbGetAvgLength(void* seqdb_handle, void* ignoreme) /// Retrieves the name of the BLAST database. /// @param seqdb_handle Pointer to initialized CSeqDB object [in] -static const char* +static const char* s_SeqDbGetName(void* seqdb_handle, void*) { CSeqDB & seqdb = **(TSeqDBData *) seqdb_handle; @@ -218,27 +220,29 @@ s_SeqDbGetName(void* seqdb_handle, void*) /// Checks whether database is protein or nucleotide. /// @param seqdb_handle Pointer to initialized CSeqDB object [in] /// @return TRUE if database is protein, FALSE if nucleotide. -static Boolean +static Boolean s_SeqDbGetIsProt(void* seqdb_handle, void*) { - CSeqDB & seqdb = **(TSeqDBData *) seqdb_handle; + TSeqDBData * datap = (TSeqDBData *) seqdb_handle; - return (seqdb.GetSequenceType() == CSeqDB::eProtein); + return datap->isProtein; } /// Determine if partial fetching should be enabled /// @param seqdb_handle Pointer to initialized CSeqDB object [in] static Boolean -s_SeqDbGetSupportsPartialFetching(void* seqdb_handle, void*) +s_SeqDbGetSupportsPartialFetching(void* seqdb_handle, void*) { - CSeqDB & seqdb = **(TSeqDBData *) seqdb_handle; - - if (seqdb.GetSequenceType() != CSeqDB::eNucleotide) { + TSeqDBData * datap = (TSeqDBData *) seqdb_handle; + + if (datap->isProtein == true) { // don't bother doing this for proteins as the sequences are // never long enough to cause performance degredation return false; } + CSeqDB & seqdb = **(TSeqDBData *) seqdb_handle; + // If longest sequence is below this we quit static const int kMaxLengthCutoff = 5000; if (seqdb.GetMaxLength() < kMaxLengthCutoff) { @@ -266,7 +270,7 @@ s_SeqDbSetRanges(void* seqdb_handle, BlastSeqSrcSetRangesArg* args) if (!seqdb_handle || !args) return; CSeqDB & seqdb = **(TSeqDBData *) seqdb_handle; - + CSeqDB::TRangeList ranges; for (int i=0; i< args->num_ranges; ++i) { ranges.insert(pair (args->ranges[i*2], args->ranges[i*2+1])); @@ -279,118 +283,117 @@ s_SeqDbSetRanges(void* seqdb_handle, BlastSeqSrcSetRangesArg* args) /// @param seqdb_handle Pointer to initialized CSeqDB object [in] /// @param args Pointer to BlastSeqSrcGetSeqArg structure [in] /// @return return codes defined in blast_seqsrc.h -static Int2 +static Int2 s_SeqDbGetSequence(void* seqdb_handle, BlastSeqSrcGetSeqArg* args) { Int4 oid = -1, len = 0; Boolean has_sentinel_byte; - + if (!seqdb_handle || !args) return BLAST_SEQSRC_ERROR; - + TSeqDBData * datap = (TSeqDBData *) seqdb_handle; - + CSeqDBExpert & seqdb = **datap; - + oid = args->oid; // If we are asked to check for OID exclusion, and if the database // has a GI list, then we check whether all the seqids have been // removed by filtering. If so we return an error. The traceback // code will exclude this HSP list. - + if (args->check_oid_exclusion) { if (! seqdb.GetIdSet().Blank()) { list< CRef > seqids = seqdb.GetSeqIDs(oid); - + if (seqids.empty()) { return BLAST_SEQSRC_EXCLUDED; } } } - + #if ((!defined(NCBI_COMPILER_WORKSHOP) || (NCBI_COMPILER_VERSION > 550)) && \ (!defined(NCBI_COMPILER_MIPSPRO)) ) - if (datap->mask_type != eNoSubjMasking) { + if (datap->mask_type != eNoSubjMasking) { ASSERT(datap->mask_algo_id != -1); seqdb.GetMaskData(oid, datap->mask_algo_id, datap->seq_ranges); } #endif datap->copied = false; - - if ( args->encoding == eBlastEncodingNucleotide - || args->encoding == eBlastEncodingNcbi4na - || (datap->mask_type == eHardSubjMasking + + if ( args->encoding == eBlastEncodingNucleotide + || args->encoding == eBlastEncodingNcbi4na + || (datap->mask_type == eHardSubjMasking && !(datap->seq_ranges.empty()) && args->check_oid_exclusion)) datap->copied = true; has_sentinel_byte = (args->encoding == eBlastEncodingNucleotide); - + /* free buffers if necessary */ if (args->seq) BlastSequenceBlkClean(args->seq); - + /* This occurs if the pre-selected partial sequence in the traceback stage * was too small to perform the traceback. Only do this for nucleotide * sequences as proteins are not long enough to be of significance */ - if (args->reset_ranges && seqdb.GetSequenceType() == CSeqDB::eNucleotide) { + if (args->reset_ranges && datap->isProtein == false) seqdb.RemoveOffsetRanges(oid); - } - + const char *buf; - len = (datap->copied) + len = (datap->copied) /* This will consume and clear datap->seq_ranges */ - ? seqdb.GetAmbigSeqAlloc(oid, - const_cast(&buf), - has_sentinel_byte, + ? seqdb.GetAmbigSeqAlloc(oid, + const_cast(&buf), + has_sentinel_byte, eMalloc, ((datap->mask_type == eHardSubjMasking) ? &(datap->seq_ranges) : NULL)) : seqdb.GetSequence(oid, &buf); - + if (len <= 0) return BLAST_SEQSRC_ERROR; - + BlastSetUp_SeqBlkNew((Uint1*)buf, len, &args->seq, datap->copied); - + /* If there is no sentinel byte, and buffer is allocated, i.e. this is - the traceback stage of a translated search, set "sequence" to the same + the traceback stage of a translated search, set "sequence" to the same position as "sequence_start". */ if (datap->copied && !has_sentinel_byte) args->seq->sequence = args->seq->sequence_start; - + /* For preliminary stage, even though sequence buffer points to a memory mapped location, we still need to call ReleaseSequence. This can only be guaranteed by making the engine believe tat sequence is allocated. */ if (!datap->copied) args->seq->sequence_allocated = TRUE; - + args->seq->oid = oid; #if ((!defined(NCBI_COMPILER_WORKSHOP) || (NCBI_COMPILER_VERSION > 550)) && \ (!defined(NCBI_COMPILER_MIPSPRO)) ) /* If masks have not been consumed (scanning phase), pass on to engine */ if (datap->mask_type != eNoSubjMasking) { - if (BlastSeqBlkSetSeqRanges(args->seq, + if (BlastSeqBlkSetSeqRanges(args->seq, (SSeqRange*) datap->seq_ranges.get_data(), datap->seq_ranges.size() + 1, false, datap->mask_type) != 0) { return BLAST_SEQSRC_ERROR; } } #endif - + return BLAST_SEQSRC_SUCCESS; } -/// Returns the memory allocated for the sequence buffer to the CSeqDB +/// Returns the memory allocated for the sequence buffer to the CSeqDB /// interface. /// @param seqdb_handle Pointer to initialized CSeqDB object [in] -/// @param args Pointer to the BlastSeqSrcGetSeqArgs structure, +/// @param args Pointer to the BlastSeqSrcGetSeqArgs structure, /// containing sequence block with the buffer that needs to be deallocated. [in] static void s_SeqDbReleaseSequence(void* seqdb_handle, BlastSeqSrcGetSeqArg* args) { TSeqDBData * datap = (TSeqDBData *) seqdb_handle; - + CSeqDB & seqdb = **(TSeqDBData *) seqdb_handle; _ASSERT(seqdb_handle); @@ -398,8 +401,7 @@ s_SeqDbReleaseSequence(void* seqdb_handle, BlastSeqSrcGetSeqArg* args) _ASSERT(args->seq); if (args->seq->sequence_start_allocated) { - ASSERT (datap->copied); - sfree(args->seq->sequence_start); + if (datap->copied) sfree(args->seq->sequence_start); args->seq->sequence_start_allocated = FALSE; args->seq->sequence_start = NULL; } @@ -415,7 +417,7 @@ s_SeqDbReleaseSequence(void* seqdb_handle, BlastSeqSrcGetSeqArg* args) /// @param seqdb_handle Pointer to initialized CSeqDB object [in] /// @param args Pointer to integer indicating ordinal id [in] /// @return Length of the database sequence or BLAST_SEQSRC_ERROR. -static Int4 +static Int4 s_SeqDbGetSeqLen(void* seqdb_handle, void* args) { Int4* oid = (Int4*) args; @@ -428,23 +430,23 @@ s_SeqDbGetSeqLen(void* seqdb_handle, void* args) } /// Assigns next chunk of the database to the sequence source iterator. -/// @param seqdb_handle Reference to the database object, cast to void* to +/// @param seqdb_handle Reference to the database object, cast to void* to /// satisfy the signature requirement. [in] /// @param itr Iterator over the database sequence source. [in|out] -static Int2 +static Int2 s_SeqDbGetNextChunk(void* seqdb_handle, BlastSeqSrcIterator* itr) { if (!seqdb_handle || !itr) return BLAST_SEQSRC_ERROR; - + CSeqDB & seqdb = **(TSeqDBData *) seqdb_handle; - + vector oid_list; - CSeqDB::EOidListType chunk_type = - seqdb.GetNextOIDChunk(itr->oid_range[0], itr->oid_range[1], + CSeqDB::EOidListType chunk_type = + seqdb.GetNextOIDChunk(itr->oid_range[0], itr->oid_range[1], itr->chunk_sz, oid_list); - + if (itr->oid_range[1] <= itr->oid_range[0]) return BLAST_SEQSRC_EOF; @@ -457,7 +459,7 @@ s_SeqDbGetNextChunk(void* seqdb_handle, BlastSeqSrcIterator* itr) if (new_sz > 0) { itr->current_pos = 0; Uint4 index; - if (itr->chunk_sz < new_sz) { + if (itr->chunk_sz < new_sz) { sfree(itr->oid_list); itr->oid_list = (int *) malloc (new_sz * sizeof(int)); } @@ -473,11 +475,11 @@ s_SeqDbGetNextChunk(void* seqdb_handle, BlastSeqSrcIterator* itr) } /// Finds the next not searched ordinal id in the iteration over BLAST database. -/// @param seqdb_handle Reference to the database object, cast to void* to +/// @param seqdb_handle Reference to the database object, cast to void* to /// satisfy the signature requirement. [in] /// @param itr Iterator of the BlastSeqSrc pointed by ptr. [in] /// @return Next ordinal id. -static Int4 +static Int4 s_SeqDbIteratorNext(void* seqdb_handle, BlastSeqSrcIterator* itr) { Int4 retval = BLAST_SEQSRC_EOF; @@ -486,7 +488,7 @@ s_SeqDbIteratorNext(void* seqdb_handle, BlastSeqSrcIterator* itr) _ASSERT(seqdb_handle); _ASSERT(itr); - /* If internal iterator is uninitialized/invalid, retrieve the next chunk + /* If internal iterator is uninitialized/invalid, retrieve the next chunk from the BlastSeqSrc */ if (itr->current_pos == UINT4_MAX) { status = s_SeqDbGetNextChunk(seqdb_handle, itr); @@ -518,7 +520,7 @@ s_SeqDbIteratorNext(void* seqdb_handle, BlastSeqSrcIterator* itr) } /// Resets CSeqDB's internal chunk bookmark -/// @param seqdb_handle Reference to the database object, cast to void* to +/// @param seqdb_handle Reference to the database object, cast to void* to /// satisfy the signature requirement. [in] static void s_SeqDbResetChunkIterator(void* seqdb_handle) @@ -541,9 +543,9 @@ public: /// Constructor CSeqDbSrcNewArgs(const string& db, bool is_prot, Uint4 first_oid = 0, Uint4 final_oid = 0, - Int4 mask_algo_id = -1, + Int4 mask_algo_id = -1, ESubjectMaskingType mask_type = eNoSubjMasking) - : m_DbName(db), m_IsProtein(is_prot), + : m_DbName(db), m_IsProtein(is_prot), m_FirstDbSeq(first_oid), m_FinalDbSeq(final_oid), m_MaskAlgoId(mask_algo_id), m_MaskType(mask_type) {} @@ -576,15 +578,15 @@ extern "C" { /// SeqDb sequence source destructor: frees its internal data structure /// @param seq_src BlastSeqSrc structure to free [in] /// @return NULL -static BlastSeqSrc* +static BlastSeqSrc* s_SeqDbSrcFree(BlastSeqSrc* seq_src) { - if (!seq_src) + if (!seq_src) return NULL; - + TSeqDBData * datap = static_cast (_BlastSeqSrcImpl_GetDataStructure(seq_src)); - + delete datap; return NULL; } @@ -593,30 +595,30 @@ s_SeqDbSrcFree(BlastSeqSrc* seq_src) /// and copies the rest of the BlastSeqSrc structure. /// @param seq_src BlastSeqSrc structure to copy [in] /// @return Pointer to the new BlastSeqSrc. -static BlastSeqSrc* +static BlastSeqSrc* s_SeqDbSrcCopy(BlastSeqSrc* seq_src) { - if (!seq_src) + if (!seq_src) return NULL; - + TSeqDBData * datap = static_cast (_BlastSeqSrcImpl_GetDataStructure(seq_src)); - + _BlastSeqSrcImpl_SetDataStructure(seq_src, (void*) datap->clone()); - + return seq_src; } -/// Initializes the data structure and function pointers in a SeqDb based +/// Initializes the data structure and function pointers in a SeqDb based /// BlastSeqSrc. /// @param retval Structure to populate [in] [out] /// @param seqdb Reference to a CSeqDB object [in] -static void +static void s_InitNewSeqDbSrc(BlastSeqSrc* retval, TSeqDBData * datap) { _ASSERT(retval); _ASSERT(datap); - + /* Initialize the BlastSeqSrc structure fields with user-defined function * pointers and seqdb */ _BlastSeqSrcImpl_SetDeleteFnPtr (retval, & s_SeqDbSrcFree); @@ -644,53 +646,54 @@ s_InitNewSeqDbSrc(BlastSeqSrc* retval, TSeqDBData * datap) #endif /* KAPPA_PRINT_DIAGNOSTICS */ } -/// Populates a BlastSeqSrc, creating a new reference to the already existing +/// Populates a BlastSeqSrc, creating a new reference to the already existing /// SeqDb object. /// @param retval Original BlastSeqSrc [in] /// @param args Pointer to a reference to CSeqDB object [in] /// @return retval -static BlastSeqSrc* +static BlastSeqSrc* s_SeqDbSrcSharedNew(BlastSeqSrc* retval, void* args) { _ASSERT(retval); _ASSERT(args); - + TSeqDBData * datap = (TSeqDBData *) args; - + s_InitNewSeqDbSrc(retval, datap->clone()); - + return retval; } -/// SeqDb sequence source constructor +/// SeqDb sequence source constructor /// @param retval BlastSeqSrc structure (already allocated) to populate [in] /// @param args Pointer to internal CSeqDbSrcNewArgs structure (@sa /// CSeqDbSrcNewArgs) [in] /// @return Updated seq_src structure (with all function pointers initialized -static BlastSeqSrc* +static BlastSeqSrc* s_SeqDbSrcNew(BlastSeqSrc* retval, void* args) { _ASSERT(retval); _ASSERT(args); - + CSeqDbSrcNewArgs* seqdb_args = (CSeqDbSrcNewArgs*) args; _ASSERT(seqdb_args); - + TSeqDBData * datap = new TSeqDBData; - + try { bool is_protein = (seqdb_args->GetDbType() == 'p'); - + datap->seqdb.Reset(new CSeqDBExpert(seqdb_args->GetDbName(), (is_protein ? CSeqDB::eProtein : CSeqDB::eNucleotide))); - + datap->seqdb->SetIterationRange(seqdb_args->GetFirstOid(), seqdb_args->GetFinalOid()); - + datap->mask_algo_id = seqdb_args->GetMaskAlgoId(); datap->mask_type = seqdb_args->GetMaskType(); + datap->isProtein = is_protein; // Validate that the masking algorithm is supported if (datap->mask_algo_id > 0) { @@ -701,8 +704,8 @@ s_SeqDbSrcNew(BlastSeqSrc* retval, void* args) datap->mask_algo_id) == supported_algorithms.end()) { CNcbiOstrstream oss; oss << "Masking algorithm ID " << datap->mask_algo_id << " is " - << "not supported in " << - (is_protein ? "protein" : "nucleotide") << " '" + << "not supported in " << + (is_protein ? "protein" : "nucleotide") << " '" << seqdb_args->GetDbName() << "' BLAST database"; string msg = CNcbiOstrstreamToString(oss); throw runtime_error(msg); @@ -710,27 +713,27 @@ s_SeqDbSrcNew(BlastSeqSrc* retval, void* args) } } catch (const ncbi::CException& e) { - _BlastSeqSrcImpl_SetInitErrorStr(retval, + _BlastSeqSrcImpl_SetInitErrorStr(retval, strdup(e.ReportThis(eDPF_ErrCodeExplanation).c_str())); } catch (const std::exception& e) { _BlastSeqSrcImpl_SetInitErrorStr(retval, strdup(e.what())); } catch (...) { - _BlastSeqSrcImpl_SetInitErrorStr(retval, + _BlastSeqSrcImpl_SetInitErrorStr(retval, strdup("Caught unknown exception from CSeqDB constructor")); } - + /* Initialize the BlastSeqSrc structure fields with user-defined function * pointers and seqdb */ - + s_InitNewSeqDbSrc(retval, datap); - + return retval; } } -BlastSeqSrc* -SeqDbBlastSeqSrcInit(const string& dbname, bool is_prot, +BlastSeqSrc* +SeqDbBlastSeqSrcInit(const string& dbname, bool is_prot, Uint4 first_seq, Uint4 last_seq, Int4 mask_algo_id, ESubjectMaskingType mask_type) { @@ -745,7 +748,7 @@ SeqDbBlastSeqSrcInit(const string& dbname, bool is_prot, return seq_src; } -BlastSeqSrc* +BlastSeqSrc* SeqDbBlastSeqSrcInit(CSeqDB * seqdb, Int4 mask_algo_id, ESubjectMaskingType mask_type) diff --git a/c++/src/algo/blast/api/setup_factory.cpp b/c++/src/algo/blast/api/setup_factory.cpp index 46cc54a5..80338d8a 100644 --- a/c++/src/algo/blast/api/setup_factory.cpp +++ b/c++/src/algo/blast/api/setup_factory.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: setup_factory.cpp 458896 2015-02-11 15:05:08Z boratyng $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -59,8 +55,10 @@ static char const rcsid[] = #include #include #include +#include #include +#include "../core/jumper.h" /** @addtogroup AlgoBlast * @@ -219,7 +217,8 @@ CSetupFactory::CreateLookupTable(CRef query_data, score_blk, &retval, rps_info ? (*rps_info)() : 0, - &blast_msg); + &blast_msg, + seqsrc); if (status != 0) { TSearchMessages search_messages; Blast_Message2TSearchMessages(blast_msg.Get(), @@ -294,6 +293,7 @@ CSetupFactory::CreateHspStream(const CBlastOptionsMemento* opts_memento, BlastHSPWriter* CSetupFactory::CreateHspWriter(const CBlastOptionsMemento* opts_memento, + BLAST_SequenceBlk* query, BlastQueryInfo* query_info) { BlastHSPWriterInfo* writer_info = NULL; @@ -304,8 +304,16 @@ CSetupFactory::CreateHspWriter(const CBlastOptionsMemento* opts_memento, //We want to only do score edge in prelimiary stage, skip if score edge in 0 filt_opts = NULL; } - if (filt_opts) { - bool hsp_writer_found = false; + + if (Blast_ProgramIsMapping(opts_memento->m_ProgramType)) { + + BlastHSPMapperParams* params = + BlastHSPMapperParamsNew(opts_memento->m_HitSaveOpts, + opts_memento->m_ScoringOpts); + + writer_info = BlastHSPMapperInfoNew(params); + } + else if (filt_opts) { if (filt_opts->best_hit && (filt_opts->best_hit_stage & ePrelimSearch)) { BlastHSPBestHitParams* params = @@ -316,21 +324,17 @@ CSetupFactory::CreateHspWriter(const CBlastOptionsMemento* opts_memento, // Disable overhang in prelimiary stage params->overhang = 0; writer_info = BlastHSPBestHitInfoNew(params); - hsp_writer_found = true; } else if (filt_opts->culling_opts && (filt_opts->culling_stage & ePrelimSearch)) { - _ASSERT(hsp_writer_found == false); BlastHSPCullingParams* params = BlastHSPCullingParamsNew(opts_memento->m_HitSaveOpts, filt_opts->culling_opts, opts_memento->m_ExtnOpts->compositionBasedStats, opts_memento->m_ScoringOpts->gapped_calculation); writer_info = BlastHSPCullingInfoNew(params); - hsp_writer_found = true; } - (void)hsp_writer_found; /* to pacify compiler warning */ } else { /* Use the collector filtering algorithm as the default */ BlastHSPCollectorParams * params = @@ -340,7 +344,7 @@ CSetupFactory::CreateHspWriter(const CBlastOptionsMemento* opts_memento, writer_info = BlastHSPCollectorInfoNew(params); } - BlastHSPWriter* retval = BlastHSPWriterNew(&writer_info, query_info); + BlastHSPWriter* retval = BlastHSPWriterNew(&writer_info, query_info, query); _ASSERT(writer_info == NULL); return retval; } @@ -420,7 +424,8 @@ CSetupFactory::InitializeMegablastDbIndex(CRef options) string errstr = ""; bool partial( false ); - if( options->GetProgramType() != eBlastTypeBlastn ) { + if( options->GetProgramType() != eBlastTypeBlastn + && options->GetProgramType() != eBlastTypeMapping) { errstr = "Database indexing is available for blastn only."; } else if( options->GetMBTemplateLength() > 0 ) { diff --git a/c++/src/algo/blast/api/split_query_aux_priv.cpp b/c++/src/algo/blast/api/split_query_aux_priv.cpp index 01e18414..e8bbfa60 100644 --- a/c++/src/algo/blast/api/split_query_aux_priv.cpp +++ b/c++/src/algo/blast/api/split_query_aux_priv.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: split_query_aux_priv.cpp 458701 2015-02-09 15:05:54Z fongah2 $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -82,6 +78,10 @@ SplitQuery_ShouldSplit(EBlastProgramType program, // TODO: need to model mem usage and when it's advantageous to split bool retval = true; + if (program == eBlastTypeMapping) { + return false; + } + // if ((concatenated_query_length <= chunk_size+SplitQuery_GetOverlapChunkSize(program)) || // if ((concatenated_query_length <= chunk_size) || // do not split RPS-BLAST diff --git a/c++/src/algo/blast/api/split_query_blk.cpp b/c++/src/algo/blast/api/split_query_blk.cpp index 126ea28d..655b1fdc 100644 --- a/c++/src/algo/blast/api/split_query_blk.cpp +++ b/c++/src/algo/blast/api/split_query_blk.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: split_query_blk.cpp 195768 2010-06-25 17:12:38Z maning $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/algo/blast/api/split_query_cxx.cpp b/c++/src/algo/blast/api/split_query_cxx.cpp index 55afcb86..64ebcaf9 100644 --- a/c++/src/algo/blast/api/split_query_cxx.cpp +++ b/c++/src/algo/blast/api/split_query_cxx.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: split_query_cxx.cpp 442852 2014-08-07 17:41:12Z camacho $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * diff --git a/c++/src/algo/blast/api/traceback_stage.cpp b/c++/src/algo/blast/api/traceback_stage.cpp index 83f0dc5f..5032a037 100644 --- a/c++/src/algo/blast/api/traceback_stage.cpp +++ b/c++/src/algo/blast/api/traceback_stage.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: traceback_stage.cpp 459518 2015-02-19 13:53:19Z madden $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/algo/blast/api/uniform_search.cpp b/c++/src/algo/blast/api/uniform_search.cpp index 3c443680..c1edc5ee 100644 --- a/c++/src/algo/blast/api/uniform_search.cpp +++ b/c++/src/algo/blast/api/uniform_search.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: uniform_search.cpp 481634 2015-10-14 15:21:43Z fongah2 $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/algo/blast/api/winmask_filter.cpp b/c++/src/algo/blast/api/winmask_filter.cpp index d63303eb..3bc6fa63 100644 --- a/c++/src/algo/blast/api/winmask_filter.cpp +++ b/c++/src/algo/blast/api/winmask_filter.cpp @@ -1,4 +1,4 @@ -/* $Id: winmask_filter.cpp 463952 2015-04-02 16:08:53Z camacho $ +/* $Id: winmask_filter.cpp 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -34,11 +34,6 @@ /// @file winmask_filter.cpp /// Blast wrappers for WindowMasker filtering. - -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = "$Id: winmask_filter.cpp 463952 2015-04-02 16:08:53Z camacho $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include "winmask_filter.hpp" #include diff --git a/c++/src/algo/blast/blastinput/Makefile.blastinput.lib b/c++/src/algo/blast/blastinput/Makefile.blastinput.lib index 96ea05b1..4008d136 100644 --- a/c++/src/algo/blast/blastinput/Makefile.blastinput.lib +++ b/c++/src/algo/blast/blastinput/Makefile.blastinput.lib @@ -1,4 +1,4 @@ -# $Id: Makefile.blastinput.lib 441606 2014-07-25 14:36:47Z fongah2 $ +# $Id: Makefile.blastinput.lib 514850 2016-09-26 17:23:32Z ivanov $ SRC_CXX = \ blast_input \ @@ -18,7 +18,10 @@ rpsblast_args \ rpstblastn_args \ igblastn_args \ igblastp_args \ -deltablast_args +deltablast_args \ +magicblast_args \ +kblastp_args \ +blast_asn1_input SRC = $(SRC_CXX) @@ -34,7 +37,7 @@ CPPFLAGS = -DNCBI_MODULE=BLAST $(ORIG_CPPFLAGS) CXXFLAGS = $(FAST_CXXFLAGS) LDFLAGS = $(FAST_LDFLAGS) -WATCHERS = madden camacho fongah2 +WATCHERS = madden camacho fongah2 boratyng USES_LIBRARIES = \ diff --git a/c++/src/algo/blast/blastinput/Makefile.in b/c++/src/algo/blast/blastinput/Makefile.in index d7d08c78..ab9e5abf 100644 --- a/c++/src/algo/blast/blastinput/Makefile.in +++ b/c++/src/algo/blast/blastinput/Makefile.in @@ -1,4 +1,4 @@ -# $Id: Makefile.in 134303 2008-07-17 17:42:49Z camacho $ +# $Id: Makefile.in 507863 2016-07-21 20:15:31Z boratyng $ # Meta-makefile("ALGO" project) ################################# diff --git a/c++/src/algo/blast/blastinput/blast_args.cpp b/c++/src/algo/blast/blastinput/blast_args.cpp index ca39587c..948c9221 100644 --- a/c++/src/algo/blast/blastinput/blast_args.cpp +++ b/c++/src/algo/blast/blastinput/blast_args.cpp @@ -1,4 +1,4 @@ -/* $Id: blast_args.cpp 499246 2016-04-25 11:32:24Z ivanov $ +/* $Id: blast_args.cpp 516396 2016-10-13 12:26:43Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -35,11 +35,6 @@ Author: Jason Papadopoulos * convert blast-related command line * arguments into blast options */ - -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = "$Id: blast_args.cpp 499246 2016-04-25 11:32:24Z ivanov $"; -#endif - #include #include #include @@ -132,10 +127,11 @@ CGenericSearchArgs::SetArgumentDescriptions(CArgDescriptions& arg_desc) CArgDescriptions::eDouble, NStr::DoubleToString(1.0)); } else { + //igblastn arg_desc.AddDefaultKey(kArgEvalue, "evalue", "Expectation value (E) threshold for saving hits ", CArgDescriptions::eDouble, - NStr::DoubleToString(1e-15)); + NStr::DoubleToString(20.0)); } // word size @@ -228,7 +224,7 @@ void CGenericSearchArgs::ExtractAlgorithmOptions(const CArgs& args, CBlastOptions& opt) { - if (args[kArgEvalue]) { + if (args.Exist(kArgEvalue) && args[kArgEvalue]) { opt.SetEvalueThreshold(args[kArgEvalue].AsDouble()); } @@ -251,7 +247,7 @@ CGenericSearchArgs::ExtractAlgorithmOptions(const CArgs& args, opt.SetGapExtensionCost(gap_extend); } - if (args[kArgUngappedXDropoff]) { + if (args.Exist(kArgUngappedXDropoff) && args[kArgUngappedXDropoff]) { opt.SetXDropoff(args[kArgUngappedXDropoff].AsDouble()); } @@ -269,7 +265,7 @@ CGenericSearchArgs::ExtractAlgorithmOptions(const CArgs& args, opt.SetWordSize(args[kArgWordSize].AsInteger()); } - if (args[kArgEffSearchSpace]) { + if (args.Exist(kArgEffSearchSpace) && args[kArgEffSearchSpace]) { CNcbiEnvironment env; env.Set("OLD_FSC", "true"); opt.SetEffectiveSearchSpace(args[kArgEffSearchSpace].AsInt8()); @@ -283,7 +279,7 @@ CGenericSearchArgs::ExtractAlgorithmOptions(const CArgs& args, opt.SetQueryCovHspPerc(args[kArgQueryCovHspPerc].AsDouble()); } - if (args[kArgMaxHSPsPerSubject]) { + if (args.Exist(kArgMaxHSPsPerSubject) && args[kArgMaxHSPsPerSubject]) { opt.SetMaxHspsPerSubject(args[kArgMaxHSPsPerSubject].AsInteger()); } @@ -638,14 +634,15 @@ void CNuclArgs::ExtractAlgorithmOptions(const CArgs& cmd_line_args, CBlastOptions& options) { - if (cmd_line_args[kArgMismatch]) { + if (cmd_line_args.Exist(kArgMismatch) && cmd_line_args[kArgMismatch]) { options.SetMismatchPenalty(cmd_line_args[kArgMismatch].AsInteger()); } - if (cmd_line_args[kArgMatch]) { + if (cmd_line_args.Exist(kArgMatch) && cmd_line_args[kArgMatch]) { options.SetMatchReward(cmd_line_args[kArgMatch].AsInteger()); } - if (cmd_line_args[kArgNoGreedyExtension]) { + if (cmd_line_args.Exist(kArgNoGreedyExtension) && + cmd_line_args[kArgNoGreedyExtension]) { options.SetGapExtnAlgorithm(eDynProgScoreOnly); options.SetGapTracebackAlgorithm(eDynProgTbck); } @@ -794,7 +791,7 @@ s_SetCompositionBasedStats(CBlastOptions& opt, const EProgram program = opt.GetProgram(); if (program == eBlastp || program == eTblastn || program == ePSIBlast || program == ePSITblastn || - program == eRPSBlast || + program == eRPSBlast || program == eRPSTblastn || program == eBlastx || program == eDeltaBlast) { ECompoAdjustModes compo_mode = eNoCompositionBasedStats; @@ -807,7 +804,7 @@ s_SetCompositionBasedStats(CBlastOptions& opt, compo_mode = eCompositionBasedStats; break; case 'D': case 'd': - if (program == eRPSBlast) { + if ((program == eRPSBlast) || (program == eRPSTblastn)) { compo_mode = eNoCompositionBasedStats; } else if (program == eDeltaBlast) { @@ -824,7 +821,7 @@ s_SetCompositionBasedStats(CBlastOptions& opt, compo_mode = eCompoForceFullMatrixAdjust; break; case 'T': case 't': - compo_mode = (program == eRPSBlast || program == eDeltaBlast) ? + compo_mode = (program == eRPSBlast || program == eRPSTblastn || program == eDeltaBlast) ? eCompositionBasedStats : eCompositionMatrixAdjust; break; } @@ -1370,6 +1367,35 @@ CPhiBlastArgs::ExtractAlgorithmOptions(const CArgs& args, } } +void +CKBlastpArgs::SetArgumentDescriptions(CArgDescriptions& arg_desc) +{ + arg_desc.SetCurrentGroup("KBLASTP options"); + arg_desc.AddDefaultKey(kArgJDistance, "threshold", "Jaccard Distance", + CArgDescriptions::eDouble, kDfltArgJDistance); + arg_desc.AddDefaultKey(kArgMinHits, "minhits", "minimal number of LSH matches", + CArgDescriptions::eInteger, kDfltArgMinHits); + arg_desc.AddDefaultKey(kArgKIndex, "dbk", "index of kmers", + CArgDescriptions::eString, kDfltArgKIndex); + arg_desc.AddDefaultKey(kArgTargetSeqs, "targetseqs", "Number of target sequences to process with BLAST", + CArgDescriptions::eInteger, kDfltArgTargetSeqs); +} + +void +CKBlastpArgs::ExtractAlgorithmOptions(const CArgs& args, + CBlastOptions& opt) +{ + if (args.Exist(kArgJDistance)) + m_JDistance = args[kArgJDistance].AsDouble(); + if (args.Exist(kArgMinHits)) + m_MinHits = args[kArgMinHits].AsInteger(); + if (args.Exist(kArgKIndex)) + m_DbIndex = args[kArgKIndex].AsString(); + if (args.Exist(kArgTargetSeqs)) + m_TargetSeqs = args[kArgTargetSeqs].AsInteger(); +} + + void CDeltaBlastArgs::SetArgumentDescriptions(CArgDescriptions& arg_desc) { @@ -1398,6 +1424,64 @@ CDeltaBlastArgs::ExtractAlgorithmOptions(const CArgs& args, } } +void +CMappingArgs::SetArgumentDescriptions(CArgDescriptions& arg_desc) +{ + + arg_desc.SetCurrentGroup("Mapping options"); + arg_desc.AddOptionalKey(kArgScore, "num", "Cutoff score for accepting a " + "single non-spliced alignment", + CArgDescriptions::eInteger); + arg_desc.AddOptionalKey(kArgSplice, "TF", "Search for spliced alignments", + CArgDescriptions::eBoolean); + arg_desc.AddDefaultKey(kArgRefType, "type", "Type of the reference: " + "genome or transcriptome", + CArgDescriptions::eString, "genome"); + arg_desc.SetConstraint(kArgRefType, + &(*new CArgAllow_Strings, "genome", "transcriptome")); + + arg_desc.SetCurrentGroup("Query filtering options"); + arg_desc.AddOptionalKey(kArgLimitLookup, "TF", "Remove word seeds with " + "high frequency in the searched database", + CArgDescriptions::eBoolean); + arg_desc.AddDefaultKey(kArgLookupStride, "num", "Number of words to skip " + "after collecting one while creating a lookup table", + CArgDescriptions::eInteger, "0"); + + arg_desc.SetCurrentGroup(""); +} + + +void +CMappingArgs::ExtractAlgorithmOptions(const CArgs& args, + CBlastOptions& opt) +{ + if (args.Exist(kArgScore) && args[kArgScore]) { + opt.SetCutoffScore(args[kArgScore].AsInteger()); + } + + if (args.Exist(kArgSplice) && args[kArgSplice]) { + opt.SetSpliceAlignments(args[kArgSplice].AsBoolean()); + } + + string ref_type = "genome"; + if (args.Exist(kArgRefType) && args[kArgRefType]) { + ref_type = args[kArgRefType].AsString(); + } + + if (args.Exist(kArgLimitLookup) && args[kArgLimitLookup]) { + opt.SetLookupDbFilter(args[kArgLimitLookup].AsBoolean()); + } + else { + opt.SetLookupDbFilter(ref_type == "genome"); + } + + if (args.Exist(kArgLookupStride) && args[kArgLookupStride]) { + opt.SetLookupTableStride(args[kArgLookupStride].AsInteger()); + } +} + + void CIgBlastArgs::SetArgumentDescriptions(CArgDescriptions& arg_desc) { @@ -1454,6 +1538,16 @@ CIgBlastArgs::SetArgumentDescriptions(CArgDescriptions& arg_desc) arg_desc.SetConstraint(kArgDPenalty, new CArgAllowValuesBetween(-6, 0)); + + arg_desc.AddDefaultKey(kArgNumClonotype, "num_clonotype", + "Number of top clonotypes to show ", + CArgDescriptions::eInteger, "100"); + arg_desc.SetConstraint(kArgNumClonotype, + new CArgAllowValuesGreaterThanOrEqual(0)); + + arg_desc.AddOptionalKey(kArgClonotypeFile, "clonotype_out", + "Output file name for clonotype info", + CArgDescriptions::eOutputFile); } @@ -1480,8 +1574,17 @@ CIgBlastArgs::SetArgumentDescriptions(CArgDescriptions& arg_desc) arg_desc.AddDefaultKey(kArgMinVLength, "Min_V_Length", "Minimal required V gene length", CArgDescriptions::eInteger, "9"); + arg_desc.SetConstraint(kArgMinVLength, new CArgAllowValuesGreaterThanOrEqual(9)); + + arg_desc.AddDefaultKey(kArgMinJLength, "Min_J_Length", + "Minimal required J gene length", + CArgDescriptions::eInteger, "0"); + + arg_desc.SetConstraint(kArgMinJLength, + new CArgAllowValuesGreaterThanOrEqual(0)); + if (! m_IsProtein) { arg_desc.AddFlag(kArgTranslate, "Show translated alignments", true); @@ -1510,12 +1613,12 @@ CIgBlastArgs::ExtractAlgorithmOptions(const CArgs& args, { string paths[3]; CNcbiEnvironment env; - CMetaRegistry::SEntry sentry = - CMetaRegistry::Load("ncbi", CMetaRegistry::eName_RcOrIni); paths[0] = CDirEntry::NormalizePath(CDir::GetCwd(), eFollowLinks); paths[1] = CDirEntry::NormalizePath(env.Get("IGDATA"), eFollowLinks); - if (sentry.registry) { - paths[2] = CDirEntry::NormalizePath(sentry.registry->Get("BLAST","IGDATA"), eFollowLinks); + CNcbiApplication* app = CNcbiApplication::Instance(); + if (app) { + const CNcbiRegistry& registry = app->GetConfig(); + paths[2] = CDirEntry::NormalizePath(registry.Get("BLAST","IGDATA"), eFollowLinks); } else { #if defined(NCBI_OS_DARWIN) paths[2] = "/usr/local/ncbi/igblast/data"; @@ -1536,6 +1639,7 @@ CIgBlastArgs::ExtractAlgorithmOptions(const CArgs& args, m_IgOptions->m_FocusV = args.Exist(kArgGLFocusV) ? args[kArgGLFocusV] : false; m_IgOptions->m_ExtendAlign = args.Exist(kArgExtendAlign) ? args[kArgExtendAlign] : false; m_IgOptions->m_MinVLength = args[kArgMinVLength].AsInteger(); + m_IgOptions->m_MinJLength = args[kArgMinJLength].AsInteger(); m_IgOptions->m_Translate = args.Exist(kArgTranslate) ? args[kArgTranslate] : false; if (!m_IsProtein) { @@ -1671,11 +1775,11 @@ CQueryOptionsArgs::SetArgumentDescriptions(CArgDescriptions& arg_desc) "(Format: start-stop)", CArgDescriptions::eString); - if ( !m_QueryCannotBeNucl ) { + if ( !m_QueryCannotBeNucl) { // search strands arg_desc.AddDefaultKey(kArgStrand, "strand", - "Query strand(s) to search against database/subject", - CArgDescriptions::eString, kDfltArgStrand); + "Query strand(s) to search against database/subject", + CArgDescriptions::eString, kDfltArgStrand); arg_desc.SetConstraint(kArgStrand, &(*new CArgAllow_Strings, kDfltArgStrand, "plus", "minus")); } @@ -1695,37 +1799,164 @@ CQueryOptionsArgs::ExtractAlgorithmOptions(const CArgs& args, { m_Strand = eNa_strand_unknown; - if (!Blast_QueryIsProtein(opt.GetProgramType()) && args[kArgStrand]) { - const string& kStrand = args[kArgStrand].AsString(); - if (kStrand == "both") { + if (!Blast_QueryIsProtein(opt.GetProgramType())) { + + if (args.Exist(kArgStrand) && args[kArgStrand]) { + const string& kStrand = args[kArgStrand].AsString(); + if (kStrand == "both") { + m_Strand = eNa_strand_both; + } else if (kStrand == "plus") { + m_Strand = eNa_strand_plus; + } else if (kStrand == "minus") { + m_Strand = eNa_strand_minus; + } else { + abort(); + } + } + else { m_Strand = eNa_strand_both; - } else if (kStrand == "plus") { - m_Strand = eNa_strand_plus; - } else if (kStrand == "minus") { - m_Strand = eNa_strand_minus; - } else { - abort(); } } } // set the sequence range - if (args[kArgQueryLocation]) { + if (args.Exist(kArgQueryLocation) && args[kArgQueryLocation]) { m_Range = ParseSequenceRange(args[kArgQueryLocation].AsString(), "Invalid specification of query location"); } - m_UseLCaseMask = static_cast(args[kArgUseLCaseMasking]); - m_ParseDeflines = static_cast(args[kArgParseDeflines]); + m_UseLCaseMask = args.Exist(kArgUseLCaseMasking) && + static_cast(args[kArgUseLCaseMasking]); + m_ParseDeflines = args.Exist(kArgParseDeflines) && + static_cast(args[kArgParseDeflines]); +} + +void +CMapperQueryOptionsArgs::SetArgumentDescriptions(CArgDescriptions& arg_desc) +{ + + arg_desc.SetCurrentGroup("Query filtering options"); + // lowercase masking + arg_desc.AddFlag(kArgUseLCaseMasking, + "Use lower case filtering in subject sequence(s)?", true); + arg_desc.AddDefaultKey(kArgQualityFilter, "TF", "Reject low quality " + "sequences ", CArgDescriptions::eBoolean, "true"); + + arg_desc.SetCurrentGroup("Input query options"); + arg_desc.AddDefaultKey(kArgInputFormat, "format", "Input format for " + "sequences", CArgDescriptions::eString, "fasta"); + arg_desc.SetConstraint(kArgInputFormat, &(*new CArgAllow_Strings, + "fasta", "fastc", "fastq", + "asn1", "asn1b")); + arg_desc.AddFlag(kArgPaired, "Input query sequences are paired", true); + arg_desc.AddOptionalKey(kArgQueryMate, "infile", "FASTA file with " + "mates for query sequences (if given in " + "another file)", CArgDescriptions::eInputFile); + arg_desc.SetDependency(kArgQueryMate, CArgDescriptions::eRequires, + kArgQuery); + + arg_desc.AddOptionalKey(kArgSraAccession, "accession", + "Comma-separated SRA accessions", + CArgDescriptions::eString); + arg_desc.SetDependency(kArgSraAccession, CArgDescriptions::eExcludes, + kArgQuery); + arg_desc.SetDependency(kArgSraAccession, CArgDescriptions::eExcludes, + kArgInputFormat); + + arg_desc.SetCurrentGroup("Miscellaneous options"); + arg_desc.AddDefaultKey(kArgParseDeflines, "TF", "Should the query and " + "subject defline(s) be parsed?", + CArgDescriptions::eBoolean, "true"); + + arg_desc.SetCurrentGroup(""); +} + +void +CMapperQueryOptionsArgs::ExtractAlgorithmOptions(const CArgs& args, + CBlastOptions& opt) +{ + CQueryOptionsArgs::ExtractAlgorithmOptions(args, opt); + + if (args.Exist(kArgPaired) && args[kArgPaired]) { + opt.SetPaired(true); + m_IsPaired = true; + } + + if (args.Exist(kArgInputFormat) && args[kArgInputFormat]) { + if (args[kArgInputFormat].AsString() == "fasta") { + m_InputFormat = eFasta; + } + else if (args[kArgInputFormat].AsString() == "fastc") { + m_InputFormat = eFastc; + } + else if (args[kArgInputFormat].AsString() == "fastq") { + m_InputFormat = eFastq; + } + else if (args[kArgInputFormat].AsString() == "asn1") { + m_InputFormat = eASN1text; + } + else if (args[kArgInputFormat].AsString() == "asn1b") { + m_InputFormat = eASN1bin; + } + else { + NCBI_THROW(CInputException, eInvalidInput, + "Unexpected input format: " + + args[kArgInputFormat].AsString()); + } + } + + if (m_InputFormat == eFastc) { + // FASTC format always has pairs in a single file + opt.SetPaired(true); + m_IsPaired = true; + } + + if (args.Exist(kArgQualityFilter) && args[kArgQualityFilter]) { + m_QualityFilter = args[kArgQualityFilter].AsBoolean(); + } + + if (args.Exist(kArgQueryMate) && args[kArgQueryMate]) { + // create a decompress stream is the file is compressed + // (the primary query file is handeled by CStdCmdLieArgs object) + if (NStr::EndsWith(args[kArgQueryMate].AsString(), ".gz", + NStr::eNocase)) { + m_DecompressIStream.reset(new CDecompressIStream( + args[kArgQueryMate].AsInputFile(), + CDecompressIStream::eGZipFile)); + m_MateInputStream = m_DecompressIStream.get(); + } + else { + m_MateInputStream = &args[kArgQueryMate].AsInputFile(); + } + + // queries have pairs in the mate stream + opt.SetPaired(true); + m_IsPaired = true; + } + + if (args.Exist(kArgSraAccession) && args[kArgSraAccession]) { + NStr::Split((CTempString)args[kArgSraAccession].AsString(), ",", + m_SraAccessions); + + m_InputFormat = eSra; + // assume SRA input is paired, that information for each read is in + // SRA database, this option will trigger checking for pairs + opt.SetPaired(true); + m_IsPaired = true; + } } + + CBlastDatabaseArgs::CBlastDatabaseArgs(bool request_mol_type /* = false */, bool is_rpsblast /* = false */, - bool is_igblast /* = false */) + bool is_igblast /* = false */, + bool is_mapper /* = false */) : m_RequestMoleculeType(request_mol_type), m_IsRpsBlast(is_rpsblast), m_IsIgBlast(is_igblast), m_IsProtein(true), + m_IsMapper(is_mapper), m_SupportsDatabaseMasking(false) {} @@ -1767,10 +1998,12 @@ CBlastDatabaseArgs::SetArgumentDescriptions(CArgDescriptions& arg_desc) } // DB size - arg_desc.SetCurrentGroup("Statistical options"); - arg_desc.AddOptionalKey(kArgDbSize, "num_letters", - "Effective length of the database ", - CArgDescriptions::eInt8); + if (!m_IsMapper) { + arg_desc.SetCurrentGroup("Statistical options"); + arg_desc.AddOptionalKey(kArgDbSize, "num_letters", + "Effective length of the database ", + CArgDescriptions::eInt8); + } arg_desc.SetCurrentGroup("Restrict search or results"); // GI list @@ -1805,13 +2038,15 @@ CBlastDatabaseArgs::SetArgumentDescriptions(CArgDescriptions& arg_desc) } // Entrez Query - arg_desc.AddOptionalKey(kArgEntrezQuery, "entrez_query", - "Restrict search with the given Entrez query", - CArgDescriptions::eString); + if (!m_IsMapper) { + arg_desc.AddOptionalKey(kArgEntrezQuery, "entrez_query", + "Restrict search with the given Entrez query", + CArgDescriptions::eString); - // Entrez query currently requires the -remote option - arg_desc.SetDependency(kArgEntrezQuery, CArgDescriptions::eRequires, - kArgRemote); + // Entrez query currently requires the -remote option + arg_desc.SetDependency(kArgEntrezQuery, CArgDescriptions::eRequires, + kArgRemote); + } #if ((!defined(NCBI_COMPILER_WORKSHOP) || (NCBI_COMPILER_VERSION > 550)) && \ @@ -1906,7 +2141,19 @@ CBlastDatabaseArgs::ExtractAlgorithmOptions(const CArgs& args, #endif } else if (args.Exist(kArgSubject) && args[kArgSubject]) { - CNcbiIstream& subj_input_stream = args[kArgSubject].AsInputFile(); + CNcbiIstream* subj_input_stream = NULL; + auto_ptr decompress_stream; + if (m_IsMapper && + NStr::EndsWith(args[kArgSubject].AsString(), ".gz", NStr::eNocase)) { + decompress_stream.reset( + new CDecompressIStream(args[kArgSubject].AsInputFile(), + CDecompressIStream::eGZipFile)); + subj_input_stream = decompress_stream.get(); + } + else { + subj_input_stream = &args[kArgSubject].AsInputFile(); + } + TSeqRange subj_range; if (args.Exist(kArgSubjectLocation) && args[kArgSubjectLocation]) { subj_range = @@ -1915,15 +2162,15 @@ CBlastDatabaseArgs::ExtractAlgorithmOptions(const CArgs& args, } const bool parse_deflines = args.Exist(kArgParseDeflines) - ? bool(args[kArgParseDeflines]) + ? args[kArgParseDeflines].AsBoolean() : kDfltArgParseDeflines; const bool use_lcase_masks = args.Exist(kArgUseLCaseMasking) ? bool(args[kArgUseLCaseMasking]) : kDfltArgUseLCaseMasking; CRef subjects; - m_Scope = ReadSequencesToBlast(subj_input_stream, IsProtein(), + m_Scope = ReadSequencesToBlast(*subj_input_stream, IsProtein(), subj_range, parse_deflines, - use_lcase_masks, subjects); + use_lcase_masks, subjects, m_IsMapper); m_Subjects.Reset(new blast::CObjMgr_QueryFactory(*subjects)); } else if (!m_IsIgBlast){ @@ -1937,7 +2184,7 @@ CBlastDatabaseArgs::ExtractAlgorithmOptions(const CArgs& args, return; } - if (args[kArgDbSize]) { + if (args.Exist(kArgDbSize) && args[kArgDbSize]) { opts.SetDbLength(args[kArgDbSize].AsInt8()); } @@ -1967,10 +2214,13 @@ CFormattingArgs::SetArgumentDescriptions(CArgDescriptions& arg_desc) " 14 = Multiple-file BLAST XML2,\n" " 15 = Single-file BLAST JSON,\n" " 16 = Single-file BLAST XML2"); - + if(m_FormatFlags & eIsSAM) { - kOutputFormatDescription += - ",\n 17 = Sequence Alignment/Map (SAM)\n\n" + kOutputFormatDescription += ",\n 17 = Sequence Alignment/Map (SAM)"; + } + kOutputFormatDescription += ",\n 18 = Organism Report\n\n"; + if(m_FormatFlags & eIsSAM) { + kOutputFormatDescription += "Options 6, 7, 10 and 17 " "can be additionally configured to produce\n" "a custom format specified by space delimited format specifiers.\n" @@ -1978,11 +2228,12 @@ CFormattingArgs::SetArgumentDescriptions(CArgDescriptions& arg_desc) } else { kOutputFormatDescription += - "\n\nOptions 6, 7 and 10 " + "Options 6, 7 and 10 " "can be additionally configured to produce\n" "a custom format specified by space delimited format specifiers.\n" "The supported format specifiers are:\n"; } + kOutputFormatDescription += DescribeTabularOutputFormatSpecifiers() + string("\n"); if(m_FormatFlags & eIsSAM) { @@ -1991,6 +2242,7 @@ CFormattingArgs::SetArgumentDescriptions(CArgDescriptions& arg_desc) DescribeSAMOutputFormatSpecifiers(); } + int dft_outfmt = kDfltArgOutputFormat; // Igblast shows extra column of gaps @@ -2047,6 +2299,7 @@ CFormattingArgs::SetArgumentDescriptions(CArgDescriptions& arg_desc) if(!m_IsIgBlast){ arg_desc.AddFlag(kArgProduceHtml, "Produce HTML output?", true); } + /// Hit list size, listed here for convenience only arg_desc.SetCurrentGroup("Restrict search or results"); arg_desc.AddOptionalKey(kArgMaxTargetSequences, "num_sequences", @@ -2139,7 +2392,8 @@ CFormattingArgs::ExtractAlgorithmOptions(const CArgs& args, // we need to increase the num_ descriptions and num_alignemtns if(hitlist_size > BLAST_HITLIST_SIZE ) { - if(!args[kArgNumDescriptions] && !args[kArgNumAlignments] && + if((!args.Exist(kArgNumDescriptions) || !args[kArgNumDescriptions]) && + (!args.Exist(kArgNumAlignments) || !args[kArgNumAlignments]) && (m_OutputFormat <= eFlatQueryAnchoredNoIdentities)) { m_NumDescriptions = hitlist_size; m_NumAlignments = hitlist_size/ 2; @@ -2148,7 +2402,7 @@ CFormattingArgs::ExtractAlgorithmOptions(const CArgs& args, } if(m_OutputFormat <= eFlatQueryAnchoredNoIdentities) { - if (args[kArgMaxTargetSequences]) { + if (args.Exist(kArgMaxTargetSequences) && args[kArgMaxTargetSequences]) { ERR_POST(Warning << "The parameter -max_target_seqs is ignored for " "output formats, 0,1,2,3. Use -num_descriptions " "and -num_alignments to control output"); @@ -2157,18 +2411,20 @@ CFormattingArgs::ExtractAlgorithmOptions(const CArgs& args, m_NumDescriptions = m_DfltNumDescriptions; m_NumAlignments = m_DfltNumAlignments; - if (args[kArgNumDescriptions]) { + if (args.Exist(kArgNumDescriptions) && args[kArgNumDescriptions]) { m_NumDescriptions = args[kArgNumDescriptions].AsInteger(); } - if (args[kArgNumAlignments]) { + if (args.Exist(kArgNumAlignments) && args[kArgNumAlignments]) { m_NumAlignments = args[kArgNumAlignments].AsInteger(); } // The If clause is for handling import_search_strategy hitlist size < 500 // We want to preserve the hitlist size in iss if no formatting input is entered in cmdline // If formmating option(s) is entered than the iss hitlist size is overridden. - if (args[kArgNumDescriptions] || args[kArgNumAlignments]) { + // FIXME: does this work with import search strategies? + if ((args.Exist(kArgNumDescriptions) && args[kArgNumDescriptions]) || + (args.Exist(kArgNumAlignments) && args[kArgNumAlignments])) { hitlist_size = max(m_NumDescriptions, m_NumAlignments); } @@ -2178,7 +2434,7 @@ CFormattingArgs::ExtractAlgorithmOptions(const CArgs& args, } else { - if (args[kArgNumDescriptions]) { + if (args.Exist(kArgNumDescriptions) && args[kArgNumDescriptions]) { ERR_POST(Warning << "The parameter -num_descriptions is ignored for " "output formats > 4 . Use -max_target_seqs " "to control output"); @@ -2189,10 +2445,10 @@ CFormattingArgs::ExtractAlgorithmOptions(const CArgs& args, "output formats > 4 ."); } - if (args[kArgMaxTargetSequences]) { + if (args.Exist(kArgMaxTargetSequences) && args[kArgMaxTargetSequences]) { hitlist_size = args[kArgMaxTargetSequences].AsInteger(); } - else if (args[kArgNumAlignments]) { + else if (args.Exist(kArgNumAlignments) && args[kArgNumAlignments]) { hitlist_size = args[kArgNumAlignments].AsInteger(); } @@ -2485,6 +2741,10 @@ CStdCmdLineArgs::SetArgumentDescriptions(CArgDescriptions& arg_desc) "Output file name", CArgDescriptions::eOutputFile, "-"); + if (m_GzipEnabled) { + arg_desc.AddFlag(kArgOutputGzip, "Output will be compressed"); + } + arg_desc.SetCurrentGroup(""); } @@ -2494,9 +2754,28 @@ CStdCmdLineArgs::ExtractAlgorithmOptions(const CArgs& args, { if (args.Exist(kArgQuery) && args[kArgQuery].HasValue() && m_InputStream == NULL) { - m_InputStream = &args[kArgQuery].AsInputFile(); + + if (m_GzipEnabled && + NStr::EndsWith(args[kArgQuery].AsString(), ".gz", NStr::eNocase)) { + m_DecompressIStream.reset(new CDecompressIStream( + args[kArgQuery].AsInputFile(), + CDecompressIStream::eGZipFile)); + m_InputStream = m_DecompressIStream.get(); + } + else { + m_InputStream = &args[kArgQuery].AsInputFile(); + } + } + + if (args.Exist(kArgOutputGzip) && args[kArgOutputGzip]) { + m_CompressOStream.reset(new CCompressOStream( + args[kArgOutput].AsOutputFile(), + CCompressOStream::eGZipFile)); + m_OutputStream = m_CompressOStream.get(); + } + else { + m_OutputStream = &args[kArgOutput].AsOutputFile(); } - m_OutputStream = &args[kArgOutput].AsOutputFile(); } CNcbiIstream& @@ -2556,7 +2835,8 @@ CNcbiIstream* CSearchStrategyArgs::GetImportStream(const CArgs& args) const { CNcbiIstream* retval = NULL; - if (args[kArgInputSearchStrategy].HasValue()) { + if (args.Exist(kArgInputSearchStrategy) && + args[kArgInputSearchStrategy].HasValue()) { retval = &args[kArgInputSearchStrategy].AsInputFile(); } return retval; @@ -2566,7 +2846,8 @@ CNcbiOstream* CSearchStrategyArgs::GetExportStream(const CArgs& args) const { CNcbiOstream* retval = NULL; - if (args[kArgOutputSearchStrategy].HasValue()) { + if (args.Exist(kArgOutputSearchStrategy) && + args[kArgOutputSearchStrategy].HasValue()) { retval = &args[kArgOutputSearchStrategy].AsOutputFile(); } return retval; diff --git a/c++/src/algo/blast/blastinput/blast_asn1_input.cpp b/c++/src/algo/blast/blastinput/blast_asn1_input.cpp new file mode 100644 index 00000000..db1dfcea --- /dev/null +++ b/c++/src/algo/blast/blastinput/blast_asn1_input.cpp @@ -0,0 +1,365 @@ +/* $Id: blast_asn1_input.cpp 517499 2016-10-25 17:20:41Z ivanov $ + * =========================================================================== + * + * PUBLIC DOMAIN NOTICE + * National Center for Biotechnology Information + * + * This software/database is a "United States Government Work" under the + * terms of the United States Copyright Act. It was written as part of + * the author's official duties as a United States Government employee and + * thus cannot be copyrighted. This software/database is freely available + * to the public for use. The National Library of Medicine and the U.S. + * Government have not placed any restriction on its use or reproduction. + * + * Although all reasonable efforts have been taken to ensure the accuracy + * and reliability of the software and data, the NLM and the U.S. + * Government do not and cannot warrant the performance or results that + * may be obtained by using this software or data. The NLM and the U.S. + * Government disclaim all warranties, express or implied, including + * warranties of performance, merchantability or fitness for any particular + * purpose. + * + * Please cite the author in any work or product based on this material. + * + * =========================================================================== + * + * Author: Greg Boratyn + * + */ + +/** @file blast_asn1_input.cpp + * Convert ASN1-formatted files into blast sequence input + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include + +BEGIN_NCBI_SCOPE +BEGIN_SCOPE(blast) +USING_SCOPE(objects); + + +CASN1InputSourceOMF::CASN1InputSourceOMF(CNcbiIstream& infile, + TSeqPos num_seqs, + bool is_bin, + bool is_paired, + bool validate) + : m_NumSeqsInBatch(num_seqs), + m_InputStream(&infile), + m_SecondInputStream(NULL), + m_IsPaired(is_paired), + m_Validate(validate), + m_IsBinary(is_bin) +{} + +CASN1InputSourceOMF::CASN1InputSourceOMF(CNcbiIstream& infile1, + CNcbiIstream& infile2, + TSeqPos num_seqs, + bool is_bin, + bool validate) + : m_NumSeqsInBatch(num_seqs), + m_InputStream(&infile1), + m_SecondInputStream(&infile2), + m_IsPaired(true), + m_Validate(validate), + m_IsBinary(is_bin) +{} + + +void +CASN1InputSourceOMF::GetNextNumSequences(CBioseq_set& bioseq_set, + TSeqPos /* num_seqs */) +{ + // preallocate memory for sequences to be read + m_Entries.clear(); + + // +1 in case we need to read one more sequence so that a pair is not + // broken + m_Entries.resize(m_NumSeqsInBatch + 1); + + if (m_SecondInputStream) { + x_ReadFromTwoFiles(bioseq_set); + } + else { + x_ReadFromSingleFile(bioseq_set); + } + + // detach CRefs in m_Entries from objects in bioseq_set for thread safety + m_Entries.clear(); +} + + +int +CASN1InputSourceOMF::x_ReadOneSeq(CNcbiIstream& instream) +{ + CTempString line; + CTempString id; + int retval = -1; + + CRef seq_entry(new CSeq_entry); + try { + if (m_IsBinary) { + instream >> MSerial_AsnBinary >> *seq_entry; + } + else { + instream >> MSerial_AsnText >> *seq_entry; + } + } + catch (...) { + if (instream.eof()) { + return -1; + } + + NCBI_THROW(CInputException, eInvalidInput, "Problem reading ASN1 entry"); + } + + if (!m_Validate || + x_ValidateSequence(seq_entry->GetSeq().GetInst().GetSeq_data(), + seq_entry->GetSeq().GetInst().GetLength())) { + + m_Entries[m_Index] = seq_entry; + retval = m_Index; + m_Index++; + } + + return retval; +} + + +bool +CASN1InputSourceOMF::x_ReadFromSingleFile(CBioseq_set& bioseq_set) +{ + int current_read = 0; + bool first_added = false; + + // tags to indicate paired sequences + CRef seqdesc_first(new CSeqdesc); + seqdesc_first->SetUser().SetType().SetStr("Mapping"); + seqdesc_first->SetUser().AddField("has_pair", eFirstSegment); + + CRef seqdesc_last(new CSeqdesc); + seqdesc_last->SetUser().SetType().SetStr("Mapping"); + seqdesc_last->SetUser().AddField("has_pair", eLastSegment); + + CRef seqdesc_first_partial(new CSeqdesc); + seqdesc_first_partial->SetUser().SetType().SetStr("Mapping"); + seqdesc_first_partial->SetUser().AddField("has_pair", + fFirstSegmentFlag | fPartialFlag); + + CRef seqdesc_last_partial(new CSeqdesc); + seqdesc_last_partial->SetUser().SetType().SetStr("Mapping"); + seqdesc_last_partial->SetUser().AddField("has_pair", + fLastSegmentFlag | fPartialFlag); + + m_Index = 0; + while (m_Index < (int)m_NumSeqsInBatch && !m_InputStream->eof()) { + int index = x_ReadOneSeq(*m_InputStream); + + if (index >= 0) { + + if (m_IsPaired && (current_read & 1) == 0) { + first_added = true; + } + + if (m_IsPaired && (current_read & 1) == 1) { + if (first_added) { + bioseq_set.SetSeq_set().back()->SetSeq().SetDescr().Set(). + push_back(seqdesc_first); + m_Entries[index]->SetSeq().SetDescr().Set().push_back(seqdesc_last); + } + else { + m_Entries[index]->SetSeq().SetDescr().Set().push_back( + seqdesc_last_partial); + } + first_added = false; + } + + bioseq_set.SetSeq_set().push_back(m_Entries[index]); + } + else { + if (first_added) { + bioseq_set.SetSeq_set().back()->SetSeq().SetDescr().Set(). + push_back(seqdesc_first_partial); + } + first_added = false; + } + current_read++; + } + + return true; +} + + +bool +CASN1InputSourceOMF::x_ReadFromTwoFiles(CBioseq_set& bioseq_set) +{ + // tags to indicate paired sequences + CRef seqdesc_first(new CSeqdesc); + seqdesc_first->SetUser().SetType().SetStr("Mapping"); + seqdesc_first->SetUser().AddField("has_pair", eFirstSegment); + + CRef seqdesc_last(new CSeqdesc); + seqdesc_last->SetUser().SetType().SetStr("Mapping"); + seqdesc_last->SetUser().AddField("has_pair", eLastSegment); + + CRef seqdesc_first_partial(new CSeqdesc); + seqdesc_first_partial->SetUser().SetType().SetStr("Mapping"); + seqdesc_first_partial->SetUser().AddField("has_pair", + fFirstSegmentFlag | fPartialFlag); + + CRef seqdesc_last_partial(new CSeqdesc); + seqdesc_last_partial->SetUser().SetType().SetStr("Mapping"); + seqdesc_last_partial->SetUser().AddField("has_pair", + fLastSegmentFlag | fPartialFlag); + + int index1; + int index2; + m_Index = 0; + while (m_Index < (int)m_NumSeqsInBatch && !m_InputStream->eof() && + !m_SecondInputStream->eof()) { + + index1 = x_ReadOneSeq(*m_InputStream); + index2 = x_ReadOneSeq(*m_SecondInputStream); + + // if both sequences were read, the pair in the first one + if (index1 >= 0 && index2 >= 0) { + m_Entries[index1]->SetSeq().SetDescr().Set().push_back( + seqdesc_first); + + m_Entries[index2]->SetSeq().SetDescr().Set().push_back( + seqdesc_last); + + bioseq_set.SetSeq_set().push_back(m_Entries[index1]); + bioseq_set.SetSeq_set().push_back(m_Entries[index2]); + } + else { + // otherwise mark incomplete pair for the sequence that was read + if (index1 >= 0) { + m_Entries[index1]->SetSeq().SetDescr().Set().push_back( + seqdesc_first_partial); + bioseq_set.SetSeq_set().push_back(m_Entries[index1]); + } + + if (index2 >= 0) { + m_Entries[index2]->SetSeq().SetDescr().Set().push_back( + seqdesc_last_partial); + bioseq_set.SetSeq_set().push_back(m_Entries[index2]); + } + } + } + + return true; +} + + +bool CASN1InputSourceOMF::x_ValidateSequence(const CSeq_data& seq_data, + int length) +{ + string sequence; + int entropy; + + switch (seq_data.Which()) { + + case CSeq_data::e_Ncbi2na: + // Ncbi2na format does not have ambiguous bases, hence only compute + // entropy and exit + entropy = x_FindDimerEntropy2NA(seq_data.GetNcbi2na().Get(), length); + return entropy > 16; + + + case CSeq_data::e_Ncbi4na: + // convert sequence to Iupac + CSeqConvert::Convert(seq_data.GetNcbi4na().Get(), + CSeqUtil::e_Ncbi4na, 0, length, + sequence, CSeqUtil::e_Iupacna); + break; + + case CSeq_data::e_Ncbi8na: + // convert sequence to Iupac + CSeqConvert::Convert(seq_data.GetNcbi8na().Get(), + CSeqUtil::e_Ncbi8na, 0, length, + sequence, CSeqUtil::e_Iupacna); + break; + + case CSeq_data::e_Iupacna: + sequence.resize(length); + memcpy(&sequence[0], seq_data.GetIupacna().Get().c_str(), + length * sizeof(Uint1)); + break; + + default: + NCBI_THROW(CInputException, eInvalidInput, "Encoding not handled " + "for input sequences"); + + }; + + // find number of ambiguous bases + const char* s = sequence.c_str(); + const int kNBase = (int)'N'; + const double kMaxFractionAmbiguousBases = 0.5; + int num = 0; + for (int i=0;i < length;i++) { + num += (toupper((int)s[i]) == kNBase); + } + + if ((double)num / length > kMaxFractionAmbiguousBases) { + return false; + } + + // find dimer entropy + entropy = FindDimerEntropy(sequence.c_str(), length); + return entropy > 16; +} + + +int CASN1InputSourceOMF::x_FindDimerEntropy2NA(const vector& sequence, + int length) +{ + const int kNumDimers = 1 << 4; + int counts[kNumDimers]; + memset(counts, 0, kNumDimers * sizeof(int)); + int num = 0; + Uint1 mask = 0xc0; + Uint1 base; + int dimer; + int k = 0; + int i = 0; + + // count dimers + dimer = (sequence[i] & (mask >> k)) >> (2*(3 - k)); + k++; + num++; + while (num < length) { + _ASSERT(i < (int)sequence.size()); + for (;k < 4;k++) { + base = (sequence[i] & (mask >> k)) >> (2*(3 - k)); + dimer = ((dimer << 2) | base) & 0xf; + counts[dimer]++; + num++; + } + k = 0; + i++; + } + + // compute amount of information in the sequence + double sum = 0.0; + for (int i=0;i < kNumDimers;i++) { + if (counts[i]) { + sum += (double)counts[i] * log((double)counts[i] / num); + } + } + + return -sum * (1.0 /(log(16.0))) + 0.5; +} + + +END_SCOPE(blast) +END_NCBI_SCOPE diff --git a/c++/src/algo/blast/blastinput/blast_fasta_input.cpp b/c++/src/algo/blast/blastinput/blast_fasta_input.cpp index 1fba5b78..90d49e71 100644 --- a/c++/src/algo/blast/blastinput/blast_fasta_input.cpp +++ b/c++/src/algo/blast/blastinput/blast_fasta_input.cpp @@ -1,4 +1,4 @@ -/* $Id: blast_fasta_input.cpp 489949 2016-01-20 12:32:48Z madden $ +/* $Id: blast_fasta_input.cpp 517821 2016-10-27 19:13:57Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -31,11 +31,6 @@ * Convert FASTA-formatted files into blast sequence input */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_fasta_input.cpp 489949 2016-01-20 12:32:48Z madden $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include @@ -47,6 +42,7 @@ static char const rcsid[] = #include #include +#include #include #include @@ -236,10 +232,40 @@ private: }; +/// Stream line reader that converts gaps to Ns before returning each line +class CStreamLineReaderConverter : public CStreamLineReader +{ +public: + + CStreamLineReaderConverter(CNcbiIstream& instream) + : CStreamLineReader(instream) {} + + CStreamLineReaderConverter& operator++(void){ + CStreamLineReader::operator++(); + CTempString line = CStreamLineReader::operator*(); + if (NStr::StartsWith(line, ">")) { + m_ConvLine = line; + } + else { + m_ConvLine = NStr::Replace(line, "-", "N"); + } + return *this; + } + + CTempString operator*(void) const { + return CTempString(m_ConvLine); + } + +private: + string m_ConvLine; +}; + CBlastFastaInputSource::CBlastFastaInputSource(CNcbiIstream& infile, const CBlastInputSourceConfig& iconfig) : m_Config(iconfig), - m_LineReader(new CStreamLineReader(infile)), + m_LineReader(iconfig.GetConvertGapsToNs() ? + new CStreamLineReaderConverter(infile) : + new CStreamLineReader(infile)), m_ReadProteins(iconfig.IsProteinInput()) { x_InitInputReader(); @@ -298,6 +324,7 @@ CBlastFastaInputSource::x_InitInputReader() m_InputReader->IgnoreProblem(ILineError::eProblem_ModifierFoundButNoneExpected); m_InputReader->IgnoreProblem(ILineError::eProblem_TooLong); + m_InputReader->IgnoreProblem(ILineError::eProblem_TooManyAmbiguousResidues); //m_InputReader->IgnoreProblem(ILineError::eProblem_InvalidResidue); //m_InputReader->IgnoreProblem(ILineError::eProblem_IgnoredResidue); @@ -442,5 +469,698 @@ CBlastFastaInputSource::GetNextSequence(CScope& scope) (new CBlastSearchQuery(*seqloc, scope, masks_in_query)); } + +CShortReadFastaInputSource::CShortReadFastaInputSource(CNcbiIstream& infile, + TSeqPos num_seqs, + CShortReadFastaInputSource::EInputFormat format, + bool paired, + bool validate) + : m_NumSeqsInBatch(num_seqs), + m_SeqBuffLen(550), + m_LineReader(new CStreamLineReader(infile)), + m_IsPaired(paired), + m_Validate(validate), + m_NumRejected(0), + m_Format(format) +{ + // allocate sequence buffer + m_Sequence.reserve(m_SeqBuffLen + 1); + + // read the first line for FASTA input + if (m_Format == eFasta) { + do { + ++(*m_LineReader); + m_Line = **m_LineReader; + } while (m_Line.empty() && !m_LineReader->AtEOF()); + + if (m_Line[0] != '>') { + NCBI_THROW(CInputException, eInvalidInput, "FASTA parse error: " + "defline expected"); + } + } +} + +CShortReadFastaInputSource::CShortReadFastaInputSource(CNcbiIstream& infile1, + CNcbiIstream& infile2, + TSeqPos num_seqs, + CShortReadFastaInputSource::EInputFormat format, + bool validate) + : m_NumSeqsInBatch(num_seqs), + m_SeqBuffLen(550), + m_LineReader(new CStreamLineReader(infile1)), + m_SecondLineReader(new CStreamLineReader(infile2)), + m_IsPaired(true), + m_Validate(validate), + m_NumRejected(0), + m_Format(format) +{ + if (m_Format == eFastc) { + m_LineReader.Reset(); + m_SecondLineReader.Reset(); + + NCBI_THROW(CInputException, eInvalidInput, "FASTC format cannot be " + "used with two input files"); + } + + // allocate sequence buffer + m_Sequence.reserve(m_SeqBuffLen + 1); + + // read the first line for FASTA input + if (m_Format == eFasta) { + CTempString line; + do { + ++(*m_LineReader); + line = **m_LineReader; + } while (line.empty() && !m_LineReader->AtEOF()); + + if (line[0] != '>') { + NCBI_THROW(CInputException, eInvalidInput, "FASTA parse error: " + "defline expected"); + } + + do { + ++(*m_SecondLineReader); + line = **m_SecondLineReader; + } while (line.empty() && !m_SecondLineReader->AtEOF()); + + if (line[0] != '>') { + NCBI_THROW(CInputException, eInvalidInput, "FASTA parse error: " + "defline expected"); + } + } +} + +void +CShortReadFastaInputSource::GetNextNumSequences(CBioseq_set& bioseq_set, + TSeqPos /* num_seqs */) +{ + // preallocate and initialize objects for sequences to be read + m_SeqIds.clear(); + m_Entries.clear(); + + // +1 in case we need to read one more sequence so that a pair is not + // broken + m_SeqIds.resize(m_NumSeqsInBatch + 1); + m_Entries.resize(m_NumSeqsInBatch + 1); + + // allocate seq_id and seq_entry objects, they will be reused to minimize + // time spent on memory management + for (TSeqPos i=0;i < m_NumSeqsInBatch + 1;i++) { + m_SeqIds[i].Reset(new CSeq_id); + m_Entries[i].Reset(new CSeq_entry); + m_Entries[i]->SetSeq().SetInst().SetMol(CSeq_inst::eMol_na); + m_Entries[i]->SetSeq().SetInst().SetRepr(CSeq_inst::eRepr_raw); + } + + // read sequernces + switch (m_Format) { + case eFasta: + if (m_SecondLineReader.NotEmpty()) { + x_ReadFromTwoFiles(bioseq_set, m_Format); + } + else { + x_ReadFasta(bioseq_set); + } + break; + + case eFastq: + if (m_SecondLineReader.NotEmpty()) { + x_ReadFromTwoFiles(bioseq_set, m_Format); + } + else { + x_ReadFastq(bioseq_set); + } + break; + + case eFastc: + x_ReadFastc(bioseq_set); + break; + + default: + NCBI_THROW(CInputException, eInvalidInput, "Unexpected input format"); + + }; + + // detach CRefs from in m_Entries and m_SeqIds from objects in bioseq_set + // for thread safety + m_Entries.clear(); + m_SeqIds.clear(); +} + +void +CShortReadFastaInputSource::x_ReadFasta(CBioseq_set& bioseq_set) +{ + TSeqPos index = 0; + int start = 0; + // parse the last read defline + CTempString id = x_ParseDefline(m_Line); + m_SeqIds[0]->Set(CSeq_id::e_Local, id); + int current_read = 0; + bool first_added = false; + + // tags to indicate paired sequences + CRef seqdesc_first(new CSeqdesc); + seqdesc_first->SetUser().SetType().SetStr("Mapping"); + seqdesc_first->SetUser().AddField("has_pair", eFirstSegment); + + CRef seqdesc_last(new CSeqdesc); + seqdesc_last->SetUser().SetType().SetStr("Mapping"); + seqdesc_last->SetUser().AddField("has_pair", eLastSegment); + + CRef seqdesc_first_partial(new CSeqdesc); + seqdesc_first_partial->SetUser().SetType().SetStr("Mapping"); + seqdesc_first_partial->SetUser().AddField("has_pair", + fFirstSegmentFlag | fPartialFlag); + + CRef seqdesc_last_partial(new CSeqdesc); + seqdesc_last_partial->SetUser().SetType().SetStr("Mapping"); + seqdesc_last_partial->SetUser().AddField("has_pair", + fLastSegmentFlag | fPartialFlag); + + while (index < m_NumSeqsInBatch && !m_LineReader->AtEOF()) { + ++(*m_LineReader); + m_Line = **m_LineReader; + + // ignore empty lines + if (m_Line.empty()) { + continue; + } + + // if defline + if (m_Line[0] == '>') { + + // set up sequence + if (!m_Validate || x_ValidateSequence(m_Sequence.data(), start)) { + CBioseq& bioseq = m_Entries[index]->SetSeq(); + bioseq.SetId().clear(); + bioseq.SetId().push_back(m_SeqIds[index]); + bioseq.SetInst().SetLength(start); + m_Sequence[start] = 0; + bioseq.SetInst().SetSeq_data().SetIupacna(CIUPACna( + &m_Sequence[0])); + + if (m_IsPaired && (current_read & 1) == 0) { + first_added = true; + } + + if (m_IsPaired && (current_read & 1) == 1) { + if (first_added) { + // set paired tags: both sequences of the pair passed + // validation + bioseq_set.SetSeq_set().back()->SetSeq().SetDescr(). + Set().push_back(seqdesc_first); + + m_Entries[index]->SetSeq().SetDescr().Set().push_back( + seqdesc_last); + } + else { + // only the second sequence of the pair passed + // validation + m_Entries[index]->SetSeq().SetDescr().Set().push_back( + seqdesc_last_partial); + } + first_added = false; + } + + // add a sequence to the batch + bioseq_set.SetSeq_set().push_back(m_Entries[index]); + + index++; + } + else { + if (first_added) { + // only the first sequence of the pair passed validation + bioseq_set.SetSeq_set().back()->SetSeq().SetDescr(). + Set().push_back(seqdesc_first_partial); + + } + + m_NumRejected++; + first_added = false; + } + current_read++; + + start = 0; + + // set sequence id for the new sequence + if (index < m_NumSeqsInBatch) { + id = x_ParseDefline(m_Line); + m_SeqIds[index]->Set(CSeq_id::e_Local, id); + } + } + else { + // otherwise copy the sequence + // increase the sequence buffer if necessary + if (start + m_Line.length() + 1 > m_SeqBuffLen) { + string tmp; + m_SeqBuffLen = 2 * (start + m_Line.length() + 1); + tmp.reserve(m_SeqBuffLen); + memcpy(&tmp[0], &m_Sequence[0], start); + m_Sequence.swap(tmp); + } + memcpy(&m_Sequence[start], m_Line.data(), m_Line.length()); + start += m_Line.length(); + } + } + + if (!m_LineReader->AtEOF()) { + return; + } + + if (m_Validate && (!x_ValidateSequence(m_Sequence.data(), start))) { + m_NumRejected++; + if (m_IsPaired) { + if (first_added && (current_read & 1) == 1) { + bioseq_set.SetSeq_set().back()->SetSeq().SetDescr().Set(). + push_back(seqdesc_first_partial); + } + } + + return; + } + + if (m_IsPaired && (current_read & 1) == 1 && first_added) { + // add the tag for paired reads + bioseq_set.SetSeq_set().back()->SetSeq().SetDescr().Set(). + push_back(seqdesc_first); + } + + // set up the last sequence read + CBioseq& bioseq = m_Entries[index]->SetSeq(); + bioseq.SetId().clear(); + bioseq.SetId().push_back(m_SeqIds[index]); + bioseq.SetInst().SetLength(start); + m_Sequence[start] = 0; + bioseq.SetInst().SetSeq_data().SetIupacna(CIUPACna(&m_Sequence[0])); + bioseq_set.SetSeq_set().push_back(m_Entries[index]); + + if (m_IsPaired && (current_read & 1) == 1) { + bioseq_set.SetSeq_set().back()->SetSeq().SetDescr().Set(). + push_back(first_added ? seqdesc_last : seqdesc_last_partial); + } +} + + +void +CShortReadFastaInputSource::x_ReadFastc(CBioseq_set& bioseq_set) +{ + TSeqPos index = 0; + string id; + + // tags to indicate paired sequences + CRef seqdesc_first(new CSeqdesc); + seqdesc_first->SetUser().SetType().SetStr("Mapping"); + seqdesc_first->SetUser().AddField("has_pair", eFirstSegment); + + CRef seqdesc_last(new CSeqdesc); + seqdesc_last->SetUser().SetType().SetStr("Mapping"); + seqdesc_last->SetUser().AddField("has_pair", eLastSegment); + + while (index < m_NumSeqsInBatch && !m_LineReader->AtEOF()) { + ++(*m_LineReader); + m_Line = **m_LineReader; + + // ignore empty lines + if (m_Line.empty()) { + continue; + } + + // if defline + if (m_Line[0] == '>') { + id = x_ParseDefline(m_Line); + } + else { + // otherwise sequence + + // make sure that a defline was read first + if (id.empty()) { + NCBI_THROW(CInputException, eInvalidInput, + (string)"Missing defline before line: " + + NStr::IntToString(m_LineReader->GetLineNumber())); + } + + // find '><' that separate reads of a pair + size_t p = m_Line.find('>'); + if (p == CTempString::npos || m_Line[p + 1] != '<') { + + NCBI_THROW(CInputException, eInvalidInput, + (string)"FASTC parse error: Sequence separator '><'" + " was not found in line: " + + NStr::IntToString(m_LineReader->GetLineNumber())); + } + + // set up reads, there are two sequences in the same line separated + char* first = (char*)m_Line.data(); + char* second = (char*)m_Line.data() + p + 2; + size_t first_len = p; + size_t second_len = m_Line.length() - p - 2; + + // FIXME: Both reads are rejected if only one fails validation + if (x_ValidateSequence(first, first_len) && + x_ValidateSequence(second, second_len)) { + + {{ + CBioseq& bioseq = m_Entries[index]->SetSeq(); + bioseq.SetId().clear(); + m_SeqIds[index]->Set(CSeq_id::e_Local, id + ".1"); + bioseq.SetId().push_back(m_SeqIds[index]); + bioseq.SetInst().SetLength(first_len); + first[first_len] = 0; + bioseq.SetInst().SetSeq_data().SetIupacna(CIUPACna(first)); + + bioseq.SetDescr().Set().push_back(seqdesc_first); + }} + // add a sequence to the batch + bioseq_set.SetSeq_set().push_back(m_Entries[index]); + index++; + + {{ + CBioseq& bioseq = m_Entries[index]->SetSeq(); + bioseq.SetId().clear(); + m_SeqIds[index]->Set(CSeq_id::e_Local, id + ".2"); + bioseq.SetId().push_back(m_SeqIds[index]); + bioseq.SetInst().SetLength(second_len); + second[second_len] = 0; + bioseq.SetInst().SetSeq_data().SetIupacna(CIUPACna(second)); + + bioseq.SetDescr().Set().push_back(seqdesc_last); + }} + // add a sequence to the batch + bioseq_set.SetSeq_set().push_back(m_Entries[index]); + index++; + } + else { + m_NumRejected++; + } + id.clear(); + } + } +} + + +void +CShortReadFastaInputSource::x_ReadFastq(CBioseq_set& bioseq_set) +{ + int current_read = 0; + bool first_added = false; + + // tags to indicate paired sequences + CRef seqdesc_first(new CSeqdesc); + seqdesc_first->SetUser().SetType().SetStr("Mapping"); + seqdesc_first->SetUser().AddField("has_pair", eFirstSegment); + + CRef seqdesc_last(new CSeqdesc); + seqdesc_last->SetUser().SetType().SetStr("Mapping"); + seqdesc_last->SetUser().AddField("has_pair", eLastSegment); + + CRef seqdesc_first_partial(new CSeqdesc); + seqdesc_first_partial->SetUser().SetType().SetStr("Mapping"); + seqdesc_first_partial->SetUser().AddField("has_pair", + fFirstSegmentFlag | fPartialFlag); + + CRef seqdesc_last_partial(new CSeqdesc); + seqdesc_last_partial->SetUser().SetType().SetStr("Mapping"); + seqdesc_last_partial->SetUser().AddField("has_pair", + fLastSegmentFlag | fPartialFlag); + + m_Index = 0; + while (m_Index < (int)m_NumSeqsInBatch && !m_LineReader->AtEOF()) { + int index = x_ReadFastqOneSeq(m_LineReader); + + if (index >= 0) { + + if (m_IsPaired && (current_read & 1) == 0) { + first_added = true; + } + + if (m_IsPaired && (current_read & 1) == 1) { + if (first_added) { + // this field indicates that this sequence has a pair + bioseq_set.SetSeq_set().back()->SetSeq().SetDescr().Set(). + push_back(seqdesc_first); + + m_Entries[index]->SetSeq().SetDescr().Set().push_back( + seqdesc_last); + } + else { + m_Entries[index]->SetSeq().SetDescr().Set().push_back( + seqdesc_last_partial); + } + first_added = false; + } + + bioseq_set.SetSeq_set().push_back(m_Entries[index]); + } + else { + if (first_added) { + bioseq_set.SetSeq_set().back()->SetSeq().SetDescr().Set(). + push_back(seqdesc_first_partial); + } + + m_NumRejected++; + first_added = false; + } + current_read++; + } + +} + + +int +CShortReadFastaInputSource::x_ReadFastaOneSeq(CRef line_reader) +{ + int start = 0; + // parse the last read defline + CTempString line = **line_reader; + CTempString id = x_ParseDefline(line); + m_SeqIds[m_Index]->Set(CSeq_id::e_Local, id); + ++(*line_reader); + line = **line_reader; + while (line[0] != '>') { + + // ignore empty lines + if (line.empty() && !line_reader->AtEOF()) { + ++(*line_reader); + line = **line_reader; + continue; + } + + // copy the sequence + // increase the sequence buffer if necessary + if (start + line.length() + 1 > m_SeqBuffLen) { + string tmp; + m_SeqBuffLen = 2 * (start + line.length() + 1); + tmp.reserve(m_SeqBuffLen); + memcpy(&tmp[0], &m_Sequence[0], start); + m_Sequence.swap(tmp); + } + memcpy(&m_Sequence[start], line.data(), line.length()); + start += line.length(); + + if (line_reader->AtEOF()) { + break; + } + + // read next line + ++(*line_reader); + line = **line_reader; + } + + // set up sequence + if (!m_Validate || x_ValidateSequence(m_Sequence.data(), start)) { + + CBioseq& bioseq = m_Entries[m_Index]->SetSeq(); + bioseq.SetId().clear(); + bioseq.SetId().push_back(m_SeqIds[m_Index]); + bioseq.SetInst().SetLength(start); + m_Sequence[start] = 0; + bioseq.SetInst().SetSeq_data().SetIupacna(CIUPACna(&m_Sequence[0])); + + m_Index++; + return m_Index - 1; + } + + return -1; +} + + +int +CShortReadFastaInputSource::x_ReadFastqOneSeq(CRef line_reader) +{ + CTempString line; + CTempString id; + int retval = -1; + + // first read defline + ++(*line_reader); + line = **line_reader; + + // skip empty lines + while (!line_reader->AtEOF() && line.empty()) { + ++(*line_reader); + line = **line_reader; + } + + if (line[0] != '@') { + NCBI_THROW(CInputException, eInvalidInput, (string)"FASTQ parse error:" + " defline expected at line: " + + NStr::IntToString(line_reader->GetLineNumber())); + } + + id = x_ParseDefline(line); + m_SeqIds[m_Index]->Set(CSeq_id::e_Local, id); + + // read sequence + ++(*line_reader); + line = **line_reader; + // skip empty lines + while (!line_reader->AtEOF() && line.empty()) { + ++(*line_reader); + line = **line_reader; + } + + // set up sequence + if (!m_Validate || x_ValidateSequence(line.data(), line.length())) { + + CBioseq& bioseq = m_Entries[m_Index]->SetSeq(); + bioseq.SetId().clear(); + bioseq.SetId().push_back(m_SeqIds[m_Index]); + bioseq.SetInst().SetLength(line.length()); + bioseq.SetInst().SetSeq_data().SetIupacna(CIUPACna(line.data())); + + m_Index++; + retval = m_Index - 1; + } + + // read and skip second defline + ++(*line_reader); + line = **line_reader; + // skip empty lines + while (!line_reader->AtEOF() && line.empty()) { + ++(*line_reader); + line = **line_reader; + } + + if (line[0] != '+') { + NCBI_THROW(CInputException, eInvalidInput, (string)"FASTQ parse error:" + " defline expected at line: " + + NStr::IntToString(line_reader->GetLineNumber())); + } + + // read and skip quality scores + ++(*line_reader); + line = **line_reader; + // skip empty lines + while (!line_reader->AtEOF() && line.empty()) { + ++(*line_reader); + line = **line_reader; + } + + return retval; +} + + +bool +CShortReadFastaInputSource::x_ReadFromTwoFiles(CBioseq_set& bioseq_set, + CShortReadFastaInputSource::EInputFormat format) +{ + if (format == eFastc) { + NCBI_THROW(CInputException, eInvalidInput, "FASTC format cannot be " + "used with two files"); + } + + // tags to indicate paired sequences + CRef seqdesc_first(new CSeqdesc); + seqdesc_first->SetUser().SetType().SetStr("Mapping"); + seqdesc_first->SetUser().AddField("has_pair", eFirstSegment); + + CRef seqdesc_last(new CSeqdesc); + seqdesc_last->SetUser().SetType().SetStr("Mapping"); + seqdesc_last->SetUser().AddField("has_pair", eLastSegment); + + CRef seqdesc_first_partial(new CSeqdesc); + seqdesc_first_partial->SetUser().SetType().SetStr("Mapping"); + seqdesc_first_partial->SetUser().AddField("has_pair", + fFirstSegmentFlag | fPartialFlag); + + CRef seqdesc_last_partial(new CSeqdesc); + seqdesc_last_partial->SetUser().SetType().SetStr("Mapping"); + seqdesc_last_partial->SetUser().AddField("has_pair", + fLastSegmentFlag | fPartialFlag); + + int index1; + int index2; + m_Index = 0; + while (m_Index < (int)m_NumSeqsInBatch && !m_LineReader->AtEOF() && + !m_SecondLineReader->AtEOF()) { + + if (format == eFasta) { + index1 = x_ReadFastaOneSeq(m_LineReader); + index2 = x_ReadFastaOneSeq(m_SecondLineReader); + } + else { + index1 = x_ReadFastqOneSeq(m_LineReader); + index2 = x_ReadFastqOneSeq(m_SecondLineReader); + } + + if (index1 >= 0) { + if (index2 >= 0) { + m_Entries[index1]->SetSeq().SetDescr().Set().push_back( + seqdesc_first); + } + else { + m_Entries[index1]->SetSeq().SetDescr().Set().push_back( + seqdesc_first_partial); + } + bioseq_set.SetSeq_set().push_back(m_Entries[index1]); + } + + if (index2 >= 0) { + if (index1 >= 0) { + m_Entries[index2]->SetSeq().SetDescr().Set().push_back( + seqdesc_last); + } + else { + m_Entries[index2]->SetSeq().SetDescr().Set().push_back( + seqdesc_last_partial); + } + bioseq_set.SetSeq_set().push_back(m_Entries[index2]); + } + } + + return true; +} + + +CTempString CShortReadFastaInputSource::x_ParseDefline(CTempString& line) +{ + // set local sequence id for the new sequence as the string between '>' + // and the first space + size_t begin = 1; + size_t end = line.find(' ', 1); + CTempString id = line.substr(begin, end - begin); + return id; +} + + +bool CShortReadFastaInputSource::x_ValidateSequence(const char* sequence, + int length) +{ + const char* s = sequence; + const int kNBase = (int)'N'; + const double kMaxFractionAmbiguousBases = 0.5; + int num = 0; + for (int i=0;i < length;i++) { + num += (toupper((int)s[i]) == kNBase); + } + + if ((double)num / length > kMaxFractionAmbiguousBases) { + return false; + } + + int entropy = FindDimerEntropy(sequence, length); + return entropy > 16; +} + END_SCOPE(blast) END_NCBI_SCOPE diff --git a/c++/src/algo/blast/blastinput/blast_input.cpp b/c++/src/algo/blast/blastinput/blast_input.cpp index 2daf9683..1b171509 100644 --- a/c++/src/algo/blast/blastinput/blast_input.cpp +++ b/c++/src/algo/blast/blastinput/blast_input.cpp @@ -1,4 +1,4 @@ -/* $Id: blast_input.cpp 458462 2015-02-05 14:10:55Z camacho $ +/* $Id: blast_input.cpp 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -31,11 +31,6 @@ * Convert sources of sequence data into blast sequence input */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_input.cpp 458462 2015-02-05 14:10:55Z camacho $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include @@ -63,7 +58,8 @@ CBlastInputSourceConfig::CBlastInputSourceConfig m_BelieveDeflines(believe_defline), m_Range(range), m_DLConfig(dlconfig), m_RetrieveSeqData(retrieve_seq_data), m_LocalIdCounter(local_id_counter), - m_SeqLenThreshold2Guess(seqlen_thresh2guess) + m_SeqLenThreshold2Guess(seqlen_thresh2guess), + m_GapsToNs(false) { // Set an appropriate default for the strand if (m_Strand == eNa_strand_other) { @@ -280,5 +276,28 @@ CBlastBioseqMaker::IsEmptyBioseq(const CBioseq& bioseq) } +CBlastInputOMF::CBlastInputOMF(CRef source, + TSeqPos num_seqs) + : m_Source(source), + m_NumSeqsInBatch(num_seqs), + m_BioseqSet(new CBioseq_set) + +{} + +void +CBlastInputOMF::GetNextSeqBatch(CBioseq_set& bioseq_set) +{ + m_Source->GetNextNumSequences(bioseq_set, m_NumSeqsInBatch); +} + +CRef +CBlastInputOMF::GetNextSeqBatch(void) +{ + m_BioseqSet->SetSeq_set().clear(); + m_Source->GetNextNumSequences(*m_BioseqSet, m_NumSeqsInBatch); + return m_BioseqSet; +} + + END_SCOPE(blast) END_NCBI_SCOPE diff --git a/c++/src/algo/blast/blastinput/blast_input_aux.cpp b/c++/src/algo/blast/blastinput/blast_input_aux.cpp index b2164905..07df8ce6 100644 --- a/c++/src/algo/blast/blastinput/blast_input_aux.cpp +++ b/c++/src/algo/blast/blastinput/blast_input_aux.cpp @@ -1,4 +1,4 @@ -/* $Id: blast_input_aux.cpp 489109 2016-01-08 15:13:42Z fongah2 $ +/* $Id: blast_input_aux.cpp 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -31,11 +31,6 @@ * Auxiliary functions for BLAST input library */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_input_aux.cpp 489109 2016-01-08 15:13:42Z fongah2 $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include @@ -110,6 +105,7 @@ GetQueryBatchSize(EProgram program, bool is_ungapped /* = false */, retval = 500000; break; case eMegablast: + case eMapper: retval = 5000000; break; case eTblastn: @@ -217,7 +213,8 @@ ReadSequencesToBlast(CNcbiIstream& in, const TSeqRange& range, bool parse_deflines, bool use_lcase_masking, - CRef& sequences) + CRef& sequences, + bool gaps_to_Ns /* = false */) { SDataLoaderConfig dlconfig(read_proteins); dlconfig.OptimizeForWholeLargeSequenceRetrieval(); @@ -227,6 +224,9 @@ ReadSequencesToBlast(CNcbiIstream& in, iconfig.SetBelieveDeflines(parse_deflines); iconfig.SetLowercaseMask(use_lcase_masking); iconfig.SetSubjectLocalIdMode(); + if (!read_proteins && gaps_to_Ns) { + iconfig.SetConvertGapsToNs(true); + } CRef fasta(new CBlastFastaInputSource(in, iconfig)); CRef input(new CBlastInput(fasta)); @@ -426,5 +426,36 @@ CheckForEmptySequences(CRef sequences, string& warnings) } } +// compute enrtopy of 2-mers in a IUPACNA sequence +int FindDimerEntropy(const char* sequence, int length) +{ + const int kNumDimers = 1 << 4; + int counts[kNumDimers]; + memset(counts, 0, kNumDimers * sizeof(int)); + int num = 0; + // count dimers + for (int i=0;i < length - 1;i++) { + Uint1 base_1 = IUPACNA_TO_BLASTNA[toupper((int)sequence[i])]; + Uint1 base_2 = IUPACNA_TO_BLASTNA[toupper((int)sequence[i + 1])]; + if ((base_1 & 0xfc) == 0 && (base_2 & 0xfc) == 0) { + int dimer = (base_1 << 2) | base_2; + counts[dimer]++; + num++; + } + } + + // compute amount of information in the sequence + double sum = 0.0; + for (int i=0;i < kNumDimers;i++) { + if (counts[i]) { + sum += (double)counts[i] * log((double)counts[i] / num); + } + } + + return -sum * (1.0 /(log(16.0))) + 0.5; +} + + + END_SCOPE(blast) END_NCBI_SCOPE diff --git a/c++/src/algo/blast/blastinput/blast_scope_src.cpp b/c++/src/algo/blast/blastinput/blast_scope_src.cpp index 563e515a..b7517dff 100644 --- a/c++/src/algo/blast/blastinput/blast_scope_src.cpp +++ b/c++/src/algo/blast/blastinput/blast_scope_src.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_scope_src.cpp 445894 2014-09-09 15:49:42Z boratyng $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -68,21 +64,21 @@ SDataLoaderConfig::x_Init(SDataLoaderConfig::EConfigOpts options, } m_IsLoadingProteins = load_proteins; - CMetaRegistry::SEntry sentry = - CMetaRegistry::Load("ncbi", CMetaRegistry::eName_RcOrIni); - x_LoadDataLoadersConfig(sentry); - x_LoadBlastDbDataLoaderConfig(sentry); + CNcbiApplication* app = CNcbiApplication::Instance(); + if (app) { + const CNcbiRegistry& registry = app->GetConfig(); + x_LoadDataLoadersConfig(registry); + x_LoadBlastDbDataLoaderConfig(registry); + } } void -SDataLoaderConfig::x_LoadDataLoadersConfig(const CMetaRegistry::SEntry& sentry) +SDataLoaderConfig::x_LoadDataLoadersConfig(const CNcbiRegistry& registry) { static const string kDataLoadersConfig("DATA_LOADERS"); - if (sentry.registry && - sentry.registry->HasEntry("BLAST", kDataLoadersConfig)) { - const string& kLoaders = sentry.registry->Get("BLAST", - kDataLoadersConfig); + if (registry.HasEntry("BLAST", kDataLoadersConfig)) { + const string& kLoaders = registry.Get("BLAST", kDataLoadersConfig); if (NStr::FindNoCase(kLoaders, "blastdb") == NPOS) { m_UseBlastDbs = false; } @@ -99,8 +95,7 @@ SDataLoaderConfig::x_LoadDataLoadersConfig(const CMetaRegistry::SEntry& sentry) } void -SDataLoaderConfig::x_LoadBlastDbDataLoaderConfig - (const CMetaRegistry::SEntry& sentry) +SDataLoaderConfig::x_LoadBlastDbDataLoaderConfig(const CNcbiRegistry& registry) { if ( !m_UseBlastDbs ) { m_BlastDbName.clear(); @@ -119,8 +114,8 @@ SDataLoaderConfig::x_LoadBlastDbDataLoaderConfig ? kProtBlastDbLoaderConfig : kNuclBlastDbLoaderConfig; - if (sentry.registry && sentry.registry->HasEntry("BLAST", config_param)) { - m_BlastDbName = sentry.registry->Get("BLAST", config_param); + if (registry.HasEntry("BLAST", config_param)) { + m_BlastDbName = registry.Get("BLAST", config_param); } else { _ASSERT(m_BlastDbName.empty()); m_BlastDbName = m_IsLoadingProteins diff --git a/c++/src/algo/blast/blastinput/blastn_args.cpp b/c++/src/algo/blast/blastinput/blastn_args.cpp index 61693703..12be18e0 100644 --- a/c++/src/algo/blast/blastinput/blastn_args.cpp +++ b/c++/src/algo/blast/blastinput/blastn_args.cpp @@ -1,4 +1,4 @@ -/* $Id: blastn_args.cpp 474565 2015-07-29 19:26:43Z fongah2 $ +/* $Id: blastn_args.cpp 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -31,11 +31,6 @@ * Implementation of the BLASTN command line arguments */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] - = "$Id: blastn_args.cpp 474565 2015-07-29 19:26:43Z fongah2 $"; -#endif - #include #include #include diff --git a/c++/src/algo/blast/blastinput/blastp_args.cpp b/c++/src/algo/blast/blastinput/blastp_args.cpp index 2d1ee427..75f2d03c 100644 --- a/c++/src/algo/blast/blastinput/blastp_args.cpp +++ b/c++/src/algo/blast/blastinput/blastp_args.cpp @@ -1,4 +1,4 @@ -/* $Id: blastp_args.cpp 448376 2014-10-06 09:52:42Z mcelhany $ +/* $Id: blastp_args.cpp 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -30,11 +30,6 @@ /** @file blastp_args.cpp * Implementation of the BLASTP command line arguments */ - -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = "$Id: blastp_args.cpp 448376 2014-10-06 09:52:42Z mcelhany $"; -#endif - #include #include #include diff --git a/c++/src/algo/blast/blastinput/blastx_args.cpp b/c++/src/algo/blast/blastinput/blastx_args.cpp index fc2e07e2..9f67704f 100644 --- a/c++/src/algo/blast/blastinput/blastx_args.cpp +++ b/c++/src/algo/blast/blastinput/blastx_args.cpp @@ -1,4 +1,4 @@ -/* $Id: blastx_args.cpp 448376 2014-10-06 09:52:42Z mcelhany $ +/* $Id: blastx_args.cpp 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -31,11 +31,6 @@ * Implementation of the BLASTX command line arguments */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] - = "$Id: blastx_args.cpp 448376 2014-10-06 09:52:42Z mcelhany $"; -#endif - #include #include #include diff --git a/c++/src/algo/blast/blastinput/cmdline_flags.cpp b/c++/src/algo/blast/blastinput/cmdline_flags.cpp index c5f57442..bf3659be 100644 --- a/c++/src/algo/blast/blastinput/cmdline_flags.cpp +++ b/c++/src/algo/blast/blastinput/cmdline_flags.cpp @@ -1,4 +1,4 @@ -/* $Id: cmdline_flags.cpp 499246 2016-04-25 11:32:24Z ivanov $ +/* $Id: cmdline_flags.cpp 514854 2016-09-26 17:24:36Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -31,11 +31,6 @@ * Constant definitions for command line arguments for BLAST programs */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: cmdline_flags.cpp 499246 2016-04-25 11:32:24Z ivanov $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #ifndef SKIP_DOXYGEN_PROCESSING @@ -187,6 +182,9 @@ const string kArgGLDomainSystem("domain_system"); const string kArgGLFocusV("focus_on_V_segment"); const string kArgExtendAlign("extend_align5end"); const string kArgMinVLength("min_V_length"); +const string kArgMinJLength("min_J_length"); +const string kArgNumClonotype("num_clonotype"); +const string kArgClonotypeFile("clonotype_out"); const string kArgTranslate("show_translation"); const string kArgMinDMatch("min_D_match"); const string kArgDPenalty("D_penalty"); @@ -215,12 +213,33 @@ const string kDfltArgRpsDb("cdd_delta"); const string kArgDomainInclusionEThreshold("domain_inclusion_ethresh"); const string kArgShowDomainHits("show_domain_hits"); +const string kArgJDistance("thresh"); +const string kDfltArgJDistance("0.05"); +const string kArgMinHits("min_hits"); +const string kDfltArgMinHits("0"); +const string kArgKIndex("dbk"); +const string kDfltArgKIndex("nr"); +const string kArgTargetSeqs("target_seqs"); +const string kDfltArgTargetSeqs("5000"); + const string kArgRid("rid"); const string kArgArchive("archive"); const string kArgQueryCovHspPerc("qcov_hsp_perc"); const string kArgLineLength("line_length"); +const string kArgPaired("paired"); +const string kArgScore("score"); +const string kArgLimitLookup("limit_lookup"); +const string kArgSplice("splice"); +const string kArgLookupStride("lookup_stride"); +const string kArgInputFormat("infmt"); +const string kArgQualityFilter("validate_seqs"); +const string kArgQueryMate("query_mate"); +const string kArgRefType("reftype"); +const string kArgOutputGzip("gzo"); +const string kArgSraAccession("sra"); + END_SCOPE(blast) END_NCBI_SCOPE diff --git a/c++/src/algo/blast/blastinput/deltablast_args.cpp b/c++/src/algo/blast/blastinput/deltablast_args.cpp index fb7c4574..dafc1994 100644 --- a/c++/src/algo/blast/blastinput/deltablast_args.cpp +++ b/c++/src/algo/blast/blastinput/deltablast_args.cpp @@ -1,4 +1,4 @@ -/* $Id: deltablast_args.cpp 483573 2015-11-02 17:48:31Z boratyng $ +/* $Id: deltablast_args.cpp 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -30,11 +30,6 @@ /** @file deltablast_args.cpp * Implementation of the DELTA-BLAST command line arguments */ - -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = "$Id: deltablast_args.cpp 483573 2015-11-02 17:48:31Z boratyng $"; -#endif - #include #include #include diff --git a/c++/src/algo/blast/blastinput/igblastn_args.cpp b/c++/src/algo/blast/blastinput/igblastn_args.cpp index 4ced77f6..94a048b3 100644 --- a/c++/src/algo/blast/blastinput/igblastn_args.cpp +++ b/c++/src/algo/blast/blastinput/igblastn_args.cpp @@ -1,4 +1,4 @@ -/* $Id: igblastn_args.cpp 431056 2014-04-01 15:13:51Z camacho $ +/* $Id: igblastn_args.cpp 514849 2016-09-26 17:23:09Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -31,11 +31,6 @@ * Implementation of the IGBLASTN command line arguments */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] - = "$Id: igblastn_args.cpp 431056 2014-04-01 15:13:51Z camacho $"; -#endif - #include #include #include @@ -142,7 +137,7 @@ CIgBlastnAppArgs::x_CreateOptionsHandle(CBlastOptions::EAPILocality locality, CBlastOptions &opts = retval->SetOptions(); opts.SetMatchReward(1); opts.SetMismatchPenalty(-1); - opts.SetWordSize(11); + opts.SetWordSize(9); opts.SetGapOpeningCost(4); opts.SetGapExtensionCost(1); diff --git a/c++/src/algo/blast/blastinput/igblastp_args.cpp b/c++/src/algo/blast/blastinput/igblastp_args.cpp index 8ea11ce9..401c268b 100644 --- a/c++/src/algo/blast/blastinput/igblastp_args.cpp +++ b/c++/src/algo/blast/blastinput/igblastp_args.cpp @@ -1,4 +1,4 @@ -/* $Id: igblastp_args.cpp 431056 2014-04-01 15:13:51Z camacho $ +/* $Id: igblastp_args.cpp 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -31,11 +31,6 @@ * Implementation of the IGBLASTP command line arguments */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] - = "$Id: igblastp_args.cpp 431056 2014-04-01 15:13:51Z camacho $"; -#endif - #include #include #include diff --git a/c++/src/algo/blast/blastinput/kblastp_args.cpp b/c++/src/algo/blast/blastinput/kblastp_args.cpp new file mode 100644 index 00000000..3bcbb559 --- /dev/null +++ b/c++/src/algo/blast/blastinput/kblastp_args.cpp @@ -0,0 +1,105 @@ +/* $Id: kblastp_args.cpp 514853 2016-09-26 17:24:14Z ivanov $ + * =========================================================================== + * + * PUBLIC DOMAIN NOTICE + * National Center for Biotechnology Information + * + * This software/database is a "United States Government Work" under the + * terms of the United States Copyright Act. It was written as part of + * the author's official duties as a United States Government employee and + * thus cannot be copyrighted. This software/database is freely available + * to the public for use. The National Library of Medicine and the U.S. + * Government have not placed any restriction on its use or reproduction. + * + * Although all reasonable efforts have been taken to ensure the accuracy + * and reliability of the software and data, the NLM and the U.S. + * Government do not and cannot warrant the performance or results that + * may be obtained by using this software or data. The NLM and the U.S. + * Government disclaim all warranties, express or implied, including + * warranties of performance, merchantability or fitness for any particular + * purpose. + * + * Please cite the author in any work or product based on this material. + * + * =========================================================================== + * + * Author: Tom Madden + * + */ + +/** @file kblastp_args.cpp + * Implementation of the BLASTP command line arguments + */ +#include +#include +#include +#include +#include +#include + +BEGIN_NCBI_SCOPE +BEGIN_SCOPE(blast) +USING_SCOPE(objects); + +CKBlastpAppArgs::CKBlastpAppArgs() +{ + CRef arg; + static const string kProgram("kblastp"); + arg.Reset(new CProgramDescriptionArgs(kProgram, "Protein-Protein BLAST")); + const bool kQueryIsProtein = true; + bool const kFilterByDefault = false; + m_Args.push_back(arg); + m_ClientId = kProgram + " " + CBlastVersion().Print(); + + // m_BlastDbArgs.Reset(new CBlastDatabaseArgs); + // m_BlastDbArgs->SetDatabaseMaskingSupport(false); + // arg.Reset(m_BlastDbArgs); + // m_Args.push_back(arg); + + m_StdCmdLineArgs.Reset(new CStdCmdLineArgs); + arg.Reset(m_StdCmdLineArgs); + m_Args.push_back(arg); + + arg.Reset(new CGenericSearchArgs(kQueryIsProtein)); + m_Args.push_back(arg); + + // arg.Reset(new CFilteringArgs(kQueryIsProtein, kFilterByDefault)); + // m_Args.push_back(arg); + + m_QueryOptsArgs.Reset(new CQueryOptionsArgs(kQueryIsProtein)); + arg.Reset(m_QueryOptsArgs); + m_Args.push_back(arg); + + m_FormattingArgs.Reset(new CFormattingArgs); + arg.Reset(m_FormattingArgs); + m_Args.push_back(arg); + + m_MTArgs.Reset(new CMTArgs); + arg.Reset(m_MTArgs); + m_Args.push_back(arg); + + m_KBlastpArgs.Reset(new CKBlastpArgs); + arg.Reset(m_KBlastpArgs); + m_Args.push_back(arg); + + m_DebugArgs.Reset(new CDebugArgs); + arg.Reset(m_DebugArgs); + m_Args.push_back(arg); +} + +CRef +CKBlastpAppArgs::x_CreateOptionsHandle(CBlastOptions::EAPILocality locality, + const CArgs& args) +{ + return CRef(new CBlastProteinOptionsHandle(locality)); +} + +int +CKBlastpAppArgs::GetQueryBatchSize() const +{ + return 10000; +} + +END_SCOPE(blast) +END_NCBI_SCOPE + diff --git a/c++/src/algo/blast/blastinput/magicblast_args.cpp b/c++/src/algo/blast/blastinput/magicblast_args.cpp new file mode 100644 index 00000000..3e6f5ec7 --- /dev/null +++ b/c++/src/algo/blast/blastinput/magicblast_args.cpp @@ -0,0 +1,278 @@ +/* $Id: magicblast_args.cpp 517510 2016-10-25 17:24:24Z ivanov $ + * =========================================================================== + * + * PUBLIC DOMAIN NOTICE + * National Center for Biotechnology Information + * + * This software/database is a "United States Government Work" under the + * terms of the United States Copyright Act. It was written as part of + * the author's official duties as a United States Government employee and + * thus cannot be copyrighted. This software/database is freely available + * to the public for use. The National Library of Medicine and the U.S. + * Government have not placed any restriction on its use or reproduction. + * + * Although all reasonable efforts have been taken to ensure the accuracy + * and reliability of the software and data, the NLM and the U.S. + * Government do not and cannot warrant the performance or results that + * may be obtained by using this software or data. The NLM and the U.S. + * Government disclaim all warranties, express or implied, including + * warranties of performance, merchantability or fitness for any particular + * purpose. + * + * Please cite the author in any work or product based on this material. + * + * =========================================================================== + * + * Author: Greg Boratyn + * + */ + +/** @file blastmapper_args.cpp + * Implementation of the BLASTMAPPER command line arguments + */ + +#include +#include +#include +#include +#include +//#include +#include + +BEGIN_NCBI_SCOPE +BEGIN_SCOPE(blast) +USING_SCOPE(objects); + +/// Special generic search arguments for blastmapper +class CMapperGenericSearchArgs : public CGenericSearchArgs +{ +public: + CMapperGenericSearchArgs(void) : CGenericSearchArgs(false) {} + + virtual void SetArgumentDescriptions(CArgDescriptions& arg_desc) { + + arg_desc.SetCurrentGroup("General search options"); + + arg_desc.AddOptionalKey(kArgWordSize, "int_value", "Word size for " + "wordfinder algorithm (length of best perfect " + "match)", CArgDescriptions::eInteger); + + arg_desc.SetConstraint(kArgWordSize, + new CArgAllowValuesGreaterThanOrEqual(12)); + + + // gap open penalty + arg_desc.AddOptionalKey(kArgGapOpen, "open_penalty", + "Cost to open a gap", + CArgDescriptions::eInteger); + + // gap extend penalty + arg_desc.AddOptionalKey(kArgGapExtend, "extend_penalty", + "Cost to extend a gap", + CArgDescriptions::eInteger); + + // FIXME: not sure if this one is needed + arg_desc.SetCurrentGroup("Restrict search or results"); + arg_desc.AddOptionalKey(kArgPercentIdentity, "float_value", + "Percent identity", + CArgDescriptions::eDouble); + arg_desc.SetConstraint(kArgPercentIdentity, + new CArgAllow_Doubles(0.0, 100.0)); + } +}; + +/// Nucleotide args with no reward score +class CMapperNuclArgs : public CNuclArgs +{ +public: + CMapperNuclArgs(void) : CNuclArgs() {} + + virtual void SetArgumentDescriptions(CArgDescriptions& arg_desc) { + arg_desc.SetCurrentGroup("General search options"); + // blastn mismatch penalty + arg_desc.AddOptionalKey(kArgMismatch, "penalty", + "Penalty for a nucleotide mismatch", + CArgDescriptions::eInteger); + arg_desc.SetConstraint(kArgMismatch, + new CArgAllowValuesLessThanOrEqual(0)); + arg_desc.SetCurrentGroup(""); + } +}; + +/// Formatting args advertising only SAM and fast tabular formats +class CMapperFormattingArgs : public CFormattingArgs +{ +public: + + CMapperFormattingArgs(void) : CFormattingArgs() {} + + virtual void SetArgumentDescriptions(CArgDescriptions& arg_desc) { + arg_desc.SetCurrentGroup("Formatting options"); + string kOutputFormatDescription = string( + "alignment view options:\n" + "sam = SAM format,\n" + "tabular = Tabular format,\n" + "asn = text ASN.1\n"); + + arg_desc.AddDefaultKey(align_format::kArgOutputFormat, "format", + kOutputFormatDescription, + CArgDescriptions::eString, + "sam"); + + set allowed_formats = {"sam", "tabular", "asn"}; + arg_desc.SetConstraint(align_format::kArgOutputFormat, + new CArgAllowStringSet(allowed_formats)); + + arg_desc.SetCurrentGroup(""); + } + + virtual void ExtractAlgorithmOptions(const CArgs& args, CBlastOptions& opt) { + if (args.Exist(align_format::kArgOutputFormat)) { + string fmt_choice = args[align_format::kArgOutputFormat].AsString(); + if (fmt_choice == "sam") { + m_OutputFormat = eSAM; + } + else if (fmt_choice == "tabular") { + m_OutputFormat = eTabular; + } + else if (fmt_choice == "asn") { + m_OutputFormat = eAsnText; + } + else { + CNcbiOstrstream os; + os << "'" << fmt_choice << "' is not a valid output format"; + string msg = CNcbiOstrstreamToString(os); + NCBI_THROW(CInputException, eInvalidInput, msg); + } + } + + m_ShowGis = true; + m_Html = false; + + // only the fast tabular format is able to show merged HSPs with + // common query bases + if (m_OutputFormat != eTabular) { + // FIXME: This is a hack. Merging should be done by the formatter, + // but is currently done by HSP stream writer. This is an easy + // switch until merging is implemented properly. + CNcbiEnvironment().Set("MAPPER_NO_OVERLAPPED_HSP_MERGE", "1"); + } + } + + virtual bool ArchiveFormatRequested(const CArgs& args) const { + return false; + } +}; + +/// Longest intron size with non-zero defalut value +class CMapperLargestIntronSizeArgs : public CLargestIntronSizeArgs +{ +public: + virtual void SetArgumentDescriptions(CArgDescriptions& arg_desc) { + arg_desc.SetCurrentGroup("General search options"); + // largest intron length + arg_desc.AddDefaultKey(kArgMaxIntronLength, "length", + "Length of the largest intron allowed in a translated " + "nucleotide sequence when linking multiple distinct " + "alignments", + CArgDescriptions::eInteger, + NStr::IntToString(2000)); + arg_desc.SetConstraint(kArgMaxIntronLength, + new CArgAllowValuesGreaterThanOrEqual(0)); + arg_desc.SetCurrentGroup(""); + } +}; + +/// RemoteArgs with no option for remote +class CMapperRemoteArgs : public CRemoteArgs +{ +public: + virtual void SetArgumentDescriptions(CArgDescriptions& arg_desc) {} +}; + + +/// Program description without BLAST+ version +class CMapperProgramDescriptionArgs : public CProgramDescriptionArgs +{ +public: + CMapperProgramDescriptionArgs(const string& program_name, + const string& program_desc) + : CProgramDescriptionArgs(program_name, program_desc) {} + + virtual void SetArgumentDescriptions(CArgDescriptions& arg_desc) { + arg_desc.SetUsageContext(m_ProgName, m_ProgDesc); + } +}; + +CMagicBlastAppArgs::CMagicBlastAppArgs() +{ + // remove search strategy args added in parent class constructor + m_Args.clear(); + + CRef arg; + static const char kProgram[] = "magicblast"; + arg.Reset(new CMapperProgramDescriptionArgs(kProgram, "Short read mapper")); + m_Args.push_back(arg); + + m_BlastDbArgs.Reset(new CBlastDatabaseArgs(false, false, false, true)); + m_BlastDbArgs->SetDatabaseMaskingSupport(true); + arg.Reset(m_BlastDbArgs); + m_Args.push_back(arg); + + m_StdCmdLineArgs.Reset(new CStdCmdLineArgs); + m_StdCmdLineArgs->SetGzipEnabled(true); + arg.Reset(m_StdCmdLineArgs); + m_Args.push_back(arg); + + arg.Reset(new CMapperGenericSearchArgs); + m_Args.push_back(arg); + + arg.Reset(new CMapperNuclArgs); + m_Args.push_back(arg); + + m_QueryOptsArgs.Reset(new CMapperQueryOptionsArgs); + arg.Reset(m_QueryOptsArgs); + m_Args.push_back(arg); + + arg.Reset(new CMapperFormattingArgs); + m_FormattingArgs.Reset(dynamic_cast( + arg.GetNonNullPointer())); + m_Args.push_back(arg); + + m_MTArgs.Reset(new CMTArgs); + arg.Reset(m_MTArgs); + m_Args.push_back(arg); + + m_RemoteArgs.Reset(new CMapperRemoteArgs); + arg.Reset(m_RemoteArgs); + m_Args.push_back(arg); + + m_DebugArgs.Reset(new CDebugArgs); + arg.Reset(m_DebugArgs); + m_Args.push_back(arg); + + arg.Reset(new CMapperLargestIntronSizeArgs); + m_Args.push_back(arg); + + arg.Reset(new CMappingArgs); + m_Args.push_back(arg); +} + +CRef +CMagicBlastAppArgs::x_CreateOptionsHandle( + CBlastOptions::EAPILocality locality, + const CArgs& args) +{ + return CRef(new CMagicBlastOptionsHandle(locality)); +} + +int +CMagicBlastAppArgs::GetQueryBatchSize() const +{ + bool is_remote = (m_RemoteArgs.NotEmpty() && m_RemoteArgs->ExecuteRemotely()); + return blast::GetQueryBatchSize(ProgramNameToEnum(GetTask()), m_IsUngapped, is_remote, false); +} + +END_SCOPE(blast) +END_NCBI_SCOPE + diff --git a/c++/src/algo/blast/blastinput/psiblast_args.cpp b/c++/src/algo/blast/blastinput/psiblast_args.cpp index 3146f823..ee7e91e1 100644 --- a/c++/src/algo/blast/blastinput/psiblast_args.cpp +++ b/c++/src/algo/blast/blastinput/psiblast_args.cpp @@ -1,4 +1,4 @@ -/* $Id: psiblast_args.cpp 483345 2015-10-30 14:04:13Z boratyng $ +/* $Id: psiblast_args.cpp 516795 2016-10-18 14:21:21Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -30,11 +30,6 @@ /** @file psiblast_args.cpp * Implementation of the PSI-BLAST command line arguments */ - -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = "$Id: psiblast_args.cpp 483345 2015-10-30 14:04:13Z boratyng $"; -#endif - #include #include #include @@ -53,7 +48,7 @@ CPsiBlastAppArgs::CPsiBlastAppArgs() static const string kProgram("psiblast"); CRef arg; arg.Reset(new CProgramDescriptionArgs(kProgram, - "Position-Specific Initiated BLAST")); + "Position-Specific Iterated BLAST")); m_Args.push_back(arg); m_ClientId = kProgram + " " + CBlastVersion().Print(); diff --git a/c++/src/algo/blast/blastinput/rmblastn_args.cpp b/c++/src/algo/blast/blastinput/rmblastn_args.cpp index c5ebd7cb..b869f669 100644 --- a/c++/src/algo/blast/blastinput/rmblastn_args.cpp +++ b/c++/src/algo/blast/blastinput/rmblastn_args.cpp @@ -1,4 +1,4 @@ -/* $Id: rmblastn_args.cpp 431056 2014-04-01 15:13:51Z camacho $ +/* $Id: rmblastn_args.cpp 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -16,11 +16,6 @@ */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] - = "$Id: rmblastn_args.cpp 431056 2014-04-01 15:13:51Z camacho $"; -#endif - #include #include #include diff --git a/c++/src/algo/blast/blastinput/rpsblast_args.cpp b/c++/src/algo/blast/blastinput/rpsblast_args.cpp index 1a541733..677f1b2b 100644 --- a/c++/src/algo/blast/blastinput/rpsblast_args.cpp +++ b/c++/src/algo/blast/blastinput/rpsblast_args.cpp @@ -1,4 +1,4 @@ -/* $Id: rpsblast_args.cpp 448376 2014-10-06 09:52:42Z mcelhany $ +/* $Id: rpsblast_args.cpp 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -30,11 +30,6 @@ /** @file rpsblast_args.cpp * Implementation of the RPSBLAST command line arguments */ - -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = "$Id: rpsblast_args.cpp 448376 2014-10-06 09:52:42Z mcelhany $"; -#endif - #include #include #include diff --git a/c++/src/algo/blast/blastinput/rpstblastn_args.cpp b/c++/src/algo/blast/blastinput/rpstblastn_args.cpp index 624d0fa4..98ae1ab8 100644 --- a/c++/src/algo/blast/blastinput/rpstblastn_args.cpp +++ b/c++/src/algo/blast/blastinput/rpstblastn_args.cpp @@ -1,4 +1,4 @@ -/* $Id: rpstblastn_args.cpp 448376 2014-10-06 09:52:42Z mcelhany $ +/* $Id: rpstblastn_args.cpp 505234 2016-06-23 13:16:57Z fongah2 $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -31,11 +31,6 @@ * Implementation of the RPSTBLASTN command line arguments */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] - = "$Id: rpstblastn_args.cpp 448376 2014-10-06 09:52:42Z mcelhany $"; -#endif - #include #include #include @@ -49,11 +44,13 @@ USING_SCOPE(objects); CRPSTBlastnAppArgs::CRPSTBlastnAppArgs() { CRef arg; + bool const kFilterByDefault = false; static const string kProgram("rpstblastn"); arg.Reset(new CProgramDescriptionArgs(kProgram, "Translated Reverse Position Specific BLAST")); const bool kQueryIsProtein = false; const bool kIsRpsBlast = true; + const bool kIsCBS2and3Supported = false; m_Args.push_back(arg); m_ClientId = kProgram + " " + CBlastVersion().Print(); @@ -78,7 +75,7 @@ CRPSTBlastnAppArgs::CRPSTBlastnAppArgs() // N.B.: query is not protein because the filtering is applied on the // translated query - arg.Reset(new CFilteringArgs( !kQueryIsProtein )); + arg.Reset(new CFilteringArgs( !kQueryIsProtein, kFilterByDefault)); m_Args.push_back(arg); arg.Reset(new CWindowSizeArg); @@ -106,6 +103,10 @@ CRPSTBlastnAppArgs::CRPSTBlastnAppArgs() m_DebugArgs.Reset(new CDebugArgs); arg.Reset(m_DebugArgs); m_Args.push_back(arg); + + arg.Reset(new CCompositionBasedStatsArgs(kIsCBS2and3Supported, kDfltArgCompBasedStatsRPS )); + m_Args.push_back(arg); + } CRef diff --git a/c++/src/algo/blast/blastinput/tblastn_args.cpp b/c++/src/algo/blast/blastinput/tblastn_args.cpp index a4ec8a08..c1bac5aa 100644 --- a/c++/src/algo/blast/blastinput/tblastn_args.cpp +++ b/c++/src/algo/blast/blastinput/tblastn_args.cpp @@ -1,4 +1,4 @@ -/* $Id: tblastn_args.cpp 448376 2014-10-06 09:52:42Z mcelhany $ +/* $Id: tblastn_args.cpp 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -31,11 +31,6 @@ * Implementation of the TBLASTN command line arguments */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] - = "$Id: tblastn_args.cpp 448376 2014-10-06 09:52:42Z mcelhany $"; -#endif - #include #include #include diff --git a/c++/src/algo/blast/blastinput/tblastx_args.cpp b/c++/src/algo/blast/blastinput/tblastx_args.cpp index a14a9772..8158a539 100644 --- a/c++/src/algo/blast/blastinput/tblastx_args.cpp +++ b/c++/src/algo/blast/blastinput/tblastx_args.cpp @@ -1,4 +1,4 @@ -/* $Id: tblastx_args.cpp 448376 2014-10-06 09:52:42Z mcelhany $ +/* $Id: tblastx_args.cpp 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -31,11 +31,6 @@ * Implementation of the TBLASTX command line arguments */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] - = "$Id: tblastx_args.cpp 448376 2014-10-06 09:52:42Z mcelhany $"; -#endif - #include #include #include diff --git a/c++/src/algo/blast/blastinput/unit_test/Makefile.blastinput_unit_test.app b/c++/src/algo/blast/blastinput/unit_test/Makefile.blastinput_unit_test.app index 7cbc1247..7c223644 100644 --- a/c++/src/algo/blast/blastinput/unit_test/Makefile.blastinput_unit_test.app +++ b/c++/src/algo/blast/blastinput/unit_test/Makefile.blastinput_unit_test.app @@ -1,4 +1,4 @@ -# $Id: Makefile.blastinput_unit_test.app 435839 2014-05-21 13:36:09Z camacho $ +# $Id: Makefile.blastinput_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = blastinput_unit_test SRC = blastinput_unit_test blast_scope_src_unit_test @@ -8,7 +8,7 @@ CPPFLAGS = $(ORIG_CPPFLAGS) $(BOOST_INCLUDE) ENTREZ_LIBS = entrez2cli entrez2 LIB_ = test_boost $(ENTREZ_LIBS) $(BLAST_INPUT_LIBS) \ - ncbi_xloader_blastdb_rmt $(BLAST_LIBS) $(OBJMGR_LIBS) + $(BLAST_LIBS) $(OBJMGR_LIBS) LIB = $(LIB_:%=%$(STATIC)) LIBS = $(NETWORK_LIBS) $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) diff --git a/c++/src/algo/blast/blastinput/unit_test/blast_input_unit_test_aux.hpp b/c++/src/algo/blast/blastinput/unit_test/blast_input_unit_test_aux.hpp index 845c2cac..c3957432 100644 --- a/c++/src/algo/blast/blastinput/unit_test/blast_input_unit_test_aux.hpp +++ b/c++/src/algo/blast/blastinput/unit_test/blast_input_unit_test_aux.hpp @@ -1,4 +1,4 @@ -/* $Id: blast_input_unit_test_aux.hpp 424465 2014-01-16 14:02:06Z camacho $ +/* $Id: blast_input_unit_test_aux.hpp 516396 2016-10-13 12:26:43Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -56,8 +56,13 @@ public: typedef blast::SDataLoaderConfig::EConfigOpts EConfigOpts; - CAutoNcbiConfigFile(EConfigOpts opts = blast::SDataLoaderConfig::eDefault) { - m_Sentry = CMetaRegistry::Load("ncbi", CMetaRegistry::eName_RcOrIni); + CAutoNcbiConfigFile(EConfigOpts opts = blast::SDataLoaderConfig::eDefault) + : m_App(CNcbiApplication::Instance()), m_Registry(0) + { + _ASSERT(m_App); + m_App->ReloadConfig(CMetaRegistry::fAlwaysReload); + m_Registry = &m_App->GetConfig(); + _ASSERT(m_Registry); string value; if (opts & blast::SDataLoaderConfig::eUseBlastDbDataLoader) { @@ -69,33 +74,39 @@ public: if (opts & blast::SDataLoaderConfig::eUseNoDataLoaders) { value += "none"; } - m_Sentry.registry->Set(kSection, kDataLoaders, value); + m_Registry->Set(kSection, kDataLoaders, value); } void SetProteinBlastDbDataLoader(const string& prot_db_name) { - m_Sentry.registry->Set(kSection, kProtBlastDbDataLoader, prot_db_name); + m_Registry->Set(kSection, kProtBlastDbDataLoader, prot_db_name); } void SetNucleotideBlastDbDataLoader(const string& nucl_db_name) { - m_Sentry.registry->Set(kSection, kNuclBlastDbDataLoader, nucl_db_name); + m_Registry->Set(kSection, kNuclBlastDbDataLoader, nucl_db_name); } void RemoveBLASTDBEnvVar() { - m_BlastDb = m_Sentry.registry->Get(kSection, "BLASTDB"); - m_Sentry.registry->Set(kSection, "BLASTDB", "/dev/null"); + m_BlastDb = m_Registry->Get(kSection, "BLASTDB"); + m_Registry->Set(kSection, "BLASTDB", "/dev/null"); } ~CAutoNcbiConfigFile() { - m_Sentry.registry->Set(kSection, kDataLoaders, kEmptyStr); - m_Sentry.registry->Set(kSection, kProtBlastDbDataLoader, kEmptyStr); - m_Sentry.registry->Set(kSection, kNuclBlastDbDataLoader, kEmptyStr); + m_App->ReloadConfig(CMetaRegistry::fAlwaysReload); + m_Registry->Set(kSection, kDataLoaders, kEmptyStr); + m_Registry->Set(kSection, kProtBlastDbDataLoader, kEmptyStr); + m_Registry->Set(kSection, kNuclBlastDbDataLoader, kEmptyStr); if ( !m_BlastDb.empty() ) { - m_Sentry.registry->Set(kSection, "BLASTDB", m_BlastDb); + m_Registry->Set(kSection, "BLASTDB", m_BlastDb); } } + private: - CMetaRegistry::SEntry m_Sentry; + CNcbiApplication* m_App; + CNcbiRegistry* m_Registry; string m_BlastDb; + + CAutoNcbiConfigFile(const CAutoNcbiConfigFile&) = delete; + CAutoNcbiConfigFile& operator=(const CAutoNcbiConfigFile&) = delete; }; /// RAII class for the CBlastScopeSource. It revokes the BLAST database data diff --git a/c++/src/algo/blast/blastinput/unit_test/blast_scope_src_unit_test.cpp b/c++/src/algo/blast/blastinput/unit_test/blast_scope_src_unit_test.cpp index 23c50632..7039430b 100644 --- a/c++/src/algo/blast/blastinput/unit_test/blast_scope_src_unit_test.cpp +++ b/c++/src/algo/blast/blastinput/unit_test/blast_scope_src_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: blast_scope_src_unit_test.cpp 481294 2015-10-08 14:03:49Z grichenk $ +/* $Id: blast_scope_src_unit_test.cpp 516396 2016-10-13 12:26:43Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -393,14 +393,6 @@ BOOST_AUTO_TEST_CASE(ForceRemoteBlastDbLoader) { acf.RemoveBLASTDBEnvVar(); acf.SetProteinBlastDbDataLoader(SDataLoaderConfig::kDefaultProteinBlastDb); - // Make sure to post warnings - CDiagRestorer diag_restorer; - SetDiagPostLevel(eDiag_Info); - - // Redirect the output warnings - CNcbiOstrstream error_stream; - SetDiagStream(&error_stream); - const CSeq_id seqid(CSeq_id::e_Gi, 129295); SDataLoaderConfig dlconfig(true); @@ -415,10 +407,6 @@ BOOST_AUTO_TEST_CASE(ForceRemoteBlastDbLoader) { const TSeqPos kExpectedLength = 232; BOOST_CHECK_EQUAL(kExpectedLength, length); - const string kWarnings = CNcbiOstrstreamToString(error_stream); - const string kExpectedMsg("Error initializing local BLAST database data"); - BOOST_CHECK(kWarnings.find(kExpectedMsg) != NPOS); - string data_loader_name("REMOTE_BLASTDB_"); data_loader_name += string(SDataLoaderConfig::kDefaultProteinBlastDb); data_loader_name += "Protein"; diff --git a/c++/src/algo/blast/blastinput/unit_test/blastinput_unit_test.cpp b/c++/src/algo/blast/blastinput/unit_test/blastinput_unit_test.cpp index 47a08966..f7d01eee 100644 --- a/c++/src/algo/blast/blastinput/unit_test/blastinput_unit_test.cpp +++ b/c++/src/algo/blast/blastinput/unit_test/blastinput_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: blastinput_unit_test.cpp 489949 2016-01-20 12:32:48Z madden $ +/* $Id: blastinput_unit_test.cpp 517499 2016-10-25 17:20:41Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -40,13 +40,16 @@ #include #include #include +#include #include #include #include +#include #include #include #include +#include #include #include @@ -59,6 +62,8 @@ #include #include "blast_input_unit_test_aux.hpp" +#include + #undef NCBI_BOOST_NO_AUTO_TEST_MAIN #include @@ -998,7 +1003,7 @@ BOOST_AUTO_TEST_CASE(ReadSingleAccession_RetrieveLargeSequence) BOOST_REQUIRE(ssl.seqloc->GetInt().IsSetId() == true); BOOST_REQUIRE_EQUAL(CSeq_id::e_Gi, ssl.seqloc->GetInt().GetId().Which()); - BOOST_REQUIRE_EQUAL(GI_FROM(TIntId, kGi), ssl.seqloc->GetInt().GetId().GetGi()); + BOOST_REQUIRE_EQUAL(GI_CONST(kGi), ssl.seqloc->GetInt().GetId().GetGi()); BOOST_REQUIRE(!ssl.mask); @@ -1013,7 +1018,7 @@ BOOST_AUTO_TEST_CASE(ReadSingleAccession_RetrieveLargeSequence) bool found_gi = false, found_accession = false; ITERATE(CBioseq::TId, id, b.GetId()) { if ((*id)->Which() == CSeq_id::e_Gi) { - BOOST_REQUIRE_EQUAL(GI_FROM(TIntId, kGi), (*id)->GetGi()); + BOOST_REQUIRE_EQUAL(GI_CONST(kGi), (*id)->GetGi()); found_gi = true; } else if ((*id)->Which() == CSeq_id::e_Other) { CNcbiOstrstream os; @@ -1249,7 +1254,7 @@ BOOST_AUTO_TEST_CASE(ReadSingleGi) BOOST_REQUIRE(ssl.seqloc->GetInt().IsSetId() == true); BOOST_REQUIRE_EQUAL(CSeq_id::e_Gi, ssl.seqloc->GetInt().GetId().Which()); - const TGi gi = GI_FROM(TIntId, 89161185); + const TGi gi = GI_CONST(89161185); BOOST_REQUIRE_EQUAL(gi, ssl.seqloc->GetInt().GetId().GetGi()); BOOST_REQUIRE(!ssl.mask); @@ -1710,7 +1715,7 @@ BOOST_AUTO_TEST_CASE(ReadGiNuclWithFlankingSpacesIntoBuffer_Single) BOOST_REQUIRE(ssl.seqloc->GetInt().IsSetId() == true); BOOST_REQUIRE( !blast::IsLocalId(ssl.seqloc->GetId()) ); BOOST_REQUIRE_EQUAL(CSeq_id::e_Gi, ssl.seqloc->GetInt().GetId().Which()); - const TGi gi = GI_FROM(TIntId, 1945386); + const TGi gi = GI_CONST(1945386); BOOST_REQUIRE_EQUAL(gi, ssl.seqloc->GetInt().GetId().GetGi()); BOOST_REQUIRE(!ssl.mask); @@ -1721,8 +1726,11 @@ BOOST_AUTO_TEST_CASE(ReadGiNuclWithFlankingSpacesIntoBuffer_Single) BOOST_REQUIRE(bioseqs->GetSeq_set().front()->IsSeq()); const CBioseq& b = bioseqs->GetSeq_set().front()->GetSeq(); BOOST_REQUIRE(b.IsNa()); - BOOST_REQUIRE_EQUAL(CSeq_id::e_Gi, b.GetId().front()->Which()); - BOOST_REQUIRE_EQUAL(gi, b.GetId().front()->GetGi()); + + CRef id = FindBestChoice(b.GetId(), CSeq_id::BestRank); + BOOST_REQUIRE(id.NotNull()); + BOOST_REQUIRE_EQUAL(CSeq_id::e_Gi, id->Which()); + BOOST_REQUIRE_EQUAL(gi, id->GetGi()); BOOST_REQUIRE_EQUAL(CSeq_inst::eRepr_raw, b.GetInst().GetRepr()); BOOST_REQUIRE(CSeq_inst::IsNa(b.GetInst().GetMol())); BOOST_REQUIRE_EQUAL(length, b.GetInst().GetLength()); @@ -1761,7 +1769,7 @@ BOOST_AUTO_TEST_CASE(ReadAccessionNuclWithFlankingSpacesIntoBuffer_Single) BOOST_REQUIRE( !blast::IsLocalId(ssl.seqloc->GetId()) ); BOOST_REQUIRE_EQUAL(CSeq_id::e_Gi, ssl.seqloc->GetInt().GetId().Which()); const string accession("X65215.1"); - BOOST_REQUIRE_EQUAL(GI_FROM(TIntId, 555), ssl.seqloc->GetInt().GetId().GetGi()); + BOOST_REQUIRE_EQUAL(GI_CONST(555), ssl.seqloc->GetInt().GetId().GetGi()); BOOST_REQUIRE(!ssl.mask); @@ -1774,7 +1782,7 @@ BOOST_AUTO_TEST_CASE(ReadAccessionNuclWithFlankingSpacesIntoBuffer_Single) bool found_gi = false, found_accession = false; ITERATE(CBioseq::TId, id, b.GetId()) { if ((*id)->Which() == CSeq_id::e_Gi) { - BOOST_REQUIRE_EQUAL(GI_FROM(TIntId, 555), (*id)->GetGi()); + BOOST_REQUIRE_EQUAL(GI_CONST(555), (*id)->GetGi()); found_gi = true; } else if ((*id)->Which() == CSeq_id::e_Embl) { CNcbiOstrstream os; @@ -1975,7 +1983,7 @@ BOOST_AUTO_TEST_CASE(ParseDefline) CRef source(s_DeclareBlastInput(infile, iconfig)); CScope scope(*CObjectManager::GetInstance()); - const TGi gi = GI_FROM(TIntId, 129295); + const TGi gi = GI_CONST(129295); blast::SSeqLoc ssl = source->GetNextSeqLocBatch(scope).front(); BOOST_REQUIRE_EQUAL(CSeq_id::e_Gi, ssl.seqloc->GetId()->Which()); BOOST_REQUIRE_EQUAL(gi, ssl.seqloc->GetId()->GetGi()); @@ -2222,7 +2230,7 @@ BOOST_AUTO_TEST_CASE(MultiBatch) v = source->GetNextSeqLocBatch(scope); BOOST_REQUIRE_EQUAL((size_t)7, v.size()); BOOST_REQUIRE_EQUAL((TSeqPos)530, v[0].seqloc->GetInt().GetTo()); - gi = GI_FROM(TIntId, 1346057); + gi = GI_CONST(1346057); BOOST_REQUIRE( !blast::IsLocalId(v[0].seqloc->GetId()) ); BOOST_REQUIRE_EQUAL(gi, v[0].seqloc->GetInt().GetId().GetGi()); BOOST_REQUIRE_EQUAL(gi, v[0].seqloc->GetId()->GetGi()); @@ -2230,7 +2238,7 @@ BOOST_AUTO_TEST_CASE(MultiBatch) v = source->GetNextSeqLocBatch(scope); BOOST_REQUIRE_EQUAL((size_t)8, v.size()); BOOST_REQUIRE_EQUAL((TSeqPos)445, v[0].seqloc->GetInt().GetTo()); - gi = GI_FROM(TIntId, 1170625); + gi = GI_CONST(1170625); BOOST_REQUIRE( !blast::IsLocalId(v[0].seqloc->GetId()) ); BOOST_REQUIRE_EQUAL(gi, v[0].seqloc->GetInt().GetId().GetGi()); BOOST_REQUIRE_EQUAL(gi, v[0].seqloc->GetId()->GetGi()); @@ -2238,7 +2246,7 @@ BOOST_AUTO_TEST_CASE(MultiBatch) v = source->GetNextSeqLocBatch(scope); BOOST_REQUIRE_EQUAL((size_t)4, v.size()); BOOST_REQUIRE_EQUAL((TSeqPos)688, v[0].seqloc->GetInt().GetTo()); - gi = GI_FROM(TIntId, 114152); + gi = GI_CONST(114152); BOOST_REQUIRE( !blast::IsLocalId(v[0].seqloc->GetId()) ); BOOST_REQUIRE_EQUAL(gi, v[0].seqloc->GetInt().GetId().GetGi()); BOOST_REQUIRE_EQUAL(gi, v[0].seqloc->GetId()->GetGi()); @@ -2664,8 +2672,300 @@ BOOST_AUTO_TEST_CASE(FetchGiFromAccessionInput) } } + BOOST_AUTO_TEST_SUITE_END() // end of blastinput test suite + +BOOST_AUTO_TEST_SUITE(short_reads) + +static int s_GetSegmentFlags(const CBioseq& bioseq) +{ + int retval = 0; + + BOOST_REQUIRE(bioseq.IsSetDescr()); + for (auto desc : bioseq.GetDescr().Get()) { + if (desc->Which() == CSeqdesc::e_User) { + + if (!desc->GetUser().IsSetType() || + !desc->GetUser().GetType().IsStr() || + desc->GetUser().GetType().GetStr() != "Mapping") { + continue; + } + + BOOST_REQUIRE(desc->GetUser().HasField("has_pair")); + const CUser_field& field = desc->GetUser().GetField("has_pair"); + BOOST_REQUIRE(field.GetData().IsInt()); + + retval = field.GetData().GetInt(); + } + } + + return retval; +} + +BOOST_AUTO_TEST_CASE(TestFlagsForPairedReadsFromFasta) { + + CNcbiIfstream istr("data/paired_reads.fa"); + BOOST_REQUIRE(istr); + unordered_map ref_flags = { + {"lcl|pair1", eFirstSegment}, + {"lcl|pair2", eLastSegment}, + {"lcl|incomplete1.1", fFirstSegmentFlag | fPartialFlag}, + {"lcl|incomplete2.2", fLastSegmentFlag | fPartialFlag} + }; + + CShortReadFastaInputSource input_source(istr, 1000, + CShortReadFastaInputSource::eFasta, + true, true); + + CRef queries(new CBioseq_set); + input_source.GetNextNumSequences(*queries, 0); + // input file contains six sequences, but two should have been rejected + // in screening + BOOST_REQUIRE_EQUAL(queries->GetSeq_set().size(), 4u); + + size_t count = 0; + for (auto it : queries->GetSeq_set()) { + string id = it->GetSeq().GetFirstId()->AsFastaString(); + int flags = s_GetSegmentFlags(it->GetSeq()); + int expected = ref_flags.at(id); + + BOOST_REQUIRE_MESSAGE(flags == expected, (string)"Segment flag for " + + id + " is different from expected " + + NStr::IntToString(flags) + " != " + + NStr::IntToString(expected)); + count++; + } + + BOOST_REQUIRE_EQUAL(ref_flags.size(), count); +} + +BOOST_AUTO_TEST_CASE(TestPairedFlagsForPairedReadsFromTwoFastaFiles) { + + CNcbiIfstream istr1("data/paired_reads_1.fa"); + CNcbiIfstream istr2("data/paired_reads_2.fa"); + BOOST_REQUIRE(istr1); + BOOST_REQUIRE(istr2); + unordered_map ref_flags = { + {"lcl|pair1", eFirstSegment}, + {"lcl|pair2", eLastSegment}, + {"lcl|incomplete1.1", fFirstSegmentFlag | fPartialFlag}, + {"lcl|incomplete2.2", fLastSegmentFlag | fPartialFlag} + }; + + CShortReadFastaInputSource input_source(istr1, istr2, 1000, + CShortReadFastaInputSource::eFasta, + true); + + CRef queries(new CBioseq_set); + input_source.GetNextNumSequences(*queries, 0); + // input file contains six sequences, but two should have been rejected + // in screening + BOOST_REQUIRE_EQUAL(queries->GetSeq_set().size(), 4u); + + size_t count = 0; + for (auto it : queries->GetSeq_set()) { + string id = it->GetSeq().GetFirstId()->AsFastaString(); + int flags = s_GetSegmentFlags(it->GetSeq()); + int expected = ref_flags.at(id); + + BOOST_REQUIRE_MESSAGE(flags == expected, (string)"Segment flag for " + + id + " is different from expected " + + NStr::IntToString(flags) + " != " + + NStr::IntToString(expected)); + count++; + } + + BOOST_REQUIRE_EQUAL(ref_flags.size(), count); +} + +BOOST_AUTO_TEST_CASE(TestPairedFlagsForSingleReadsFromFasta) { + + CNcbiIfstream istr("data/paired_reads.fa"); + CShortReadFastaInputSource input_source(istr, 1000, + CShortReadFastaInputSource::eFasta, + false, true); + + CRef queries(new CBioseq_set); + input_source.GetNextNumSequences(*queries, 0); + // input file contains six sequences, but two should have been rejected + // in screening + BOOST_REQUIRE_EQUAL(queries->GetSeq_set().size(), 4u); + + size_t count = 0; + for (auto it : queries->GetSeq_set()) { + if (it->GetSeq().IsSetDescr()) { + + string id = it->GetSeq().GetFirstId()->AsFastaString(); + int flags = s_GetSegmentFlags(it->GetSeq()); + int expected = 0; + + BOOST_REQUIRE_MESSAGE(flags == expected, + (string)"Segment flag for " + + id + " is different from expected " + + NStr::IntToString(flags) + " != " + + NStr::IntToString(expected)); + } + count++; + } + + BOOST_REQUIRE_EQUAL(4u, count); +} + +BOOST_AUTO_TEST_CASE(TestFlagsForPairedReadsFromFastQ) { + + CNcbiIfstream istr("data/paired_reads.fastq"); + BOOST_REQUIRE(istr); + unordered_map ref_flags = { + {"lcl|pair1", eFirstSegment}, + {"lcl|pair2", eLastSegment}, + {"lcl|incomplete1.1", fFirstSegmentFlag | fPartialFlag}, + {"lcl|incomplete2.2", fLastSegmentFlag | fPartialFlag} + }; + + CShortReadFastaInputSource input_source(istr, 1000, + CShortReadFastaInputSource::eFastq, + true, true); + + CRef queries(new CBioseq_set); + input_source.GetNextNumSequences(*queries, 0); + // input file contains six sequences, but two should have been rejected + // in screening + BOOST_REQUIRE_EQUAL(queries->GetSeq_set().size(), 4u); + + size_t count = 0; + for (auto it : queries->GetSeq_set()) { + string id = it->GetSeq().GetFirstId()->AsFastaString(); + int flags = s_GetSegmentFlags(it->GetSeq()); + int expected = ref_flags.at(id); + + BOOST_REQUIRE_MESSAGE(flags == expected, (string)"Segment flag for " + + id + " is different from expected " + + NStr::IntToString(flags) + " != " + + NStr::IntToString(expected)); + count++; + } + + BOOST_REQUIRE_EQUAL(ref_flags.size(), count); +} + +BOOST_AUTO_TEST_CASE(TestPairedFlagsForPairedReadsFromTwoFastQFiles) { + + CNcbiIfstream istr1("data/paired_reads_1.fastq"); + CNcbiIfstream istr2("data/paired_reads_2.fastq"); + BOOST_REQUIRE(istr1); + BOOST_REQUIRE(istr2); + unordered_map ref_flags = { + {"lcl|pair1", eFirstSegment}, + {"lcl|pair2", eLastSegment}, + {"lcl|incomplete1.1", fFirstSegmentFlag | fPartialFlag}, + {"lcl|incomplete2.2", fLastSegmentFlag | fPartialFlag} + }; + + CShortReadFastaInputSource input_source(istr1, istr2, 1000, + CShortReadFastaInputSource::eFastq, + true); + + CRef queries(new CBioseq_set); + input_source.GetNextNumSequences(*queries, 0); + // input file contains six sequences, but two should have been rejected + // in screening + BOOST_REQUIRE_EQUAL(queries->GetSeq_set().size(), 4u); + + size_t count = 0; + for (auto it : queries->GetSeq_set()) { + string id = it->GetSeq().GetFirstId()->AsFastaString(); + int flags = s_GetSegmentFlags(it->GetSeq()); + int expected = ref_flags.at(id); + + BOOST_REQUIRE_MESSAGE(flags == expected, (string)"Segment flag for " + + id + " is different from expected " + + NStr::IntToString(flags) + " != " + + NStr::IntToString(expected)); + count++; + } + + BOOST_REQUIRE_EQUAL(ref_flags.size(), count); +} + + + + +BOOST_AUTO_TEST_CASE(TestFlagsForPairedReadsFromASN1) { + + CNcbiIfstream istr("data/paired_reads.asn"); + BOOST_REQUIRE(istr); + unordered_map ref_flags = { + {"lcl|pair1", eFirstSegment}, + {"lcl|pair2", eLastSegment}, + {"lcl|incomplete1.1", fFirstSegmentFlag | fPartialFlag}, + {"lcl|incomplete2.2", fLastSegmentFlag | fPartialFlag} + }; + + CASN1InputSourceOMF input_source(istr, 1000, false, true, true); + + CRef queries(new CBioseq_set); + input_source.GetNextNumSequences(*queries, 0); + // input file contains six sequences, but two should have been rejected + // in screening + BOOST_REQUIRE_EQUAL(queries->GetSeq_set().size(), 4u); + + size_t count = 0; + for (auto it : queries->GetSeq_set()) { + string id = it->GetSeq().GetFirstId()->AsFastaString(); + int flags = s_GetSegmentFlags(it->GetSeq()); + int expected = ref_flags.at(id); + + BOOST_REQUIRE_MESSAGE(flags == expected, (string)"Segment flag for " + + id + " is different from expected " + + NStr::IntToString(flags) + " != " + + NStr::IntToString(expected)); + count++; + } + + BOOST_REQUIRE_EQUAL(ref_flags.size(), count); +} + +BOOST_AUTO_TEST_CASE(TestPairedFlagsForPairedReadsFromTwoASN1Files) { + + CNcbiIfstream istr1("data/paired_reads_1.asn"); + CNcbiIfstream istr2("data/paired_reads_2.asn"); + BOOST_REQUIRE(istr1); + BOOST_REQUIRE(istr2); + unordered_map ref_flags = { + {"lcl|pair1", eFirstSegment}, + {"lcl|pair2", eLastSegment}, + {"lcl|incomplete1.1", fFirstSegmentFlag | fPartialFlag}, + {"lcl|incomplete2.2", fLastSegmentFlag | fPartialFlag} + }; + + CASN1InputSourceOMF input_source(istr1, istr2, 1000, false, true); + + CRef queries(new CBioseq_set); + input_source.GetNextNumSequences(*queries, 0); + // input file contains six sequences, but two should have been rejected + // in screening + BOOST_REQUIRE_EQUAL(queries->GetSeq_set().size(), 4u); + + size_t count = 0; + for (auto it : queries->GetSeq_set()) { + string id = it->GetSeq().GetFirstId()->AsFastaString(); + int flags = s_GetSegmentFlags(it->GetSeq()); + int expected = ref_flags.at(id); + + BOOST_REQUIRE_MESSAGE(flags == expected, (string)"Segment flag for " + + id + " is different from expected " + + NStr::IntToString(flags) + " != " + + NStr::IntToString(expected)); + count++; + } + + BOOST_REQUIRE_EQUAL(ref_flags.size(), count); +} + +BOOST_AUTO_TEST_SUITE_END() // end of short_reads test suite + + BOOST_AUTO_TEST_SUITE(blastargs) /// Auxiliary class to convert a string into an argument count and vector diff --git a/c++/src/algo/blast/blastinput/unit_test/data/paired_reads.asn b/c++/src/algo/blast/blastinput/unit_test/data/paired_reads.asn new file mode 100644 index 00000000..e984b26c --- /dev/null +++ b/c++/src/algo/blast/blastinput/unit_test/data/paired_reads.asn @@ -0,0 +1,84 @@ +Seq-entry ::= seq { + id { + local str "pair1" + }, + descr { + title "HWI-ST330:273:C19UAACXX:1:1307:6147:73672" + }, + inst { + repr raw, + mol na, + length 67, + seq-data iupacna "GAATGTCCGTCTGGGTCTCCTTGTGCTGCGGTCCTGGCAACTCGTAGAATTTCTTACCAAAGTATCG" + } +} +Seq-entry ::= seq { + id { + local str "pair2" + }, + descr { + title "HWI-ST330:273:C19UAACXX:1:1307:6147:73672" + }, + inst { + repr raw, + mol na, + length 67, + seq-data iupacna "GAATGTCCGTCTGGGTCTCCTTGTGCTGCGGTCCTGGCAACTCGTAGAATTTCTTACCAAAGTATCG" + } +} +Seq-entry ::= seq { + id { + local str "incomplete1.1" + }, + descr { + title "HWI-ST330:273:C19UAACXX:1:1307:6147:73672" + }, + inst { + repr raw, + mol na, + length 67, + seq-data iupacna "GAATGTCCGTCTGGGTCTCCTTGTGCTGCGGTCCTGGCAACTCGTAGAATTTCTTACCAAAGTATCG" + } +} +Seq-entry ::= seq { + id { + local str "incomplete1.2" + }, + descr { + title "HWI-ST330:273:C19UAACXX:1:1307:6147:73672" + }, + inst { + repr raw, + mol na, + length 66, + seq-data iupacna "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC" + } +} +Seq-entry ::= seq { + id { + local str "incomplete2.1" + }, + descr { + title "HWI-ST330:273:C19UAACXX:1:1307:6147:73672" + }, + inst { + repr raw, + mol na, + length 66, + seq-data iupacna "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC" + } +} +Seq-entry ::= seq { + id { + local str "incomplete2.2" + }, + descr { + title "HWI-ST330:273:C19UAACXX:1:1307:6147:73672" + }, + inst { + repr raw, + mol na, + length 67, + seq-data iupacna "GAATGTCCGTCTGGGTCTCCTTGTGCTGCGGTCCTGGCAACTCGTAGAATTTCTTACCAAAGTATCG" + } +} diff --git a/c++/src/algo/blast/blastinput/unit_test/data/paired_reads.fa b/c++/src/algo/blast/blastinput/unit_test/data/paired_reads.fa new file mode 100644 index 00000000..491555fc --- /dev/null +++ b/c++/src/algo/blast/blastinput/unit_test/data/paired_reads.fa @@ -0,0 +1,12 @@ +>pair1 (both are read) +GAATGTCCGTCTGGGTCTCCTTGTGCTGCGGTCCTGGCAACTCGTAGAATTTCTTACCAAAGTATCGATCCGGGAGATAGTACGATGGATACTCCGCCCTCAGCCTCTCG +>pair2 +ATGTTTTCCGATCCCGCCCAGGAGTCGGTTGCCACGCAGACGGAGGCACAACCGGTTCCGTCGCCCATCTGCACCCCACTGCTGATGGTGGACGAGGATGGACGAAAGCG +>incomplete1.1 (only the first is accepted) +ATGTTTTCCGATCCCGCCCAGGAGTCGGTTGCCACGCAGACGGAGGCACAACCGGTTCCGTCGCCCATCTGCACCCCACTGCTGATGGTGGACGAGGATGGACGAAAGCG +>incomplete1.2 +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +>incomplete2.1 (only the second is accepted) +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +>incomplete2.2 +ATGTTTTCCGATCCCGCCCAGGAGTCGGTTGCCACGCAGACGGAGGCACAACCGGTTCCGTCGCCCATCTGCACCCCACTGCTGATGGTGGACGAGGATGGACGAAAGCG diff --git a/c++/src/algo/blast/blastinput/unit_test/data/paired_reads.fastq b/c++/src/algo/blast/blastinput/unit_test/data/paired_reads.fastq new file mode 100644 index 00000000..74c1c408 --- /dev/null +++ b/c++/src/algo/blast/blastinput/unit_test/data/paired_reads.fastq @@ -0,0 +1,24 @@ +@pair1 (both are read) +GAATGTCCGTCTGGGTCTCCTTGTGCTGCGGTCCTGGCAACTCGTAGAATTTCTTACCAAAGTATCGATCCGGGAGATAGTACGATGGATACTCCGCCCTCAGCCTCTCG ++pair1 +BBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFFFFBFFFFpair1 (both are read) +GAATGTCCGTCTGGGTCTCCTTGTGCTGCGGTCCTGGCAACTCGTAGAATTTCTTACCAAAGTATCGATCCGGGAGATAGTACGATGGATACTCCGCCCTCAGCCTCTCG +>incomplete1.1 (only the first is accepted) +ATGTTTTCCGATCCCGCCCAGGAGTCGGTTGCCACGCAGACGGAGGCACAACCGGTTCCGTCGCCCATCTGCACCCCACTGCTGATGGTGGACGAGGATGGACGAAAGCG +>incomplete2.1 (only the second is accepted) +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC diff --git a/c++/src/algo/blast/blastinput/unit_test/data/paired_reads_1.fastq b/c++/src/algo/blast/blastinput/unit_test/data/paired_reads_1.fastq new file mode 100644 index 00000000..c5167511 --- /dev/null +++ b/c++/src/algo/blast/blastinput/unit_test/data/paired_reads_1.fastq @@ -0,0 +1,12 @@ +@pair1 (both are read) +GAATGTCCGTCTGGGTCTCCTTGTGCTGCGGTCCTGGCAACTCGTAGAATTTCTTACCAAAGTATCGATCCGGGAGATAGTACGATGGATACTCCGCCCTCAGCCTCTCG ++pair1 +BBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFFFFBFFFFpair2 +ATGTTTTCCGATCCCGCCCAGGAGTCGGTTGCCACGCAGACGGAGGCACAACCGGTTCCGTCGCCCATCTGCACCCCACTGCTGATGGTGGACGAGGATGGACGAAAGCG +>incomplete1.2 +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +>incomplete2.2 +ATGTTTTCCGATCCCGCCCAGGAGTCGGTTGCCACGCAGACGGAGGCACAACCGGTTCCGTCGCCCATCTGCACCCCACTGCTGATGGTGGACGAGGATGGACGAAAGCG diff --git a/c++/src/algo/blast/blastinput/unit_test/data/paired_reads_2.fastq b/c++/src/algo/blast/blastinput/unit_test/data/paired_reads_2.fastq new file mode 100644 index 00000000..09c728e9 --- /dev/null +++ b/c++/src/algo/blast/blastinput/unit_test/data/paired_reads_2.fastq @@ -0,0 +1,12 @@ +@pair2 +ATGTTTTCCGATCCCGCCCAGGAGTCGGTTGCCACGCAGACGGAGGCACAACCGGTTCCGTCGCCCATCTGCACCCCACTGCTGATGGTGGACGAGGATGGACGAAAGCG ++pair2 +BBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFFFFBFFFF #include #include diff --git a/c++/src/algo/blast/composition_adjustment/compo_mode_condition.c b/c++/src/algo/blast/composition_adjustment/compo_mode_condition.c index 9bc0cbb5..07c2631a 100644 --- a/c++/src/algo/blast/composition_adjustment/compo_mode_condition.c +++ b/c++/src/algo/blast/composition_adjustment/compo_mode_condition.c @@ -30,11 +30,6 @@ * Authors: Alejandro Schaffer, Yi-Kuo Yu */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: compo_mode_condition.c 112888 2007-10-25 15:34:02Z camacho $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include diff --git a/c++/src/algo/blast/composition_adjustment/composition_adjustment.c b/c++/src/algo/blast/composition_adjustment/composition_adjustment.c index 83ec1cd2..26e9fe55 100644 --- a/c++/src/algo/blast/composition_adjustment/composition_adjustment.c +++ b/c++/src/algo/blast/composition_adjustment/composition_adjustment.c @@ -28,10 +28,6 @@ * * @author Yi-Kuo Yu, Alejandro Schaffer, E. Michael Gertz */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: composition_adjustment.c 500367 2016-05-04 12:06:01Z ivanov $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ #include #include @@ -1177,11 +1173,23 @@ Blast_ReadAaComposition(Blast_AminoAcidComposition * composition, prob[i] = 0.0; } for (i = 0; i < length; i++) { - if (alphaConvert[sequence[i]] >= 0) { + if (alphaConvert[sequence[i]] >= 0 || sequence[i] == eSelenocysteine) { prob[sequence[i]]++; numTrueAminoAcids++; } } + + /* Count Selenocysteine (U) as if it was Cysteine (C) to avoid a result + where C aligned to U is scored higher than C aligned to C. Otherwise, + because U is not counted as a true amino acid, sequences with U would + appear more complex than those composed only of the 20 "true" amino + acids. Therefore computationally adjusted alignment score would be + larger for sequences containing U than for sequences with C. */ + if (prob[eSelenocysteine] > 0.0) { + prob[eCchar] += prob[eSelenocysteine]; + prob[eSelenocysteine] = 0.0; + } + composition->numTrueAminoAcids = numTrueAminoAcids; if (numTrueAminoAcids > 0) { for (i = 0; i < alphsize; i++) { diff --git a/c++/src/algo/blast/composition_adjustment/matrix_frequency_data.c b/c++/src/algo/blast/composition_adjustment/matrix_frequency_data.c index 9ed0e7d1..4b179005 100644 --- a/c++/src/algo/blast/composition_adjustment/matrix_frequency_data.c +++ b/c++/src/algo/blast/composition_adjustment/matrix_frequency_data.c @@ -27,10 +27,6 @@ * * @author Yi-Kuo Yu, Alejandro Schaffer, E. Michael Gertz */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: matrix_frequency_data.c 439568 2014-07-01 16:13:36Z madden $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ #include #include diff --git a/c++/src/algo/blast/composition_adjustment/nlm_linear_algebra.c b/c++/src/algo/blast/composition_adjustment/nlm_linear_algebra.c index c1928846..f6091384 100644 --- a/c++/src/algo/blast/composition_adjustment/nlm_linear_algebra.c +++ b/c++/src/algo/blast/composition_adjustment/nlm_linear_algebra.c @@ -27,10 +27,6 @@ * * @author E. Michael Gertz */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: nlm_linear_algebra.c 138123 2008-08-21 19:28:07Z camacho $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ #include #include diff --git a/c++/src/algo/blast/composition_adjustment/optimize_target_freq.c b/c++/src/algo/blast/composition_adjustment/optimize_target_freq.c index 3b28b13c..e271ecb4 100644 --- a/c++/src/algo/blast/composition_adjustment/optimize_target_freq.c +++ b/c++/src/algo/blast/composition_adjustment/optimize_target_freq.c @@ -82,10 +82,6 @@ * * @author E. Michael Gertz */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: optimize_target_freq.c 74455 2005-12-19 15:38:01Z gertz $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ #include #include diff --git a/c++/src/algo/blast/composition_adjustment/redo_alignment.c b/c++/src/algo/blast/composition_adjustment/redo_alignment.c index 93e914b9..4d09c344 100644 --- a/c++/src/algo/blast/composition_adjustment/redo_alignment.c +++ b/c++/src/algo/blast/composition_adjustment/redo_alignment.c @@ -29,10 +29,6 @@ * * @author Alejandro Schaffer, E. Michael Gertz */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: redo_alignment.c 496008 2016-03-23 11:29:15Z ivanov $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ #include #include @@ -139,7 +135,6 @@ BlastCompo_AlignmentsFree(BlastCompo_Alignment ** palign, /* Save the value of align->next, because align is to be deleted. */ BlastCompo_Alignment * align_next = align->next; - align_next = align->next; if (free_context != NULL && align->context != NULL) { free_context(align->context); } @@ -626,6 +621,17 @@ s_SubjectCompareWindows(const void * vp1, const void *vp2) return result; } +static +int s_GetTranslatedLength(int length,int frame, int is_pos_based) { + if(is_pos_based) { + int f = GET_SEQ_FRAME(frame); + int nucl_length = GET_NUCL_LENGTH(length); + return GET_TRANSLATED_LENGTH(nucl_length, f); + } + + return ((length - ABS(frame) + 1)/3); +} + /** * Read a list of alignments from a translated search and create a * new array of pointers to s_WindowInfo so that each alignment is @@ -639,7 +645,7 @@ s_WindowsFromTranslatedAligns(BlastCompo_Alignment * alignments, BlastCompo_QueryInfo * query_info, int hspcnt, int border, int sequence_length, s_WindowInfo ***pwindows, int * nWindows, - int subject_is_translated) + int subject_is_translated, int is_pos_based) { int k; /* iteration index */ s_WindowInfo ** windows; /* the output list of windows */ @@ -649,10 +655,10 @@ s_WindowsFromTranslatedAligns(BlastCompo_Alignment * alignments, alignment in the main loop */ *nWindows = 0; windows = *pwindows = calloc(hspcnt, sizeof(s_WindowInfo*)); - *nWindows = hspcnt; if (windows == NULL) goto error_return; + *nWindows = hspcnt; for (align = alignments, k = 0; align != NULL; align = align->next, k++) { @@ -669,7 +675,7 @@ s_WindowsFromTranslatedAligns(BlastCompo_Alignment * alignments, frame = align->frame; query_index = align->queryIndex; query_length = query_info[query_index].seq.length; - translated_length = (sequence_length - ABS(frame) + 1)/3; + translated_length = s_GetTranslatedLength(sequence_length, frame, is_pos_based); align_copy = s_AlignmentCopy(align); if (align_copy == NULL) @@ -744,11 +750,14 @@ s_WindowsFromTranslatedAligns(BlastCompo_Alignment * alignments, return 0; /* normal return */ error_return: - for (k = 0; k < *nWindows; k++) { - if (windows[k] != NULL) - s_WindowInfoFree(&windows[k]); + if (windows) + { + for (k = 0; k < *nWindows; k++) { + if (windows[k] != NULL) + s_WindowInfoFree(&windows[k]); + } + free(windows); } - free(windows); *pwindows = NULL; return -1; } @@ -812,8 +821,10 @@ s_WindowsFromProteinAligns(BlastCompo_Alignment * alignments, } /* shrink to fit */ { - s_WindowInfo ** new_windows = - realloc(windows, window_index * sizeof(s_WindowInfo*)); + s_WindowInfo ** new_windows = NULL; + if (window_index > 0) + new_windows = realloc(windows, window_index * sizeof(s_WindowInfo*)); + if (new_windows == NULL) { goto error_return; } else { @@ -863,19 +874,19 @@ s_WindowsFromAligns(BlastCompo_Alignment * alignments, BlastCompo_QueryInfo * query_info, int hspcnt, int numQueries, int border, int sequence_length, s_WindowInfo ***pwindows, int * nWindows, - int query_is_translated, int subject_is_translated) + int query_is_translated, int subject_is_translated, int is_pos_based) { if (subject_is_translated || query_is_translated) { return s_WindowsFromTranslatedAligns(alignments, query_info, hspcnt, border, sequence_length, pwindows, nWindows, - subject_is_translated); + subject_is_translated, is_pos_based); } else { return s_WindowsFromProteinAligns(alignments, query_info, numQueries, sequence_length, pwindows, nWindows); - } + } } @@ -909,7 +920,6 @@ s_GetComposition(Blast_AminoAcidComposition * composition, data = seq->data; length = range->end - range->begin; - if (query_is_translated || subject_is_translated) { int start; int end; @@ -1125,7 +1135,7 @@ Blast_RedoOneMatch(BlastCompo_Alignment ** alignments, status = s_WindowsFromAligns(incoming_aligns, query_info, hspcnt, numQueries, kWindowBorder, matchingSeq->length, &windows, - &nWindows, query_is_translated, subject_is_translated); + &nWindows, query_is_translated, subject_is_translated, params->positionBased); if (status != 0) { goto function_level_cleanup; } @@ -1246,8 +1256,6 @@ Blast_RedoOneMatch(BlastCompo_Alignment ** alignments, num_adjustments++; } - // By this point there's a discrepancy in - // gapping_params->context->gap_align->sbp->matrix->data if ( !adjust_search_failed ) { newAlign = callbacks->redo_one_alignment( in_align, @@ -1346,7 +1354,7 @@ Blast_RedoOneMatchSmithWaterman(BlastCompo_Alignment ** alignments, status = s_WindowsFromAligns(incoming_aligns, query_info, hspcnt, numQueries, kWindowBorder, matchingSeq->length, &windows, - &nWindows, query_is_translated, subject_is_translated); + &nWindows, query_is_translated, subject_is_translated, params->positionBased); if (status != 0) goto function_level_cleanup; /* We are performing a Smith-Waterman alignment */ diff --git a/c++/src/algo/blast/composition_adjustment/smith_waterman.c b/c++/src/algo/blast/composition_adjustment/smith_waterman.c index 644c43cc..17af7515 100644 --- a/c++/src/algo/blast/composition_adjustment/smith_waterman.c +++ b/c++/src/algo/blast/composition_adjustment/smith_waterman.c @@ -28,10 +28,6 @@ * * @author Alejandro Schaffer, E. Michael Gertz */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: smith_waterman.c 85238 2006-06-29 16:50:24Z gertz $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ #include #include diff --git a/c++/src/algo/blast/composition_adjustment/unified_pvalues.c b/c++/src/algo/blast/composition_adjustment/unified_pvalues.c index 2b63025b..0f7c530d 100644 --- a/c++/src/algo/blast/composition_adjustment/unified_pvalues.c +++ b/c++/src/algo/blast/composition_adjustment/unified_pvalues.c @@ -29,10 +29,6 @@ * * @author Yi-Kuo Yu, Alejandro Schaffer, Mike Gertz */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: unified_pvalues.c 86217 2006-07-17 17:18:48Z gertz $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ #include #include diff --git a/c++/src/algo/blast/core/Makefile.blast.lib b/c++/src/algo/blast/core/Makefile.blast.lib index 574ebb90..8a8a1271 100644 --- a/c++/src/algo/blast/core/Makefile.blast.lib +++ b/c++/src/algo/blast/core/Makefile.blast.lib @@ -1,4 +1,4 @@ -# $Id: Makefile.blast.lib 498856 2016-04-20 11:37:59Z ivanov $ +# $Id: Makefile.blast.lib 504861 2016-06-20 15:45:40Z boratyng $ SRC_C = aa_ungapped blast_diagnostics blast_engine blast_extend \ blast_filter blast_gapalign blast_hits blast_hspstream blast_itree \ @@ -11,8 +11,9 @@ SRC_C = aa_ungapped blast_diagnostics blast_engine blast_extend \ ncbi_std ncbi_math blast_encoding pattern phi_extend phi_gapalign \ phi_lookup blast_parameters blast_posit blast_program blast_query_info \ blast_tune blast_sw blast_dynarray split_query gencode_singleton \ - index_ungapped blast_traceback_mt_priv blast_hspstream_mt_utils boost_erf - + index_ungapped blast_traceback_mt_priv blast_hspstream_mt_utils boost_erf \ + jumper hspfilter_mapper + SRC = $(SRC_C) LIB = blast @@ -20,7 +21,6 @@ LIB = blast #CFLAGS = $(FAST_CFLAGS) -pedantic -std=c99 -Wall -W -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wundef -Winline -Wno-parentheses CFLAGS = $(FAST_CFLAGS) LDFLAGS = $(FAST_LDFLAGS) - WATCHERS = madden camacho fongah2 diff --git a/c++/src/algo/blast/core/aa_ungapped.c b/c++/src/algo/blast/core/aa_ungapped.c index a98f976b..f650aee5 100644 --- a/c++/src/algo/blast/core/aa_ungapped.c +++ b/c++/src/algo/blast/core/aa_ungapped.c @@ -1,4 +1,4 @@ -/* $Id: aa_ungapped.c 419638 2013-11-27 14:48:24Z boratyng $ +/* $Id: aa_ungapped.c 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -28,11 +28,6 @@ * Functions to iterate over seed hits and perform ungapped extensions. */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: aa_ungapped.c 419638 2013-11-27 14:48:24Z boratyng $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include diff --git a/c++/src/algo/blast/core/blast_aalookup.c b/c++/src/algo/blast/core/blast_aalookup.c index 8961a75a..151c628f 100644 --- a/c++/src/algo/blast/core/blast_aalookup.c +++ b/c++/src/algo/blast/core/blast_aalookup.c @@ -1,4 +1,4 @@ -/* $Id: blast_aalookup.c 464154 2015-04-06 16:36:18Z madden $ +/* $Id: blast_aalookup.c 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -32,11 +32,6 @@ #include #include -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_aalookup.c 464154 2015-04-06 16:36:18Z madden $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - /** Structure containing information needed for adding neighboring words. */ typedef struct NeighborInfo { diff --git a/c++/src/algo/blast/core/blast_aascan.c b/c++/src/algo/blast/core/blast_aascan.c index 7a6d4f85..158bd733 100644 --- a/c++/src/algo/blast/core/blast_aascan.c +++ b/c++/src/algo/blast/core/blast_aascan.c @@ -1,4 +1,4 @@ -/* $Id: blast_aascan.c 197897 2010-07-23 14:34:13Z maning $ +/* $Id: blast_aascan.c 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -32,11 +32,6 @@ #include #include "masksubj.inl" -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_aascan.c 197897 2010-07-23 14:34:13Z maning $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - /** * Scans the subject sequence from "offset" to the end of the sequence. * Copies at most array_size hits. diff --git a/c++/src/algo/blast/core/blast_diagnostics.c b/c++/src/algo/blast/core/blast_diagnostics.c index 413c2acf..c1238d5b 100644 --- a/c++/src/algo/blast/core/blast_diagnostics.c +++ b/c++/src/algo/blast/core/blast_diagnostics.c @@ -1,4 +1,4 @@ -/* $Id: blast_diagnostics.c 303807 2011-06-13 18:22:23Z camacho $ +/* $Id: blast_diagnostics.c 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -32,11 +32,6 @@ */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_diagnostics.c 303807 2011-06-13 18:22:23Z camacho $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include diff --git a/c++/src/algo/blast/core/blast_dynarray.c b/c++/src/algo/blast/core/blast_dynarray.c index f431d4d1..faf1f501 100644 --- a/c++/src/algo/blast/core/blast_dynarray.c +++ b/c++/src/algo/blast/core/blast_dynarray.c @@ -1,4 +1,4 @@ -/* $Id: blast_dynarray.c 113776 2007-11-08 22:38:18Z camacho $ +/* $Id: blast_dynarray.c 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -32,11 +32,6 @@ */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_dynarray.c 113776 2007-11-08 22:38:18Z camacho $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include "blast_dynarray.h" #include #include /* for error codes */ diff --git a/c++/src/algo/blast/core/blast_encoding.c b/c++/src/algo/blast/core/blast_encoding.c index ddd83cc1..887b6760 100644 --- a/c++/src/algo/blast/core/blast_encoding.c +++ b/c++/src/algo/blast/core/blast_encoding.c @@ -1,4 +1,4 @@ -/* $Id: blast_encoding.c 118195 2008-01-24 21:22:19Z camacho $ +/* $Id: blast_encoding.c 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -32,11 +32,6 @@ * @sa blast_encoding.h */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_encoding.c 118195 2008-01-24 21:22:19Z camacho $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include const Uint1 NCBI4NA_TO_BLASTNA[BLASTNA_SIZE] = { diff --git a/c++/src/algo/blast/core/blast_engine.c b/c++/src/algo/blast/core/blast_engine.c index a3f01536..1b66173b 100644 --- a/c++/src/algo/blast/core/blast_engine.c +++ b/c++/src/algo/blast/core/blast_engine.c @@ -1,4 +1,4 @@ -/* $Id: blast_engine.c 500531 2016-05-05 14:28:38Z ivanov $ +/* $Id: blast_engine.c 521263 2016-12-07 15:18:43Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -32,20 +32,20 @@ *
  * Preliminary stage of the BLAST search:
  *
- *    Blast_RunPreliminarySearch 
+ *    Blast_RunPreliminarySearch
  *        BLAST_GapAlignSetUp
  *        BLAST_PreliminarySearchEngine
  *            if (RPS BLAST) {
  *                s_RPSPreliminarySearchEngine
  *                    s_BlastSearchEngineCore
  *            } else {
- *                for (all sequences in the database) 
+ *                for (all sequences in the database)
  *                    s_BlastSearchEngineCore
  *            }
- * 
+ *
  * Full BLAST search, including preliminary search and traceback:
  *
- *    Blast_RunFullSearch 
+ *    Blast_RunFullSearch
  *        BLAST_GapAlignSetUp
  *        BLAST_PreliminarySearchEngine
  *        BLAST_ComputeTraceback
@@ -53,11 +53,6 @@
  * 
*/ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_engine.c 500531 2016-05-05 14:28:38Z ivanov $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include @@ -83,11 +78,11 @@ static char const rcsid[] = #define CONV_NUCL2PROT_COORDINATES(length) (length) / CODON_LENGTH NCBI_XBLAST_EXPORT const int kBlastMajorVersion = 2; -NCBI_XBLAST_EXPORT const int kBlastMinorVersion = 4; +NCBI_XBLAST_EXPORT const int kBlastMinorVersion = 6; NCBI_XBLAST_EXPORT const int kBlastPatchVersion = 0; -NCBI_XBLAST_EXPORT const char* kBlastReleaseDate = "June-01-2016"; +NCBI_XBLAST_EXPORT const char* kBlastReleaseDate = "January-09-2017"; -/** Structure to be passed to s_BlastSearchEngineCore, containing pointers +/** Structure to be passed to s_BlastSearchEngineCore, containing pointers to various preallocated structures and arrays. */ typedef struct BlastCoreAuxStruct { @@ -96,24 +91,30 @@ typedef struct BlastCoreAuxStruct { BlastWordFinderType WordFinder; /**< Word finder function pointer */ BlastGetGappedScoreType GetGappedScore; /**< Gapped extension function pointer */ - BlastInitHitList* init_hitlist; /**< Placeholder for HSPs after + JumperGappedType JumperGapped; /**< Word finder and gapped extension + for mapping short reads */ + + BlastInitHitList* init_hitlist; /**< Placeholder for HSPs after ungapped extension */ BlastOffsetPair* offset_pairs; /**< Array of offset pairs for initial seeds. */ + MapperWordHits* mapper_wordhits; + Uint1* translation_buffer; /**< Placeholder for translated subject sequences */ Uint1* translation_table; /**< Translation table for forward strand */ - Uint1* translation_table_rc; /**< Translation table for reverse + Uint1* translation_table_rc; /**< Translation table for reverse strand */ } BlastCoreAuxStruct; /** Deallocates all memory in BlastCoreAuxStruct */ -static BlastCoreAuxStruct* +static BlastCoreAuxStruct* s_BlastCoreAuxStructFree(BlastCoreAuxStruct* aux_struct) { BlastExtendWordFree(aux_struct->ewp); BLAST_InitHitListFree(aux_struct->init_hitlist); sfree(aux_struct->offset_pairs); - + MapperWordHitsFree(aux_struct->mapper_wordhits); + sfree(aux_struct); return NULL; } @@ -172,11 +173,11 @@ static void s_BackupSubject(BLAST_SequenceBlk* subject, ASSERT (backup->num_seq_ranges >= 1); backup->hard_ranges = backup->seq_ranges; backup->num_hard_ranges = backup->num_seq_ranges; - } + } backup->offset = backup->hard_ranges[0].left; backup->next = backup->offset; - subject->chunk = -1; + subject->chunk = -1; } @@ -219,9 +220,18 @@ const Int2 SUBJECT_SPLIT_NO_RANGE = 2; /**< return value indicating all masked static Int2 s_GetNextSubjectChunk(BLAST_SequenceBlk* subject, SubjectSplitStruct *backup, - Boolean is_nucleotide) + Boolean is_nucleotide, + int chunk_overlap) { int start, len, i, residual; + int dbseq_chunk_overlap; + + if (chunk_overlap > 0) { + dbseq_chunk_overlap = chunk_overlap; + } + else { + dbseq_chunk_overlap = DBSEQ_CHUNK_OVERLAP; + } ASSERT(subject); ASSERT(backup); @@ -233,15 +243,15 @@ static Int2 s_GetNextSubjectChunk(BLAST_SequenceBlk* subject, subject->sequence = backup->sequence + ((is_nucleotide) ? backup->offset /COMPRESSION_RATIO : backup->offset); - if (backup->offset + MAX_DBSEQ_LEN < + if (backup->offset + MAX_DBSEQ_LEN < backup->hard_ranges[backup->hm_index].right) { subject->length = MAX_DBSEQ_LEN; - backup->next = backup->offset + MAX_DBSEQ_LEN - DBSEQ_CHUNK_OVERLAP; + backup->next = backup->offset + MAX_DBSEQ_LEN - dbseq_chunk_overlap; } else { - subject->length = backup->hard_ranges[backup->hm_index].right + subject->length = backup->hard_ranges[backup->hm_index].right - backup->offset; backup->hm_index++; backup->next = (backup->hm_index < backup->num_hard_ranges) ? @@ -265,7 +275,7 @@ static Int2 s_GetNextSubjectChunk(BLAST_SequenceBlk* subject, subject->seq_ranges[0].right = subject->length; return SUBJECT_SPLIT_OK; } - + /* soft masking is on, sequence is chunked, must re-allocate and adjust */ ASSERT (residual == 0); start = backup->offset; @@ -292,7 +302,7 @@ static Int2 s_GetNextSubjectChunk(BLAST_SequenceBlk* subject, subject->seq_ranges[i].right = backup->soft_ranges[i+start].right - backup->offset; } - if (subject->seq_ranges[0].left < 0) + if (subject->seq_ranges[0].left < 0) subject->seq_ranges[0].left = 0; if (subject->seq_ranges[len-1].right > subject->length) subject->seq_ranges[len-1].right = subject->length; @@ -310,11 +320,11 @@ static Int2 s_GetNextSubjectChunk(BLAST_SequenceBlk* subject, * tblastn only [in] * @param offset Shift in the subject sequence protein coordinates [in] */ -static void -s_TranslateHSPsToDNAPCoord(EBlastProgramType program, - BlastInitHitList* init_hitlist, +static void +s_TranslateHSPsToDNAPCoord(EBlastProgramType program, + BlastInitHitList* init_hitlist, const BlastQueryInfo* query_info, - Int2 subject_frame, Int4 subject_length, + Int2 subject_frame, Int4 subject_length, Int4 offset) { BlastInitHSP * init_hsp = 0; @@ -323,28 +333,28 @@ s_TranslateHSPsToDNAPCoord(EBlastProgramType program, for(index = 0; index < init_hitlist->total; ++index) { BlastContextInfo * contexts = query_info->contexts; init_hsp = &init_hitlist->init_hsp_array[index]; - + if (program == eBlastTypeBlastx) { Int4 context_idx = 0; /* Index of this HSP's context */ Int4 frame_idx = 0; /* Index of this frame within set of frames with same query and sign */ Int4 init_frame_idx = 0; /* First frame of this query */ Int4 frame_pos = 0; /* Start of this frame in DNA */ - + /* Find context containing this HSP */ - context_idx = - BSearchContextInfo(init_hsp->offsets.qs_offsets.q_off, + context_idx = + BSearchContextInfo(init_hsp->offsets.qs_offsets.q_off, query_info); - + frame_idx = context_idx % CODON_LENGTH; init_frame_idx = context_idx - frame_idx; - + frame_pos = contexts[init_frame_idx].query_offset + frame_idx; - + init_hsp->offsets.qs_offsets.q_off = (init_hsp->offsets.qs_offsets.q_off - contexts[context_idx].query_offset) * CODON_LENGTH + frame_pos; - + init_hsp->ungapped_data->q_start = (init_hsp->ungapped_data->q_start - contexts[context_idx].query_offset) * CODON_LENGTH + frame_pos; @@ -352,18 +362,18 @@ s_TranslateHSPsToDNAPCoord(EBlastProgramType program, init_hsp->offsets.qs_offsets.s_off += offset; init_hsp->ungapped_data->s_start += offset; if (subject_frame > 0) { - init_hsp->offsets.qs_offsets.s_off = - (init_hsp->offsets.qs_offsets.s_off * CODON_LENGTH) + + init_hsp->offsets.qs_offsets.s_off = + (init_hsp->offsets.qs_offsets.s_off * CODON_LENGTH) + subject_frame - 1; - init_hsp->ungapped_data->s_start = - (init_hsp->ungapped_data->s_start * CODON_LENGTH) + + init_hsp->ungapped_data->s_start = + (init_hsp->ungapped_data->s_start * CODON_LENGTH) + subject_frame - 1; } else { - init_hsp->offsets.qs_offsets.s_off = - (init_hsp->offsets.qs_offsets.s_off * CODON_LENGTH) + + init_hsp->offsets.qs_offsets.s_off = + (init_hsp->offsets.qs_offsets.s_off * CODON_LENGTH) + subject_length - subject_frame; - init_hsp->ungapped_data->s_start = - (init_hsp->ungapped_data->s_start * CODON_LENGTH) + + init_hsp->ungapped_data->s_start = + (init_hsp->ungapped_data->s_start * CODON_LENGTH) + subject_length - subject_frame; } } @@ -372,7 +382,7 @@ s_TranslateHSPsToDNAPCoord(EBlastProgramType program, } /** Set up context offsets for the auxiliary BlastQueryInfo structure that is - * created for the concatenated database in RPS BLAST search. Calls the public + * created for the concatenated database in RPS BLAST search. Calls the public * function OffsetArrayToContextOffsets with a blastp program, because subjects * are protein sequences. This guarantees that all frames are set to 0. * @param info The preallocated structure [in] [out] @@ -386,6 +396,133 @@ s_RPSOffsetArrayToContextOffsets(BlastQueryInfo * info, OffsetArrayToContextOffsets(info, new_offsets, kProgram); } +static int +s_CompareHSPsBySubjectEnd(const void* a, const void* b) +{ + BlastHSP* h1, * h2; + BlastHSP** hp1, ** hp2; + + hp1 = (BlastHSP**)a; + hp2 = (BlastHSP**)b; + h1 = *hp1; + h2 = *hp2; + + if (!h1 && !h2) { + return 0; + } + else if (!h1) { + return -1; + } + else if (!h2) { + return 1; + } + + if (h1->subject.end < h2->subject.end) { + return -1; + } + else if (h1->subject.end > h2->subject.end) { + return 1; + } + + return 0; +} + +/* Write HSPs for a single subject chunk to HSP stream, implemented for mapper. + A single read may align to several exons that fall in two subject chunks. + This is a problem because combining HSPs into exon chains is done for each + HSP list write independently. + Given the maximum intron length we can write HSPs with positions on the + subject too far from subject chunk end to be combined with HSPs aligned to + the next subject chunk. */ +static Int2 +s_WriteHSPsForChunk(BlastHSPList* hsp_list, + const SubjectSplitStruct* backup, + const BlastHitSavingParameters* hit_params, + BlastHSPStream* hsp_stream, + Int4 chunk_length, + Int4 full_subject_length) +{ + BlastHSP** hsp_array = NULL; + BlastHSP** new_hsp_array = NULL; + BlastHSPList* hsp_list_to_write = NULL; + Int4 max_intron_len; + Int4 new_allocated; + Int4 last_pos_to_move; + Int4 status; + Int4 i, n = 0; + + if (!hsp_list || !backup || !hit_params || !hsp_stream) { + return -1; + } + + if (backup->next >= full_subject_length) { + /* HSPs for the last subject chunk will be written to HSP stream at + the end of subject processing */ + + return 0; + } + + max_intron_len = hit_params->options->longest_intron; + + /* HSPs up to this subject offset will be removed from hsp_list and + written to HSP stream */ + /* FIXME: shoule this be until 1 * max_intron_length? */ + last_pos_to_move = backup->offset + chunk_length - max_intron_len - 1; + + hsp_array = hsp_list->hsp_array; + + /* sort HSPs by subject offset */ + qsort(hsp_array, hsp_list->hspcnt, sizeof(BlastHSP*), + s_CompareHSPsBySubjectEnd); + + /* separate HSPs with subject offset smaller than last chunk position - + max intron length */ + i = 0; + while (i < hsp_list->hspcnt && + hsp_array[i]->subject.end < last_pos_to_move) { + i++; + } + + /* copy HSPs with sbubject positions between max intron lengths and + chunk end */ + new_allocated = hsp_list->hspcnt - i + 1; + new_hsp_array = calloc(new_allocated, sizeof(BlastHSP*)); + if (!new_hsp_array) { + return -1; + } + for (;i < hsp_list->hspcnt;i++) { + new_hsp_array[n++] = Blast_HSPClone(hsp_array[i]); + } + ASSERT(i == hsp_list->hspcnt); + + hsp_list_to_write = Blast_HSPListNew(1); + if (!hsp_list_to_write) { + return -1; + } + + if (hsp_list_to_write->hsp_array) { + sfree(hsp_list_to_write->hsp_array); + } + + hsp_list_to_write->hsp_array = hsp_array; + hsp_list_to_write->hspcnt = hsp_list->hspcnt /*hspcnt_to_write*/; + hsp_list_to_write->allocated = hsp_list->allocated; + hsp_list_to_write->oid = hsp_list->oid; + + hsp_list->hsp_array = new_hsp_array; + hsp_list->hspcnt = n; + hsp_list->allocated = new_allocated; + + /* write hsp_list_to_write */ + status = BlastHSPStreamWrite(hsp_stream, &hsp_list_to_write); + if (hsp_list_to_write) { + hsp_list_to_write = Blast_HSPListFree(hsp_list_to_write); + } + + return status; +} + + /** Searches only one context of a database sequence, but does all chunks if it is split. * @param program_number BLAST program type [in] * @param query Query sequence structure [in] @@ -395,7 +532,7 @@ s_RPSOffsetArrayToContextOffsets(BlastQueryInfo * info, * @param lookup Lookup table [in] * @param gap_align Structure for gapped alignment information [in] * @param score_params Scoring parameters [in] - * @param word_params Initial word finding and ungapped extension + * @param word_params Initial word finding and ungapped extension * parameters [in] * @param ext_params Gapped extension parameters [in] * @param hit_params Hit saving parameters [in] @@ -410,18 +547,19 @@ s_RPSOffsetArrayToContextOffsets(BlastQueryInfo * info, */ static Int2 -s_BlastSearchEngineOneContext(EBlastProgramType program_number, - BLAST_SequenceBlk* query, BlastQueryInfo* query_info, - BLAST_SequenceBlk* subject, Int4 orig_length, LookupTableWrap* lookup, - BlastGapAlignStruct* gap_align, - const BlastScoringParameters* score_params, - const BlastInitialWordParameters* word_params, - const BlastExtensionParameters* ext_params, - const BlastHitSavingParameters* hit_params, +s_BlastSearchEngineOneContext(EBlastProgramType program_number, + BLAST_SequenceBlk* query, BlastQueryInfo* query_info, + BLAST_SequenceBlk* subject, Int4 orig_length, LookupTableWrap* lookup, + BlastGapAlignStruct* gap_align, + const BlastScoringParameters* score_params, + const BlastInitialWordParameters* word_params, + const BlastExtensionParameters* ext_params, + const BlastHitSavingParameters* hit_params, BlastDiagnostics* diagnostics, BlastCoreAuxStruct* aux_struct, BlastHSPList** hsp_list_out_ptr, - TInterruptFnPtr interrupt_search, + BlastHSPStream* hsp_stream, + TInterruptFnPtr interrupt_search, SBlastProgress* progress_info) { Int2 status = 0; /* return value */ @@ -434,17 +572,30 @@ s_BlastSearchEngineOneContext(EBlastProgramType program_number, Int4 **matrix = (gap_align->positionBased) ? gap_align->sbp->psi_matrix->pssm->data : gap_align->sbp->matrix->data; - const Boolean kTranslatedSubject = + const Boolean kTranslatedSubject = (Blast_SubjectIsTranslated(program_number) || program_number == eBlastTypeRpsTblastn); - const Boolean kNucleotide = (program_number == eBlastTypeBlastn || - program_number == eBlastTypePhiBlastn); + const Boolean kNucleotide = Blast_ProgramIsNucleotide(program_number); const int kHspNumMax = BlastHspNumMax(score_options->gapped_calculation, hit_params->options); const int kScanSubjectOffsetArraySize = GetOffsetArraySize(lookup); + Int4 dbseq_chunk_overlap; Int4 overlap; - SubjectSplitStruct backup; + SubjectSplitStruct backup; backup.sequence = NULL; + /* increase overlap on db chunks for mapping to 1.5 times the longest + query */ + + if (Blast_ProgramIsMapping(program_number) && + (Int4)query_info->max_length < 110) { + + dbseq_chunk_overlap = (Int4)query_info->max_length + + (query_info->max_length / 2); + } + else { + dbseq_chunk_overlap = DBSEQ_CHUNK_OVERLAP; + } + if (diagnostics) { ungapped_stats = diagnostics->ungapped_stat; gapped_stats = diagnostics->gapped_stat; @@ -453,7 +604,9 @@ s_BlastSearchEngineOneContext(EBlastProgramType program_number, s_BackupSubject(subject, &backup); while (TRUE) { - status = s_GetNextSubjectChunk(subject, &backup, kNucleotide); + status = s_GetNextSubjectChunk(subject, &backup, kNucleotide, + dbseq_chunk_overlap); + if (status == SUBJECT_SPLIT_DONE) break; if (status == SUBJECT_SPLIT_NO_RANGE) continue; ASSERT(status == SUBJECT_SPLIT_OK); @@ -466,9 +619,9 @@ s_BlastSearchEngineOneContext(EBlastProgramType program_number, BlastInitHitListReset(init_hitlist); if (aux_struct->WordFinder) { - aux_struct->WordFinder(subject, query, query_info, lookup, matrix, - word_params, aux_struct->ewp, - aux_struct->offset_pairs, + aux_struct->WordFinder(subject, query, query_info, lookup, matrix, + word_params, aux_struct->ewp, + aux_struct->offset_pairs, kScanSubjectOffsetArraySize, init_hitlist, ungapped_stats); @@ -478,9 +631,9 @@ s_BlastSearchEngineOneContext(EBlastProgramType program_number, if (score_options->gapped_calculation) { Int4 prot_length = 0; if (score_options->is_ooframe) { - /* Convert query offsets in all HSPs into the mixed-frame + /* Convert query offsets in all HSPs into the mixed-frame coordinates */ - s_TranslateHSPsToDNAPCoord(program_number, init_hitlist, + s_TranslateHSPsToDNAPCoord(program_number, init_hitlist, query_info, subject->frame, orig_length, backup.offset); if (kTranslatedSubject) { prot_length = subject->length; @@ -490,28 +643,47 @@ s_BlastSearchEngineOneContext(EBlastProgramType program_number, /** NB: If queries are concatenated, HSP offsets must be adjusted * inside the following function call, so coordinates are * relative to the individual contexts (i.e. queries, strands or - * frames). Contexts should also be filled in HSPs when they + * frames). Contexts should also be filled in HSPs when they * are saved. */ /* fence_hit is null, since this is only for prelim stage. */ - status = aux_struct->GetGappedScore(program_number, query, query_info, - subject, gap_align, score_params, ext_params, hit_params, + if (aux_struct->GetGappedScore) { + status = aux_struct->GetGappedScore(program_number, query, + query_info, + subject, gap_align, score_params, ext_params, hit_params, init_hitlist, &hsp_list, gapped_stats, NULL); + } + else if (aux_struct->JumperGapped) { + status = aux_struct->JumperGapped(subject, query, query_info, + lookup, word_params, + score_params, hit_params, + aux_struct->offset_pairs, + aux_struct->mapper_wordhits, + kScanSubjectOffsetArraySize, + gap_align, init_hitlist, + &hsp_list, ungapped_stats, + gapped_stats); + } if (status) break; - /* Removes redundant HSPs. */ - Blast_HSPListPurgeHSPsWithCommonEndpoints(program_number, hsp_list, TRUE); + /* No need to do this for short reads */ + if (aux_struct->GetGappedScore) { + + /* Removes redundant HSPs. */ + Blast_HSPListPurgeHSPsWithCommonEndpoints(program_number, hsp_list, TRUE); - /* For nucleotide search, if match score is = 2, the odd scores - are rounded down to the nearest even number. */ - Blast_HSPListAdjustOddBlastnScores(hsp_list, score_options->gapped_calculation, gap_align->sbp); + /* For nucleotide search, if match score is = 2, the odd scores + are rounded down to the nearest even number. */ + Blast_HSPListAdjustOddBlastnScores(hsp_list, score_options->gapped_calculation, gap_align->sbp); + + } Blast_HSPListSortByScore(hsp_list); if (score_options->is_ooframe && kTranslatedSubject) subject->length = prot_length; } else { - BLAST_GetUngappedHSPList(init_hitlist, query_info, subject, + BLAST_GetUngappedHSPList(init_hitlist, query_info, subject, hit_params->options, &hsp_list); } @@ -530,10 +702,19 @@ s_BlastSearchEngineOneContext(EBlastProgramType program_number, Blast_HSPListAdjustOffsets(hsp_list, backup.offset); overlap = (backup.offset == backup.hard_ranges[backup.hm_index].left) ? - 0 : DBSEQ_CHUNK_OVERLAP; - status = Blast_HSPListsMerge(&hsp_list, &combined_hsp_list, + 0 : dbseq_chunk_overlap; + status = Blast_HSPListsMerge(&hsp_list, &combined_hsp_list, kHspNumMax, &(backup.offset), INT4_MIN, - overlap, score_options->gapped_calculation); + overlap, score_options->gapped_calculation, + Blast_ProgramIsMapping(program_number)); + + if (getenv("MAPPER_WRITE_SUBJECT_CHUNK")) { + s_WriteHSPsForChunk(combined_hsp_list, &backup, hit_params, + hsp_stream, subject->length, + backup.full_range.right - + backup.full_range.left); + } + } /* End loop on chunks of subject sequence */ s_RestoreSubject(subject, &backup); @@ -565,8 +746,8 @@ s_BlastSearchEngineCoreCleanUp(EBlastProgramType program_number, BlastQueryInfoFree(query_info); /* Free translation buffer and frame offsets, except for RPS tblastn, - * where they are taken from different structures, and hence shouldn't - * be freed here. + * where they are taken from different structures, and hence shouldn't + * be freed here. */ if (program_number != eBlastTypeRpsTblastn) { if (translation_buffer) { @@ -579,11 +760,11 @@ s_BlastSearchEngineCoreCleanUp(EBlastProgramType program_number, } } -/** Discard the HSPs above the prelim e-value threshold from the HSP list +/** Discard the HSPs above the prelim e-value threshold from the HSP list * @param hsp_list List of HSPs for one subject sequence [in] [out] * @param hit_params Parameters block containing the prelim e-value [in] */ -static Int2 +static Int2 s_Blast_HSPListReapByPrelimEvalue(BlastHSPList* hsp_list, const BlastHitSavingParameters* hit_params) { BlastHSP* hsp; @@ -619,8 +800,8 @@ s_Blast_HSPListReapByPrelimEvalue(BlastHSPList* hsp_list, const BlastHitSavingPa /** The core of the BLAST search: comparison between the (concatenated) * query against one subject sequence. Translation of the subject sequence - * into 6 frames is done inside, if necessary. If subject sequence is - * too long, it can be split into several chunks. + * into 6 frames is done inside, if necessary. If subject sequence is + * too long, it can be split into several chunks. * @param program_number BLAST program type [in] * @param query Query sequence structure [in] * @param query_info_in Query information [in] @@ -628,7 +809,7 @@ s_Blast_HSPListReapByPrelimEvalue(BlastHSPList* hsp_list, const BlastHitSavingPa * @param lookup Lookup table [in] * @param gap_align Structure for gapped alignment information [in] * @param score_params Scoring parameters [in] - * @param word_params Initial word finding and ungapped extension + * @param word_params Initial word finding and ungapped extension * parameters [in] * @param ext_params Gapped extension parameters [in] * @param hit_params Hit saving parameters [in] @@ -643,21 +824,22 @@ s_Blast_HSPListReapByPrelimEvalue(BlastHSPList* hsp_list, const BlastHitSavingPa * BLAST search [in|out] */ static Int2 -s_BlastSearchEngineCore(EBlastProgramType program_number, - BLAST_SequenceBlk* query, - BlastQueryInfo* query_info_in, - BLAST_SequenceBlk* subject, - LookupTableWrap* lookup, - BlastGapAlignStruct* gap_align, - const BlastScoringParameters* score_params, - const BlastInitialWordParameters* word_params, - const BlastExtensionParameters* ext_params, - const BlastHitSavingParameters* hit_params, +s_BlastSearchEngineCore(EBlastProgramType program_number, + BLAST_SequenceBlk* query, + BlastQueryInfo* query_info_in, + BLAST_SequenceBlk* subject, + LookupTableWrap* lookup, + BlastGapAlignStruct* gap_align, + const BlastScoringParameters* score_params, + const BlastInitialWordParameters* word_params, + const BlastExtensionParameters* ext_params, + const BlastHitSavingParameters* hit_params, const BlastDatabaseOptions* db_options, BlastDiagnostics* diagnostics, BlastCoreAuxStruct* aux_struct, BlastHSPList** hsp_list_out_ptr, - TInterruptFnPtr interrupt_search, + BlastHSPStream* hsp_stream, + TInterruptFnPtr interrupt_search, SBlastProgress* progress_info) { BlastHSPList* hsp_list_out=NULL; @@ -674,10 +856,9 @@ s_BlastSearchEngineCore(EBlastProgramType program_number, // To support rmblastn -RMH- BlastScoreBlk* sbp = gap_align->sbp; - const Boolean kTranslatedSubject = + const Boolean kTranslatedSubject = (Blast_SubjectIsTranslated(program_number) || program_number == eBlastTypeRpsTblastn); - const Boolean kNucleotide = (program_number == eBlastTypeBlastn || - program_number == eBlastTypePhiBlastn); + const Boolean kNucleotide = Blast_ProgramIsNucleotide(program_number); const int kHspNumMax = BlastHspNumMax(score_options->gapped_calculation, hit_options); Boolean isRPS = FALSE; SubjectSplitStruct backup = {0,}; @@ -703,19 +884,19 @@ s_BlastSearchEngineCore(EBlastProgramType program_number, last_context = 5; if (score_options->is_ooframe) { BLAST_GetAllTranslations(backup.sequence, eBlastEncodingNcbi2na, - backup.full_range.right, + backup.full_range.right, subject->gen_code_string, &translation_buffer, &frame_offsets, &subject->oof_sequence); subject->oof_sequence_allocated = TRUE; frame_offsets_a = frame_offsets; } else if (program_number == eBlastTypeRpsTblastn ) { - /* For RPS tblastn, subject is actually query, which has already + /* For RPS tblastn, subject is actually query, which has already been translated during the setup stage. */ translation_buffer = backup.sequence - 1; frame_offsets_a = frame_offsets = ContextOffsetsToOffsetArray(query_info_in); } else { BLAST_GetAllTranslations(backup.sequence, eBlastEncodingNcbi2na, - backup.full_range.right, + backup.full_range.right, subject->gen_code_string, &translation_buffer, &frame_offsets, NULL); frame_offsets_a = frame_offsets; @@ -767,9 +948,9 @@ s_BlastSearchEngineCore(EBlastProgramType program_number, } } else if (context == 3) { /* first negative context */ for (i = 0; i < subject->num_seq_ranges; i++) { - subject->seq_ranges[subject->num_seq_ranges-i-1].left = + subject->seq_ranges[subject->num_seq_ranges-i-1].left = subject->length - CONV_NUCL2PROT_COORDINATES(backup.seq_ranges[i].right); - subject->seq_ranges[subject->num_seq_ranges-i-1].right = + subject->seq_ranges[subject->num_seq_ranges-i-1].right = subject->length - CONV_NUCL2PROT_COORDINATES(backup.seq_ranges[i].left); } } @@ -777,20 +958,21 @@ s_BlastSearchEngineCore(EBlastProgramType program_number, subject->frame = context; } - status = s_BlastSearchEngineOneContext(program_number, query, query_info, - subject, orig_length, lookup, - gap_align, score_params, - word_params, ext_params, - hit_params, diagnostics, + status = s_BlastSearchEngineOneContext(program_number, query, query_info, + subject, orig_length, lookup, + gap_align, score_params, + word_params, ext_params, + hit_params, diagnostics, aux_struct, &hsp_list_for_chunks, - interrupt_search, progress_info); + hsp_stream, interrupt_search, + progress_info); if (status != 0) break; - + if (Blast_HSPListAppend(&hsp_list_for_chunks, &hsp_list_out, kHspNumMax)) { status = 1; break; } - + /* if searching was interrupted, delete accumulated results but continue execution so temporary structures get freed */ if (interrupt_search && (*interrupt_search)(progress_info) == TRUE) { @@ -806,33 +988,35 @@ s_BlastSearchEngineCore(EBlastProgramType program_number, if (status) { hsp_list_out = Blast_HSPListFree(hsp_list_out); - s_BlastSearchEngineCoreCleanUp(program_number, query_info, - query_info_in, translation_buffer, + s_BlastSearchEngineCoreCleanUp(program_number, query_info, + query_info_in, translation_buffer, frame_offsets_a); return status; } if (hit_params->link_hsp_params) { status = BLAST_LinkHsps(program_number, hsp_list_out, query_info, - subject->length, gap_align->sbp, hit_params->link_hsp_params, + subject->length, gap_align->sbp, hit_params->link_hsp_params, score_options->gapped_calculation); } else if (!Blast_ProgramIsPhiBlast(program_number) - && !(isRPS && !sbp->gbp) ){ + && !(isRPS && !sbp->gbp) + /* do not calculate E-values for mapping */ + && program_number != eBlastTypeMapping ) { /* Calculate e-values for all HSPs. Skip this step - for PHI or RPS with old FSC, since calculating the E values + for PHI or RPS with old FSC, since calculating the E values requires precomputation that has not been done yet */ double scale_factor = 1.0; if (isRPS) { scale_factor = score_params->scale_factor; } - status = Blast_HSPListGetEvalues(program_number, query_info, - stat_length, hsp_list_out, - score_options->gapped_calculation, + Blast_HSPListGetEvalues(program_number, query_info, + stat_length, hsp_list_out, + score_options->gapped_calculation, isRPS, gap_align->sbp, 0, scale_factor); } - - /* Use score threshold rather than evalue if - * matrix_only_scoring is used. -RMH- + + /* Use score threshold rather than evalue if + * matrix_only_scoring is used. -RMH- */ if ( sbp->matrix_only_scoring ) { @@ -854,31 +1038,31 @@ s_BlastSearchEngineCore(EBlastProgramType program_number, s_BlastSearchEngineCoreCleanUp(program_number, query_info, query_info_in, translation_buffer, frame_offsets_a); - + *hsp_list_out_ptr = hsp_list_out; return status; } -/** Fills the output information about the cutoffs uses in a BLAST search. +/** Fills the output information about the cutoffs uses in a BLAST search. * @param return_cutoffs Structure for saving cutoffs information [in] [out] * @param score_params Scoring parameters, containing the scaling factor [in] * @param word_params Initial word parameters [in] * @param ext_params Gapped extension parameters [in] * @param hit_params Hit saving parameters [in] */ -static Int2 -s_FillReturnCutoffsInfo(BlastRawCutoffs* return_cutoffs, - const BlastScoringParameters* score_params, - const BlastInitialWordParameters* word_params, +static Int2 +s_FillReturnCutoffsInfo(BlastRawCutoffs* return_cutoffs, + const BlastScoringParameters* score_params, + const BlastInitialWordParameters* word_params, const BlastExtensionParameters* ext_params, const BlastHitSavingParameters* hit_params) { /* since the cutoff score here will be used for display - purposes, strip out any internal scaling of the scores - + purposes, strip out any internal scaling of the scores + If this was a multi-query search, use the least stringent - cutoff and most generous dropoff value among all the + cutoff and most generous dropoff value among all the possible sequences */ Int4 scale_factor = (Int4)score_params->scale_factor; @@ -888,35 +1072,36 @@ s_FillReturnCutoffsInfo(BlastRawCutoffs* return_cutoffs, return_cutoffs->x_drop_ungapped = word_params->x_dropoff_max / scale_factor; return_cutoffs->x_drop_gap = ext_params->gap_x_dropoff / scale_factor; - return_cutoffs->x_drop_gap_final = ext_params->gap_x_dropoff_final / + return_cutoffs->x_drop_gap_final = ext_params->gap_x_dropoff_final / scale_factor; - return_cutoffs->ungapped_cutoff = word_params->cutoff_score_min / + return_cutoffs->ungapped_cutoff = word_params->cutoff_score_min / scale_factor; return_cutoffs->cutoff_score = hit_params->cutoff_score_min / scale_factor; return 0; } -/** Setup of the auxiliary BLAST structures; - * also calculates internally used parameters from options. - * @param seq_src Sequence source information, with callbacks to get +/** Setup of the auxiliary BLAST structures; + * also calculates internally used parameters from options. + * @param seq_src Sequence source information, with callbacks to get * sequences, their lengths, etc. [in] * @param lookup_wrap Lookup table, already constructed. [in] - * @param word_params Parameters for initial word finding and ungapped + * @param word_params Parameters for initial word finding and ungapped * extension. [in] * @param ext_options options for gapped extension. [in] * @param hit_options options for saving hits. [in] * @param query The query sequence block [in] - * @param aux_struct_ptr Placeholder joining various auxiliary memory + * @param aux_struct_ptr Placeholder joining various auxiliary memory * structures [out] */ -static Int2 +static Int2 s_BlastSetUpAuxStructures(const BlastSeqSrc* seq_src, - LookupTableWrap* lookup_wrap, + LookupTableWrap* lookup_wrap, const BlastInitialWordParameters* word_params, const BlastExtensionOptions* ext_options, const BlastHitSavingOptions* hit_options, - BLAST_SequenceBlk* query, BlastCoreAuxStruct** aux_struct_ptr) + BLAST_SequenceBlk* query, + const BlastQueryInfo* query_info, BlastCoreAuxStruct** aux_struct_ptr) { Int2 status = 0; BlastCoreAuxStruct* aux_struct; @@ -927,8 +1112,10 @@ s_BlastSetUpAuxStructures(const BlastSeqSrc* seq_src, Boolean indexed_mb_lookup = (lookup_wrap->read_indexed_db != 0); Boolean phi_lookup = (lookup_wrap->lut_type == ePhiLookupTable || lookup_wrap->lut_type == ePhiNaLookupTable); - Boolean smith_waterman = + Boolean smith_waterman = (ext_options->ePrelimGapExt == eSmithWatermanScoreOnly); + + Boolean jumper = (ext_options->ePrelimGapExt == eJumperWithTraceback); Int4 offset_array_size = GetOffsetArraySize(lookup_wrap); ASSERT(seq_src); @@ -936,10 +1123,13 @@ s_BlastSetUpAuxStructures(const BlastSeqSrc* seq_src, *aux_struct_ptr = aux_struct = (BlastCoreAuxStruct*) calloc(1, sizeof(BlastCoreAuxStruct)); - if ((status = BlastExtendWordNew(query->length, word_params, + if ((status = BlastExtendWordNew(query->length, word_params, &aux_struct->ewp)) != 0) return status; + aux_struct->JumperGapped = NULL; + aux_struct->mapper_wordhits = NULL; + if (smith_waterman) { aux_struct->WordFinder = NULL; /* @@ -965,18 +1155,38 @@ s_BlastSetUpAuxStructures(const BlastSeqSrc* seq_src, else { aux_struct->WordFinder = BlastNaWordFinder; } + + if (jumper) { + aux_struct->WordFinder = NULL; + } } - - aux_struct->offset_pairs = + + aux_struct->offset_pairs = (BlastOffsetPair*) malloc(offset_array_size * sizeof(BlastOffsetPair)); - + aux_struct->init_hitlist = BLAST_InitHitListNew(); /* Pick which gapped alignment algorithm to use. */ if (phi_lookup) aux_struct->GetGappedScore = PHIGetGappedScore; else if (smith_waterman) aux_struct->GetGappedScore = BLAST_SmithWatermanGetGappedScore; - else + else if (jumper) { + aux_struct->GetGappedScore = NULL; + + /* Create several lists of word hits for mapper with large number of + queries */ + if (query_info->num_queries > 1000) { + aux_struct->mapper_wordhits = MapperWordHitsNew(query, query_info); + } + + if (indexed_mb_lookup) { + aux_struct->JumperGapped = ShortRead_IndexedWordFinder; + } + else { + aux_struct->JumperGapped = JumperNaWordFinder; + } + } + else aux_struct->GetGappedScore = BLAST_GetGappedScore; return status; @@ -989,7 +1199,7 @@ s_BlastSetUpAuxStructures(const BlastSeqSrc* seq_src, * @param query_info Additional query information [in] * @param seq_src Structure containing BLAST database [in] * @param score_params Hit scoring parameters [in] - * @param lookup_wrap The lookup table, constructed earlier [in] + * @param lookup_wrap The lookup table, constructed earlier [in] * @param aux_struct Wrapper for auxiliary structures used in preliminary * search [in] * @param word_params Parameters for processing initial word hits [in] @@ -998,22 +1208,22 @@ s_BlastSetUpAuxStructures(const BlastSeqSrc* seq_src, * for gapped alignment. [in] * @param hit_params Parameters for saving the HSPs [in] * @param hsp_stream Placeholder for saving HSP lists [in] - * @param diagnostics Return statistics containing numbers of hits on - * different stages of the search. Statistics saved only + * @param diagnostics Return statistics containing numbers of hits on + * different stages of the search. Statistics saved only * for the allocated parts of the structure. [in] [out] * @param interrupt_search function callback to allow interruption of BLAST * search [in, optional] * @param progress_info contains information about the progress of the current * BLAST search [in|out] */ -static Int2 -s_RPSPreliminarySearchEngine(EBlastProgramType program_number, +static Int2 +s_RPSPreliminarySearchEngine(EBlastProgramType program_number, BLAST_SequenceBlk* query, BlastQueryInfo* query_info, const BlastSeqSrc* seq_src, - const BlastScoringParameters* score_params, + const BlastScoringParameters* score_params, LookupTableWrap* lookup_wrap, BlastCoreAuxStruct* aux_struct, - const BlastInitialWordParameters* word_params, - const BlastExtensionParameters* ext_params, + const BlastInitialWordParameters* word_params, + const BlastExtensionParameters* ext_params, BlastGapAlignStruct* gap_align, const BlastHitSavingParameters* hit_params, BlastHSPStream* hsp_stream, BlastDiagnostics* diagnostics, @@ -1065,27 +1275,27 @@ s_RPSPreliminarySearchEngine(EBlastProgramType program_number, /* Run the search; the input query is what gets scanned and the concatenated DB is the sequence associated with the score matrix. This essentially means that 'query' - and 'subject' have opposite conventions for the search. - + and 'subject' have opposite conventions for the search. + Note that while scores can be calculated for any alignment found, we have not set up any Karlin parameters or effective search space sizes for the concatenated DB. This means that E-values cannot be calculated after hits are found. */ for (index = 0; index < query_info->num_queries; ++index) { - /* Separate one query from the set: create an auxiliary query_info + /* Separate one query from the set: create an auxiliary query_info structure which refers to this single query. */ - if (Blast_GetOneQueryStructs(&one_query_info, &one_query, + if (Blast_GetOneQueryStructs(&one_query_info, &one_query, query_info, query, index) != 0) return -1; /* It is OK to pass NULL for the BlastDatabaseOptions argument, because it will not be checked for RPS BLAST program types. */ status = (Int4) - s_BlastSearchEngineCore(program_number, &concat_db, one_query_info, - one_query, lookup_wrap, gap_align, score_params, - word_params, ext_params, hit_params, NULL, - diagnostics, aux_struct, &hsp_list, interrupt_search, + s_BlastSearchEngineCore(program_number, &concat_db, one_query_info, + one_query, lookup_wrap, gap_align, score_params, + word_params, ext_params, hit_params, NULL, + diagnostics, aux_struct, &hsp_list, NULL, interrupt_search, progress_info); if (interrupt_search && (*interrupt_search)(progress_info) == TRUE) { @@ -1229,26 +1439,43 @@ s_AdjustSubjectForSraSearch(BlastHSPList* hsp_list, Uint1 offset ) } -Int4 -BLAST_PreliminarySearchEngine(EBlastProgramType program_number, +static Int4 s_GetMinimumSubjSeqLen(LookupTableWrap* lookup_wrap) +{ + Int4 word_length = 1; + if (lookup_wrap->lut_type == eAaLookupTable) { + BlastAaLookupTable* lut; + lut = (BlastAaLookupTable*)(lookup_wrap->lut); + word_length = lut->word_length; + } else if (lookup_wrap->lut_type == eCompressedAaLookupTable) { + BlastCompressedAaLookupTable* lut; + lut = (BlastCompressedAaLookupTable*)(lookup_wrap->lut); + word_length = lut->word_length; + } + return word_length * 3 + 2; +} + + +Int4 +BLAST_PreliminarySearchEngine(EBlastProgramType program_number, BLAST_SequenceBlk* query, BlastQueryInfo* query_info, const BlastSeqSrc* seq_src, BlastGapAlignStruct* gap_align, - BlastScoringParameters* score_params, + BlastScoringParameters* score_params, LookupTableWrap* lookup_wrap, - const BlastInitialWordOptions* word_options, - BlastExtensionParameters* ext_params, + const BlastInitialWordOptions* word_options, + BlastExtensionParameters* ext_params, BlastHitSavingParameters* hit_params, BlastEffectiveLengthsParameters* eff_len_params, - const PSIBlastOptions* psi_options, + const PSIBlastOptions* psi_options, const BlastDatabaseOptions* db_options, BlastHSPStream* hsp_stream, BlastDiagnostics* diagnostics, TInterruptFnPtr interrupt_search, SBlastProgress* progress_info) { BlastCoreAuxStruct* aux_struct = NULL; - BlastHSPList* hsp_list = NULL; + BlastHSPList* hsp_list = NULL; BlastSeqSrcGetSeqArg seq_arg; Int2 status = 0; Int8 db_length = 0; + Int4 min_subj_seq_length = 1; const BlastScoringOptions* score_options = score_params->options; const BlastHitSavingOptions* hit_options = hit_params->options; const BlastExtensionOptions* ext_options = ext_params->options; @@ -1256,20 +1483,23 @@ BLAST_PreliminarySearchEngine(EBlastProgramType program_number, Boolean gapped_calculation = score_options->gapped_calculation; BlastScoreBlk* sbp = gap_align->sbp; BlastSeqSrcIterator* itr; - const Boolean kNucleotide = (program_number == eBlastTypeBlastn || - program_number == eBlastTypePhiBlastn); + const Boolean kNucleotide = Blast_ProgramIsNucleotide(program_number); - T_MB_IdbCheckOid check_index_oid = + T_MB_IdbCheckOid check_index_oid = (T_MB_IdbCheckOid)lookup_wrap->check_index_oid; Int4 last_vol_idx = LAST_VOL_IDX_INIT; - BlastInitialWordParametersNew(program_number, word_options, - hit_params, lookup_wrap, sbp, query_info, + if (Blast_SubjectIsTranslated(program_number)) { + min_subj_seq_length = s_GetMinimumSubjSeqLen(lookup_wrap); + } + + BlastInitialWordParametersNew(program_number, word_options, + hit_params, lookup_wrap, sbp, query_info, BlastSeqSrcGetAvgSeqLen(seq_src), &word_params); - if ((status = - s_BlastSetUpAuxStructures(seq_src, lookup_wrap, word_params, - ext_options, hit_options, query, &aux_struct)) != 0) + if ((status = + s_BlastSetUpAuxStructures(seq_src, lookup_wrap, word_params, + ext_options, hit_options, query, query_info, &aux_struct)) != 0) return status; /* remember the current search state */ @@ -1279,9 +1509,9 @@ BLAST_PreliminarySearchEngine(EBlastProgramType program_number, /* For RPS BLAST, there is no loop over subject sequences, so the preliminary search engine is done in a separate function. */ if (Blast_ProgramIsRpsBlast(program_number)) { - status = - s_RPSPreliminarySearchEngine(program_number, query, query_info, - seq_src, score_params, lookup_wrap, aux_struct, word_params, + status = + s_RPSPreliminarySearchEngine(program_number, query, query_info, + seq_src, score_params, lookup_wrap, aux_struct, word_params, ext_params, gap_align, hit_params, hsp_stream, diagnostics, interrupt_search, progress_info); word_params = BlastInitialWordParametersFree(word_params); @@ -1291,19 +1521,19 @@ BLAST_PreliminarySearchEngine(EBlastProgramType program_number, /* Update the parameters for linking HSPs, if necessary. */ BlastLinkHSPParametersUpdate(word_params, hit_params, gapped_calculation); - + memset((void*) &seq_arg, 0, sizeof(seq_arg)); /* Encoding is set so there are no sentinel bytes, and protein/nucleotide sequences are retieved in ncbistdaa/ncbi2na encodings respectively. */ - seq_arg.encoding = eBlastEncodingProtein; + seq_arg.encoding = eBlastEncodingProtein; db_length = BlastSeqSrcGetTotLen(seq_src); itr = BlastSeqSrcIteratorNewEx(MAX(BlastSeqSrcGetNumSeqs(seq_src)/100,1)); /* iterate over all subject sequences */ - while ( (seq_arg.oid = BlastSeqSrcIteratorNext(seq_src, itr)) + while ( (seq_arg.oid = BlastSeqSrcIteratorNext(seq_src, itr)) != BLAST_SEQSRC_EOF) { Int4 stat_length; if (seq_arg.oid == BLAST_SEQSRC_ERROR) { @@ -1311,36 +1541,42 @@ BLAST_PreliminarySearchEngine(EBlastProgramType program_number, break; } - if( check_index_oid != 0 && - check_index_oid( seq_arg.oid, &last_vol_idx ) == eNoResults ) { + if (check_index_oid != 0 && + check_index_oid(seq_arg.oid, &last_vol_idx) == eNoResults) { + continue; + } + + if (BlastSeqSrcGetSequence(seq_src, &seq_arg) < 0) { continue; } - if (BlastSeqSrcGetSequence(seq_src, &seq_arg) < 0) + if (seq_arg.seq->length < min_subj_seq_length) { + BlastSeqSrcReleaseSequence(seq_src, &seq_arg); continue; + } if (db_length == 0) { /* This is not a database search, hence need to recalculate and save - the effective search spaces and length adjustments for all - queries based on the length of the current single subject + the effective search spaces and length adjustments for all + queries based on the length of the current single subject sequence. */ - if ((status = BLAST_OneSubjectUpdateParameters(program_number, - seq_arg.seq->length, score_options, query_info, - sbp, hit_params, word_params, + if ((status = BLAST_OneSubjectUpdateParameters(program_number, + seq_arg.seq->length, score_options, query_info, + sbp, hit_params, word_params, eff_len_params)) != 0) return status; } - stat_length = seq_arg.seq->length; + stat_length = seq_arg.seq->length; /* Calculate cutoff scores for linking HSPs. Do this only for ungapped protein searches and ungapped translated searches. */ if (hit_params->link_hsp_params && !kNucleotide && !gapped_calculation) { - CalculateLinkHSPCutoffs(program_number, query_info, sbp, - hit_params->link_hsp_params, word_params, db_length, - seq_arg.seq->length); + CalculateLinkHSPCutoffs(program_number, query_info, sbp, + hit_params->link_hsp_params, word_params, db_length, + seq_arg.seq->length); } if (Blast_SubjectIsTranslated(program_number)) { @@ -1348,17 +1584,19 @@ BLAST_PreliminarySearchEngine(EBlastProgramType program_number, * doesn't provide a genetic code string, use the default genetic * code for all subjects (as in the C toolkit) */ if (seq_arg.seq->gen_code_string == NULL) { - seq_arg.seq->gen_code_string = + seq_arg.seq->gen_code_string = GenCodeSingletonFind(db_options->genetic_code); } ASSERT(seq_arg.seq->gen_code_string); stat_length /= CODON_LENGTH; } - status = - s_BlastSearchEngineCore(program_number, query, query_info, - seq_arg.seq, lookup_wrap, gap_align, score_params, word_params, - ext_params, hit_params, db_options, diagnostics, aux_struct, - &hsp_list, interrupt_search, progress_info); + status = + s_BlastSearchEngineCore(program_number, query, query_info, + seq_arg.seq, lookup_wrap, gap_align, + score_params, word_params, ext_params, + hit_params, db_options, diagnostics, + aux_struct, &hsp_list, hsp_stream, + interrupt_search, progress_info); if (status) { break; } @@ -1373,36 +1611,36 @@ BLAST_PreliminarySearchEngine(EBlastProgramType program_number, else s_AdjustSubjectForSraSearch(hsp_list, seq_arg.seq->bases_offset); } - /* The following must be performed for any ungapped + /* The following must be performed for any ungapped search with a nucleotide database. */ - status = + status = Blast_HSPListReevaluateUngapped( - program_number, hsp_list, query, - seq_arg.seq, word_params, hit_params, - query_info, sbp, score_params, seq_src, + program_number, hsp_list, query, + seq_arg.seq, word_params, hit_params, + query_info, sbp, score_params, seq_src, seq_arg.seq->gen_code_string); if (status) { /* Tell the indexing library that this thread is done with preliminary search. */ if( check_index_oid != 0 ) { - ((T_MB_IdxEndSearchIndication)( + ((T_MB_IdxEndSearchIndication)( lookup_wrap->end_search_indication))( last_vol_idx ); } - + BlastSeqSrcReleaseSequence(seq_src, &seq_arg); return status; } /* Relink HSPs if sum statistics is used, because scores might * have changed after reevaluation with ambiguities, and there * will be no traceback stage where relinking is done normally. - * If sum statistics are not used, just recalculate e-values. + * If sum statistics are not used, just recalculate e-values. */ if (hit_params->link_hsp_params) { - status = + status = BLAST_LinkHsps(program_number, hsp_list, query_info, - seq_arg.seq->length, sbp, - hit_params->link_hsp_params, + seq_arg.seq->length, sbp, + hit_params->link_hsp_params, gapped_calculation); } else { Blast_HSPListGetEvalues(program_number, query_info, @@ -1410,8 +1648,8 @@ BLAST_PreliminarySearchEngine(EBlastProgramType program_number, gapped_calculation, FALSE, sbp, 0, 1.0); } - /* Use score threshold rather than evalue if - * matrix_only_scoring is used. -RMH- + /* Use score threshold rather than evalue if + * matrix_only_scoring is used. -RMH- */ if ( sbp->matrix_only_scoring ) { @@ -1420,13 +1658,13 @@ BLAST_PreliminarySearchEngine(EBlastProgramType program_number, }else { status = s_Blast_HSPListReapByPrelimEvalue(hsp_list, hit_params); } - + Blast_HSPListReapByQueryCoverage(hsp_list,hit_params->options, query_info, program_number); /* Calculate and fill the bit scores, since there will be no traceback stage where this can be done. */ Blast_HSPListGetBitScores(hsp_list, gapped_calculation, sbp); - } - + } + // This should only happen for sra searches if((seq_arg.seq->bases_offset > 0) && (gapped_calculation)) { @@ -1445,12 +1683,12 @@ BLAST_PreliminarySearchEngine(EBlastProgramType program_number, { for (query_index=0; query_indexresults->num_queries; query_index++) if (hsp_stream->results->hitlist_array[query_index] && hsp_stream->results->hitlist_array[query_index]->heapified) - hit_params->low_score[query_index] = - MAX(hit_params->low_score[query_index], + hit_params->low_score[query_index] = + MAX(hit_params->low_score[query_index], hit_params->options->low_score_perc*(hsp_stream->results->hitlist_array[query_index]->low_score)); } } - + BlastSeqSrcReleaseSequence(seq_src, &seq_arg); /* check for interrupt */ @@ -1459,12 +1697,12 @@ BLAST_PreliminarySearchEngine(EBlastProgramType program_number, break; } } - + /* Tell the indexing library that this thread is done with preliminary search. */ if( check_index_oid != 0 ) { - ((T_MB_IdxEndSearchIndication)( + ((T_MB_IdxEndSearchIndication)( lookup_wrap->end_search_indication))( last_vol_idx ); } @@ -1474,7 +1712,7 @@ BLAST_PreliminarySearchEngine(EBlastProgramType program_number, /* Fill the cutoff values in the diagnostics structure */ if (diagnostics && diagnostics->cutoffs) { - s_FillReturnCutoffsInfo(diagnostics->cutoffs, score_params, word_params, + s_FillReturnCutoffsInfo(diagnostics->cutoffs, score_params, word_params, ext_params, hit_params); } @@ -1484,21 +1722,21 @@ BLAST_PreliminarySearchEngine(EBlastProgramType program_number, } Int2 -Blast_RunPreliminarySearch(EBlastProgramType program, - BLAST_SequenceBlk* query, - BlastQueryInfo* query_info, - const BlastSeqSrc* seq_src, +Blast_RunPreliminarySearch(EBlastProgramType program, + BLAST_SequenceBlk* query, + BlastQueryInfo* query_info, + const BlastSeqSrc* seq_src, const BlastScoringOptions* score_options, - BlastScoreBlk* sbp, + BlastScoreBlk* sbp, LookupTableWrap* lookup_wrap, - const BlastInitialWordOptions* word_options, + const BlastInitialWordOptions* word_options, const BlastExtensionOptions* ext_options, const BlastHitSavingOptions* hit_options, const BlastEffectiveLengthsOptions* eff_len_options, - const PSIBlastOptions* psi_options, - const BlastDatabaseOptions* db_options, - BlastHSPStream* hsp_stream, - BlastDiagnostics* diagnostics) + const PSIBlastOptions* psi_options, + const BlastDatabaseOptions* db_options, + BlastHSPStream* hsp_stream, + BlastDiagnostics* diagnostics) { return Blast_RunPreliminarySearchWithInterrupt(program, query, query_info, seq_src, score_options, sbp, lookup_wrap, @@ -1506,64 +1744,64 @@ Blast_RunPreliminarySearch(EBlastProgramType program, psi_options, db_options, hsp_stream, diagnostics, NULL, NULL); } -Int2 -Blast_RunPreliminarySearchWithInterrupt(EBlastProgramType program, - BLAST_SequenceBlk* query, - BlastQueryInfo* query_info, - const BlastSeqSrc* seq_src, +Int2 +Blast_RunPreliminarySearchWithInterrupt(EBlastProgramType program, + BLAST_SequenceBlk* query, + BlastQueryInfo* query_info, + const BlastSeqSrc* seq_src, const BlastScoringOptions* score_options, - BlastScoreBlk* sbp, + BlastScoreBlk* sbp, LookupTableWrap* lookup_wrap, - const BlastInitialWordOptions* word_options, + const BlastInitialWordOptions* word_options, const BlastExtensionOptions* ext_options, const BlastHitSavingOptions* hit_options, const BlastEffectiveLengthsOptions* eff_len_options, - const PSIBlastOptions* psi_options, - const BlastDatabaseOptions* db_options, - BlastHSPStream* hsp_stream, + const PSIBlastOptions* psi_options, + const BlastDatabaseOptions* db_options, + BlastHSPStream* hsp_stream, BlastDiagnostics* diagnostics, TInterruptFnPtr interrupt_search, SBlastProgress* progress_info) { Int2 status = 0; BlastScoringParameters* score_params = NULL;/**< Scoring parameters */ - BlastExtensionParameters* ext_params = NULL;/**< Gapped extension + BlastExtensionParameters* ext_params = NULL;/**< Gapped extension parameters */ BlastHitSavingParameters* hit_params = NULL;/**< Hit saving parameters */ - BlastEffectiveLengthsParameters* eff_len_params = NULL; /**< Parameters + BlastEffectiveLengthsParameters* eff_len_params = NULL; /**< Parameters for effective lengths calculations */ BlastGapAlignStruct* gap_align = NULL; /**< Gapped alignment structure */ - - /* Use a local diagnostics structure, because the one passed in an input + + /* Use a local diagnostics structure, because the one passed in an input argument can be shared between multiple threads, so we don't want to pass it to the engine and have a lot of mutex contention. */ BlastDiagnostics* local_diagnostics = Blast_DiagnosticsInit(); - if ((status = - BLAST_GapAlignSetUp(program, seq_src, score_options, - eff_len_options, ext_options, hit_options, - query_info, sbp, &score_params, &ext_params, + if ((status = + BLAST_GapAlignSetUp(program, seq_src, score_options, + eff_len_options, ext_options, hit_options, + query_info, sbp, &score_params, &ext_params, &hit_params, &eff_len_params, &gap_align)) != 0) return status; - + if ((status= - BLAST_PreliminarySearchEngine(program, query, query_info, - seq_src, gap_align, score_params, - lookup_wrap, word_options, + BLAST_PreliminarySearchEngine(program, query, query_info, + seq_src, gap_align, score_params, + lookup_wrap, word_options, ext_params, hit_params, eff_len_params, - psi_options, db_options, hsp_stream, - local_diagnostics, interrupt_search, - progress_info)) != 0) + psi_options, db_options, hsp_stream, + local_diagnostics, interrupt_search, + progress_info)) != 0) return status; /* Do not destruct score block here */ gap_align->sbp = NULL; gap_align = BLAST_GapAlignStructFree(gap_align); - + score_params = BlastScoringParametersFree(score_params); hit_params = BlastHitSavingParametersFree(hit_params); ext_params = BlastExtensionParametersFree(ext_params); eff_len_params = BlastEffectiveLengthsParametersFree(eff_len_params); - + /* Now update the input diagonistics structure. */ Blast_DiagnosticsUpdate(diagnostics, local_diagnostics); Blast_DiagnosticsFree(local_diagnostics); @@ -1589,19 +1827,19 @@ s_BlastRunFullSearchCleanUp(BlastGapAlignStruct* gap_align, BlastEffectiveLengthsParametersFree(eff_len_params); } -Int4 -Blast_RunFullSearch(EBlastProgramType program_number, +Int4 +Blast_RunFullSearch(EBlastProgramType program_number, BLAST_SequenceBlk* query, BlastQueryInfo* query_info, const BlastSeqSrc* seq_src, BlastScoreBlk* sbp, - const BlastScoringOptions* score_options, + const BlastScoringOptions* score_options, LookupTableWrap* lookup_wrap, - const BlastInitialWordOptions* word_options, - const BlastExtensionOptions* ext_options, + const BlastInitialWordOptions* word_options, + const BlastExtensionOptions* ext_options, const BlastHitSavingOptions* hit_options, const BlastEffectiveLengthsOptions* eff_len_options, - const PSIBlastOptions* psi_options, + const PSIBlastOptions* psi_options, const BlastDatabaseOptions* db_options, - BlastHSPStream* hsp_stream, const BlastRPSInfo* rps_info, + BlastHSPStream* hsp_stream, const BlastRPSInfo* rps_info, BlastDiagnostics* diagnostics, BlastHSPResults** results, TInterruptFnPtr interrupt_search, SBlastProgress* progress_info) @@ -1614,44 +1852,44 @@ Blast_RunFullSearch(EBlastProgramType program_number, BlastGapAlignStruct* gap_align = NULL; SPHIPatternSearchBlk* pattern_blk = NULL; - if ((status = - BLAST_GapAlignSetUp(program_number, seq_src, score_options, - eff_len_options, ext_options, hit_options, query_info, sbp, - &score_params, &ext_params, &hit_params, &eff_len_params, + if ((status = + BLAST_GapAlignSetUp(program_number, seq_src, score_options, + eff_len_options, ext_options, hit_options, query_info, sbp, + &score_params, &ext_params, &hit_params, &eff_len_params, &gap_align)) != 0) { - s_BlastRunFullSearchCleanUp(gap_align, score_params, ext_params, + s_BlastRunFullSearchCleanUp(gap_align, score_params, ext_params, hit_params, eff_len_params); return status; } - + if ((status= - BLAST_PreliminarySearchEngine(program_number, query, query_info, - seq_src, gap_align, score_params, lookup_wrap, word_options, - ext_params, hit_params, eff_len_params, psi_options, - db_options, hsp_stream, diagnostics, interrupt_search, + BLAST_PreliminarySearchEngine(program_number, query, query_info, + seq_src, gap_align, score_params, lookup_wrap, word_options, + ext_params, hit_params, eff_len_params, psi_options, + db_options, hsp_stream, diagnostics, interrupt_search, progress_info)) != 0) { - s_BlastRunFullSearchCleanUp(gap_align, score_params, ext_params, + s_BlastRunFullSearchCleanUp(gap_align, score_params, ext_params, hit_params, eff_len_params); return status; } - + /* Prohibit any subsequent writing to the HSP stream. */ BlastHSPStreamClose(hsp_stream); if (Blast_ProgramIsPhiBlast(program_number)) { pattern_blk = ((SPHIPatternSearchBlk*) lookup_wrap->lut); - pattern_blk->num_patterns_db = + pattern_blk->num_patterns_db = (Int4)diagnostics->ungapped_stat->lookup_hits; - } + } - if ((status = + if ((status = BLAST_ComputeTraceback(program_number, hsp_stream, query, query_info, - seq_src, gap_align, score_params, ext_params, - hit_params, eff_len_params, db_options, + seq_src, gap_align, score_params, ext_params, + hit_params, eff_len_params, db_options, psi_options, rps_info, pattern_blk, results, interrupt_search, progress_info)) != 0) { - s_BlastRunFullSearchCleanUp(gap_align, score_params, ext_params, + s_BlastRunFullSearchCleanUp(gap_align, score_params, ext_params, hit_params, eff_len_params); return status; } diff --git a/c++/src/algo/blast/core/blast_extend.c b/c++/src/algo/blast/core/blast_extend.c index 60db56f9..36ecdd69 100644 --- a/c++/src/algo/blast/core/blast_extend.c +++ b/c++/src/algo/blast/core/blast_extend.c @@ -1,4 +1,4 @@ -/* $Id: blast_extend.c 167284 2009-07-30 19:29:38Z maning $ +/* $Id: blast_extend.c 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -28,11 +28,6 @@ * Functions to initialize structures used for BLAST extension */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_extend.c 167284 2009-07-30 19:29:38Z maning $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include diff --git a/c++/src/algo/blast/core/blast_filter.c b/c++/src/algo/blast/core/blast_filter.c index 8ad388b3..8b44c9c3 100644 --- a/c++/src/algo/blast/core/blast_filter.c +++ b/c++/src/algo/blast/core/blast_filter.c @@ -1,4 +1,4 @@ -/* $Id: blast_filter.c 306966 2011-06-20 13:16:49Z maning $ +/* $Id: blast_filter.c 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -28,11 +28,6 @@ * All code related to query sequence masking/filtering for BLAST */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_filter.c 306966 2011-06-20 13:16:49Z maning $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include @@ -575,7 +570,9 @@ BlastFilteringOptionsFromString(EBlastProgramType program_number, } else if (*ptr == 'L' || *ptr == 'T') { /* do low-complexity filtering; dust for blastn, otherwise seg.*/ - if (program_number == eBlastTypeBlastn) + if (program_number == eBlastTypeBlastn + || program_number == eBlastTypeMapping) + SDustOptionsNew(&dustOptions); else SSegOptionsNew(&segOptions); @@ -1021,7 +1018,8 @@ BLAST_ComplementMaskLocations(EBlastProgramType program_number, const BlastMaskLoc* mask_loc, BlastSeqLoc* *complement_mask) { Int4 context; - const Boolean kIsNucl = (program_number == eBlastTypeBlastn); + const Boolean kIsNucl = (program_number == eBlastTypeBlastn || + program_number == eBlastTypeMapping); BlastSeqLoc* tail = NULL; /* Pointer to the tail of the complement_mask linked list */ @@ -1196,7 +1194,8 @@ s_GetFilteringLocationsForOneContext(BLAST_SequenceBlk* query_blk, Int4 context_offset; Uint1 *buffer; /* holds sequence for plus strand or protein. */ - const Boolean kIsNucl = (program_number == eBlastTypeBlastn); + const Boolean kIsNucl = (program_number == eBlastTypeBlastn || + program_number == eBlastTypeMapping); context_offset = query_info->contexts[context].query_offset; buffer = &query_blk->sequence[context_offset]; @@ -1345,7 +1344,8 @@ BlastSetUp_MaskQuery(BLAST_SequenceBlk* query_blk, const BlastMaskLoc *filter_maskloc, EBlastProgramType program_number) { - const Boolean kIsNucl = (program_number == eBlastTypeBlastn); + const Boolean kIsNucl = (program_number == eBlastTypeBlastn + || program_number == eBlastTypeMapping); Int4 context; /* loop variable. */ Int4 total_length; Boolean has_mask = FALSE; /* Check for whether filter_maskloc is empty. */ diff --git a/c++/src/algo/blast/core/blast_gapalign.c b/c++/src/algo/blast/core/blast_gapalign.c index ebce005e..ea077452 100644 --- a/c++/src/algo/blast/core/blast_gapalign.c +++ b/c++/src/algo/blast/core/blast_gapalign.c @@ -1,4 +1,4 @@ -/* $Id: blast_gapalign.c 473564 2015-07-21 15:29:04Z madden $ +/* $Id: blast_gapalign.c 516338 2016-10-12 17:32:04Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -30,11 +30,6 @@ * Functions to perform gapped alignment */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_gapalign.c 473564 2015-07-21 15:29:04Z madden $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include /* for NCBI2NA_UNPACK_BASE macros */ @@ -42,18 +37,19 @@ static char const rcsid[] = #include "blast_gapalign_priv.h" #include "blast_hits_priv.h" #include "blast_itree.h" +#include "jumper.h" -static Int2 s_BlastDynProgNtGappedAlignment(BLAST_SequenceBlk* query_blk, - BLAST_SequenceBlk* subject_blk, BlastGapAlignStruct* gap_align, +static Int2 s_BlastDynProgNtGappedAlignment(BLAST_SequenceBlk* query_blk, + BLAST_SequenceBlk* subject_blk, BlastGapAlignStruct* gap_align, const BlastScoringParameters* score_params, BlastInitHSP* init_hsp); -static Int4 s_BlastAlignPackedNucl(Uint1* B, Uint1* A, Int4 N, Int4 M, +static Int4 s_BlastAlignPackedNucl(Uint1* B, Uint1* A, Int4 N, Int4 M, Int4* pej, Int4* pei, BlastGapAlignStruct* gap_align, const BlastScoringParameters* score_params, Boolean reverse_sequence); -static Int2 s_BlastProtGappedAlignment(EBlastProgramType program, +static Int2 s_BlastProtGappedAlignment(EBlastProgramType program, BLAST_SequenceBlk* query_in, BLAST_SequenceBlk* subject_in, BlastGapAlignStruct* gap_align, - const BlastScoringParameters* score_params, + const BlastScoringParameters* score_params, BlastInitHSP* init_hsp, Boolean restricted_alignment, Boolean * fence_hit); @@ -64,9 +60,9 @@ static Int2 s_BlastProtGappedAlignment(EBlastProgramType program, #define CHUNKSIZE 2097152 /** Retrieve the state structure corresponding to a given length - * @param head Pointer to the first element of the state structures + * @param head Pointer to the first element of the state structures * array [in] - * @param length The length for which the state structure has to be + * @param length The length for which the state structure has to be * found [in] * @return The found or created state structure */ @@ -80,7 +76,7 @@ s_GapGetState(GapStateArrayStruct** head, Int4 length) length += length/3; /* Add on about 30% so the end will get reused. */ retval = NULL; if (*head == NULL) { - retval = (GapStateArrayStruct*) + retval = (GapStateArrayStruct*) malloc(sizeof(GapStateArrayStruct)); retval->state_array = (Uint1*) malloc(chunksize*sizeof(Uint1)); retval->length = chunksize; @@ -94,7 +90,7 @@ s_GapGetState(GapStateArrayStruct** head, Int4 length) if (length < (var->length - var->used)) { retval = var; break; - } else if (var->used == 0) { + } else if (var->used == 0) { /* If it's empty and too small, replace. */ sfree(var->state_array); var->state_array = (Uint1*) malloc(chunksize*sizeof(Uint1)); @@ -105,7 +101,7 @@ s_GapGetState(GapStateArrayStruct** head, Int4 length) last = var; var = var->next; } - + if (var == NULL) { retval = (GapStateArrayStruct*) malloc(sizeof(GapStateArrayStruct)); @@ -121,7 +117,7 @@ s_GapGetState(GapStateArrayStruct** head, Int4 length) if (retval->state_array == NULL) ErrPostEx(SEV_ERROR, 0, 0, "state array is NULL"); #endif - + return retval; } @@ -138,12 +134,12 @@ s_GapPurgeState(GapStateArrayStruct* state_struct) state_struct->used = 0; state_struct = state_struct->next; } - + return TRUE; } /** Deallocate the memory for greedy gapped alignment */ -static SGreedyAlignMem* +static SGreedyAlignMem* s_BlastGreedyAlignsFree(SGreedyAlignMem* gamp) { if (gamp->last_seq2_off) { @@ -170,7 +166,7 @@ s_BlastGreedyAlignsFree(SGreedyAlignMem* gamp) * @param Xdrop The Xdrop value [in] * @return The allocated SGreedyAlignMem structure */ -static SGreedyAlignMem* +static SGreedyAlignMem* s_BlastGreedyAlignMemAlloc(const BlastScoringParameters* score_params, const BlastExtensionParameters* ext_params, Int4 max_d, Int4 Xdrop) @@ -179,14 +175,14 @@ s_BlastGreedyAlignMemAlloc(const BlastScoringParameters* score_params, Int4 max_d_1, d_diff, max_cost, gd, i; Int4 reward, penalty, gap_open, gap_extend; Int4 Mis_cost, GE_cost; - + if (score_params == NULL || (!ext_params && !Xdrop)) return NULL; - + if (score_params->reward % 2 == 1) { reward = 2*score_params->reward; penalty = -2*score_params->penalty; - if (!Xdrop) + if (!Xdrop) Xdrop = 2*MAX(ext_params->gap_x_dropoff, ext_params->gap_x_dropoff_final); gap_open = 2*score_params->gap_open; @@ -210,18 +206,18 @@ s_BlastGreedyAlignMemAlloc(const BlastScoringParameters* score_params, if (score_params->gap_open==0 && score_params->gap_extend==0) { d_diff = (Xdrop+reward/2)/(penalty+reward)+1; - + gamp->last_seq2_off = (Int4**) malloc((max_d + 2) * sizeof(Int4*)); if (gamp->last_seq2_off == NULL) { sfree(gamp); return NULL; } - gamp->last_seq2_off[0] = + gamp->last_seq2_off[0] = (Int4*) malloc((max_d + max_d + 6) * sizeof(Int4) * 2); if (gamp->last_seq2_off[0] == NULL) { #ifdef ERR_POST_EX_DEFINED - ErrPostEx(SEV_WARNING, 0, 0, - "Failed to allocate %ld bytes for greedy alignment", + ErrPostEx(SEV_WARNING, 0, 0, + "Failed to allocate %ld bytes for greedy alignment", (max_d + max_d + 6) * sizeof(Int4) * 2); #endif s_BlastGreedyAlignsFree(gamp); @@ -241,7 +237,7 @@ s_BlastGreedyAlignMemAlloc(const BlastScoringParameters* score_params, gd = BLAST_Gdb3(&Mis_cost, &gap_open, &GE_cost); d_diff = (Xdrop+reward/2)/gd+1; gamp->diag_bounds = (Int4*) calloc(2*(max_d+1+max_cost), sizeof(Int4)); - gamp->last_seq2_off_affine = (SGreedyOffset**) + gamp->last_seq2_off_affine = (SGreedyOffset**) malloc((MAX(max_d, max_cost) + 2) * sizeof(SGreedyOffset*)); if (!gamp->diag_bounds || !gamp->last_seq2_off_affine) { s_BlastGreedyAlignsFree(gamp); @@ -250,7 +246,7 @@ s_BlastGreedyAlignMemAlloc(const BlastScoringParameters* score_params, gamp->last_seq2_off_affine[0] = (SGreedyOffset*) calloc((2*max_d_1 + 6) , sizeof(SGreedyOffset) * (max_cost+1)); for (i = 1; i <= max_cost; i++) - gamp->last_seq2_off_affine[i] = + gamp->last_seq2_off_affine[i] = gamp->last_seq2_off_affine[i-1] + 2*max_d_1 + 6; if (!gamp->last_seq2_off_affine || !gamp->last_seq2_off_affine[0]) { s_BlastGreedyAlignsFree(gamp); @@ -268,7 +264,7 @@ s_BlastGreedyAlignMemAlloc(const BlastScoringParameters* score_params, } /* Documented in blast_gapalign.h */ -BlastGapAlignStruct* +BlastGapAlignStruct* BLAST_GapAlignStructFree(BlastGapAlignStruct* gap_align) { if (!gap_align) @@ -281,6 +277,7 @@ BLAST_GapAlignStructFree(BlastGapAlignStruct* gap_align) s_BlastGreedyAlignsFree(gap_align->greedy_align_mem); GapStateFree(gap_align->state_struct); sfree(gap_align->dp_mem); + JumperGapAlignFree(gap_align->jumper); sfree(gap_align); return NULL; @@ -288,8 +285,8 @@ BLAST_GapAlignStructFree(BlastGapAlignStruct* gap_align) /* Documented in blast_gapalign.h */ Int2 -BLAST_GapAlignStructNew(const BlastScoringParameters* score_params, - const BlastExtensionParameters* ext_params, +BLAST_GapAlignStructNew(const BlastScoringParameters* score_params, + const BlastExtensionParameters* ext_params, Uint4 max_subject_length, BlastScoreBlk* sbp, BlastGapAlignStruct** gap_align_ptr) { @@ -306,25 +303,33 @@ BLAST_GapAlignStructNew(const BlastScoringParameters* score_params, gap_align->sbp = sbp; gap_align->gap_x_dropoff = ext_params->gap_x_dropoff; - - if (ext_params->options->ePrelimGapExt == eDynProgScoreOnly) { - /* allocate structures for ordinary dynamic programming */ - gap_align->dp_mem_alloc = 1000; - gap_align->dp_mem = (BlastGapDP *)malloc(gap_align->dp_mem_alloc * - sizeof(BlastGapDP)); - if (!gap_align->dp_mem) - gap_align = BLAST_GapAlignStructFree(gap_align); + gap_align->max_mismatches = ext_params->options->max_mismatches; + gap_align->mismatch_window = ext_params->options->mismatch_window; + + /* allocate memory either for dynamic programming or jumper */ + if (ext_params->options->ePrelimGapExt != eJumperWithTraceback) { + if (ext_params->options->ePrelimGapExt == eDynProgScoreOnly) { + /* allocate structures for ordinary dynamic programming */ + gap_align->dp_mem_alloc = 1000; + gap_align->dp_mem = (BlastGapDP *)malloc(gap_align->dp_mem_alloc * + sizeof(BlastGapDP)); + if (!gap_align->dp_mem) + gap_align = BLAST_GapAlignStructFree(gap_align); + } + else { + /* allocate structures for greedy dynamic programming */ + max_subject_length = MIN(max_subject_length, MAX_DBSEQ_LEN); + max_subject_length = MIN(GREEDY_MAX_COST, + max_subject_length / GREEDY_MAX_COST_FRACTION + 1); + gap_align->greedy_align_mem = + s_BlastGreedyAlignMemAlloc(score_params, ext_params, + max_subject_length, 0); + if (!gap_align->greedy_align_mem) + gap_align = BLAST_GapAlignStructFree(gap_align); + } } else { - /* allocate structures for greedy dynamic programming */ - max_subject_length = MIN(max_subject_length, MAX_DBSEQ_LEN); - max_subject_length = MIN(GREEDY_MAX_COST, - max_subject_length / GREEDY_MAX_COST_FRACTION + 1); - gap_align->greedy_align_mem = - s_BlastGreedyAlignMemAlloc(score_params, ext_params, - max_subject_length, 0); - if (!gap_align->greedy_align_mem) - gap_align = BLAST_GapAlignStructFree(gap_align); + gap_align->jumper = JumperGapAlignNew(200); } if (!gap_align) @@ -350,22 +355,22 @@ enum { }; Int4 -ALIGN_EX(const Uint1* A, const Uint1* B, Int4 M, Int4 N, Int4* a_offset, - Int4* b_offset, GapPrelimEditBlock *edit_block, - BlastGapAlignStruct* gap_align, - const BlastScoringParameters* score_params, Int4 query_offset, +ALIGN_EX(const Uint1* A, const Uint1* B, Int4 M, Int4 N, Int4* a_offset, + Int4* b_offset, GapPrelimEditBlock *edit_block, + BlastGapAlignStruct* gap_align, + const BlastScoringParameters* score_params, Int4 query_offset, Boolean reversed, Boolean reverse_sequence, Boolean * fence_hit) { - /* See Blast_SemiGappedAlign for more general comments on + /* See Blast_SemiGappedAlign for more general comments on what this code is doing; comments in this function only apply to the traceback computations */ - Int4 i; + Int4 i; Int4 a_index; Int4 b_index, b_size, first_b_index, last_b_index, b_increment; const Uint1* b_ptr; - + BlastGapDP* score_array; Int4 gap_open; @@ -373,16 +378,16 @@ ALIGN_EX(const Uint1* A, const Uint1* B, Int4 M, Int4 N, Int4* a_offset, Int4 gap_open_extend; Int4 x_dropoff; Int4 best_score; - + Int4** matrix = NULL; Int4** pssm = NULL; Int4* matrix_row = NULL; - + Int4 score; Int4 score_gap_row; Int4 score_gap_col; Int4 next_score; - + GapStateArrayStruct* state_struct; Uint1* edit_script_row; Uint1** edit_script; @@ -403,15 +408,15 @@ ALIGN_EX(const Uint1* A, const Uint1* B, Int4 M, Int4 N, Int4* a_offset, gap_extend = score_params->gap_extend; gap_open_extend = gap_open + gap_extend; x_dropoff = gap_align->gap_x_dropoff; - + if (x_dropoff < gap_open_extend) x_dropoff = gap_open_extend; - - if(N <= 0 || M <= 0) + + if(N <= 0 || M <= 0) return 0; - + /* Initialize traceback information. edit_script[] is - a 2-D array which is filled in row by row as the + a 2-D array which is filled in row by row as the dynamic programming takes place */ s_GapPurgeState(gap_align->state_struct); @@ -421,7 +426,7 @@ ALIGN_EX(const Uint1* A, const Uint1* B, Int4 M, Int4 N, Int4* a_offset, separately. edit_script[i] points to the storage reserved for row i, and edit_start_offset[i] gives the offset into the B sequence corresponding to element 0 of edit_script[i]. - + Also make the number of edit script rows grow dynamically */ edit_script_num_rows = 100; @@ -456,18 +461,18 @@ ALIGN_EX(const Uint1* A, const Uint1* B, Int4 M, Int4 N, Int4* a_offset, score_array = gap_align->dp_mem; score_array[0].best = 0; score_array[0].best_gap = -gap_open_extend; - + for (i = 1; i <= N; i++) { - if (score < -x_dropoff) + if (score < -x_dropoff) break; score_array[i].best = score; - score_array[i].best_gap = score - gap_open_extend; + score_array[i].best_gap = score - gap_open_extend; score -= gap_extend; edit_script_row[i] = SCRIPT_GAP_IN_A; } state_struct->used = i + 1; - + b_size = i; best_score = 0; first_b_index = 0; @@ -475,39 +480,39 @@ ALIGN_EX(const Uint1* A, const Uint1* B, Int4 M, Int4 N, Int4* a_offset, b_increment = -1; else b_increment = 1; - + for (a_index = 1; a_index <= M; a_index++) { /* Set up the next row of the edit script; this involves allocating memory for the row, then pointing to it. It is not necessary to allocate space for offsets less - than first_b_index (since the inner loop will never - look at them); - - It is unknown at this point how far to the right the + than first_b_index (since the inner loop will never + look at them); + + It is unknown at this point how far to the right the current traceback row will extend; all that's known for sure is that the previous row fails the X-dropoff test after b_size cells, and that the current row can go at most num_extra_cells beyond that before failing the test */ if (gap_extend > 0) - state_struct = s_GapGetState(&gap_align->state_struct, + state_struct = s_GapGetState(&gap_align->state_struct, b_size - first_b_index + num_extra_cells); else - state_struct = s_GapGetState(&gap_align->state_struct, + state_struct = s_GapGetState(&gap_align->state_struct, N + 3 - first_b_index); if (a_index == edit_script_num_rows) { edit_script_num_rows = edit_script_num_rows * 2; - edit_script = (Uint1 **)realloc(edit_script, + edit_script = (Uint1 **)realloc(edit_script, edit_script_num_rows * sizeof(Uint1 *)); - edit_start_offset = (Int4 *)realloc(edit_start_offset, + edit_start_offset = (Int4 *)realloc(edit_start_offset, edit_script_num_rows * sizeof(Int4)); } - edit_script[a_index] = state_struct->state_array + + edit_script[a_index] = state_struct->state_array + state_struct->used + 1; edit_start_offset[a_index] = first_b_index; @@ -544,17 +549,18 @@ ALIGN_EX(const Uint1* A, const Uint1* B, Int4 M, Int4 N, Int4* a_offset, b_ptr += b_increment; score_gap_col = score_array[b_index].best_gap; - + matrix_index = *b_ptr; - + if (matrix_index == FENCE_SENTRY) { - ASSERT(fence_hit); - *fence_hit = 1; + if (fence_hit) { + *fence_hit = 1; + } break; } - + next_score = score_array[b_index].best + matrix_row[ *b_ptr ]; - + /* script, script_row and script_col contain the actions specified by the dynamic programming. when the inner loop has finished, 'script' con- @@ -601,7 +607,7 @@ ALIGN_EX(const Uint1* A, const Uint1* B, Int4 M, Int4 N, Int4* a_offset, script += script_col; } - if (score_gap_row < (score - gap_open_extend)) + if (score_gap_row < (score - gap_open_extend)) score_gap_row = score - gap_open_extend; else script += script_row; @@ -612,7 +618,7 @@ ALIGN_EX(const Uint1* A, const Uint1* B, Int4 M, Int4 N, Int4* a_offset, score = next_score; edit_script_row[b_index] = script; } - + if (first_b_index == b_size || (fence_hit && *fence_hit)) break; @@ -652,45 +658,45 @@ ALIGN_EX(const Uint1* A, const Uint1* B, Int4 M, Int4 N, Int4* a_offset, b_size++; } } - + /* Pick the optimal path through the now complete - edit_script[][]. This is equivalent to flattening + edit_script[][]. This is equivalent to flattening the 2-D array into a 1-D list of actions. */ a_index = *a_offset; b_index = *b_offset; script = SCRIPT_SUB; - + if (fence_hit && *fence_hit) goto done; - + while (a_index > 0 || b_index > 0) { /* Retrieve the next action to perform. Rows of the traceback array do not necessarily start at offset zero of B, so a correction is needed to point to the correct position */ - - next_script = + + next_script = edit_script[a_index][b_index - edit_start_offset[a_index]]; - + switch(script) { case SCRIPT_GAP_IN_A: script = next_script & SCRIPT_OP_MASK; if (next_script & SCRIPT_EXTEND_GAP_A) script = SCRIPT_GAP_IN_A; break; - + case SCRIPT_GAP_IN_B: script = next_script & SCRIPT_OP_MASK; if (next_script & SCRIPT_EXTEND_GAP_B) script = SCRIPT_GAP_IN_B; break; - + default: script = next_script & SCRIPT_OP_MASK; break; } - + if (script == SCRIPT_GAP_IN_A) { b_index--; } @@ -703,18 +709,18 @@ ALIGN_EX(const Uint1* A, const Uint1* B, Int4 M, Int4 N, Int4* a_offset, } GapPrelimEditBlockAdd(edit_block, (EGapAlignOpType)script, 1); } - + done: sfree(edit_start_offset); sfree(edit_script); return best_score; } -Int4 +Int4 Blast_SemiGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, - Int4* a_offset, Int4* b_offset, Boolean score_only, - GapPrelimEditBlock *edit_block, BlastGapAlignStruct* gap_align, - const BlastScoringParameters* score_params, + Int4* a_offset, Int4* b_offset, Boolean score_only, + GapPrelimEditBlock *edit_block, BlastGapAlignStruct* gap_align, + const BlastScoringParameters* score_params, Int4 query_offset, Boolean reversed, Boolean reverse_sequence, Boolean * fence_hit) { @@ -722,31 +728,31 @@ Blast_SemiGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, Int4 a_index; Int4 b_index, b_size, first_b_index, last_b_index, b_increment; const Uint1* b_ptr; - + BlastGapDP* score_array; Int4 gap_open; /* alignment penalty variables */ Int4 gap_extend; Int4 gap_open_extend; Int4 x_dropoff; - + Int4** matrix = NULL; /* pointers to the score matrix */ Int4** pssm = NULL; Int4* matrix_row = NULL; - + Int4 score; /* score tracking variables */ Int4 score_gap_row; Int4 score_gap_col; Int4 next_score; Int4 best_score; Int4 num_extra_cells; - + if (!score_only) { - return ALIGN_EX(A, B, M, N, a_offset, b_offset, edit_block, gap_align, + return ALIGN_EX(A, B, M, N, a_offset, b_offset, edit_block, gap_align, score_params, query_offset, reversed, reverse_sequence, fence_hit); } - + /* do initialization and sanity-checking */ matrix = gap_align->sbp->matrix->data; @@ -759,13 +765,13 @@ Blast_SemiGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, gap_extend = score_params->gap_extend; gap_open_extend = gap_open + gap_extend; x_dropoff = gap_align->gap_x_dropoff; - + if (x_dropoff < gap_open_extend) x_dropoff = gap_open_extend; - - if(N <= 0 || M <= 0) + + if(N <= 0 || M <= 0) return 0; - + /* Allocate and fill in the auxiliary bookeeping structures. Since A and B could be very large, maintain a window of auxiliary structures only large enough to contain to current @@ -789,17 +795,17 @@ Blast_SemiGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, score = -gap_open_extend; score_array[0].best = 0; score_array[0].best_gap = -gap_open_extend; - + for (i = 1; i <= N; i++) { - if (score < -x_dropoff) + if (score < -x_dropoff) break; score_array[i].best = score; - score_array[i].best_gap = score - gap_open_extend; + score_array[i].best_gap = score - gap_open_extend; score -= gap_extend; } - - /* The inner loop below examines letters of B from + + /* The inner loop below examines letters of B from index 'first_b_index' to 'b_size' */ b_size = i; @@ -809,9 +815,9 @@ Blast_SemiGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, b_increment = -1; else b_increment = 1; - + for (a_index = 1; a_index <= M; a_index++) { - /* pick out the row of the score matrix + /* pick out the row of the score matrix appropriate for A[a_index] */ if (!(gap_align->positionBased)) { @@ -823,7 +829,7 @@ Blast_SemiGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, else { if(reversed || reverse_sequence) matrix_row = pssm[M - a_index]; - else + else matrix_row = pssm[a_index + query_offset]; } @@ -854,11 +860,11 @@ Blast_SemiGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, /* the current best score failed the X-dropoff criterion. Note that this does not stop the inner loop, only forces future iterations to - skip this column of B. + skip this column of B. Also, if the very first letter of B that was tested failed the X dropoff criterion, make - sure future inner loops start one letter to + sure future inner loops start one letter to the right */ if (b_index == first_b_index) @@ -875,7 +881,7 @@ Blast_SemiGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, } /* If starting a gap at this position will improve - the best row, or column, score, update them to + the best row, or column, score, update them to reflect that. */ score_gap_row -= gap_extend; @@ -890,7 +896,7 @@ Blast_SemiGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, } /* Finish aligning if the best scores for all positions - of B will fail the X-dropoff test, i.e. the inner loop + of B will fail the X-dropoff test, i.e. the inner loop bounds have converged to each other */ if (first_b_index == b_size) @@ -918,7 +924,7 @@ Blast_SemiGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, else { /* The inner loop finished without failing the X-dropoff test; initialize extra bookkeeping structures until - the X dropoff test fails or we run out of letters in B. + the X dropoff test fails or we run out of letters in B. The next inner loop will have larger bounds */ while (score_gap_row >= (best_score - x_dropoff) && b_size <= N) { @@ -935,7 +941,7 @@ Blast_SemiGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, b_size++; } } - + return best_score; } @@ -943,12 +949,12 @@ Blast_SemiGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, this many sequence offsets */ #define RESTRICT_SIZE 10 -/** Low level function to perform score-only gapped extension +/** Low level function to perform score-only gapped extension * in one direction. Gaps in one sequence or the other are only * allowed to start at sequence offsets that are a multiple of * RESTRICT_SIZE from the alignment start point. For more details see *
- * Michael Cameron, Hugh E. Williams, Adam Cannane, "Improved 
+ * Michael Cameron, Hugh E. Williams, Adam Cannane, "Improved
  * Gapped Alignment in BLAST". IEEE/ACM Transactions on Computational
  * Biology and Bioinformatics, vol 1 #3 (2004) pp 116-129
  * 
@@ -958,18 +964,18 @@ Blast_SemiGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, * @param N Maximal extension length in subject [in] * @param a_offset Resulting starting offset in query [out] * @param b_offset Resulting starting offset in subject [out] - * @param gap_align Structure holding various information and allocated + * @param gap_align Structure holding various information and allocated * memory for the gapped alignment [in] * @param score_params Parameters related to scoring [in] * @param query_offset The starting offset in query [in] * @param reverse_sequence Do reverse the sequence [in] * @return The best alignment score found. */ -static Int4 +static Int4 s_RestrictedGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, Int4* a_offset, Int4* b_offset, - BlastGapAlignStruct* gap_align, - const BlastScoringParameters* score_params, + BlastGapAlignStruct* gap_align, + const BlastScoringParameters* score_params, Int4 query_offset, Boolean reverse_sequence) { /* see Blast_SemiGappedAlign for general details */ @@ -979,25 +985,25 @@ s_RestrictedGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, Int4 b_index, b_size, first_b_index, last_b_index, b_increment; const Uint1* b_ptr; Int4 b_gap; - + BlastGapDP* score_array; Int4 gap_open; Int4 gap_extend; Int4 gap_open_extend; Int4 x_dropoff; - + Int4** matrix = NULL; Int4** pssm = NULL; Int4* matrix_row = NULL; - + Int4 score; Int4 score_gap_row; Int4 score_gap_col; Int4 next_score; Int4 best_score; Int4 num_extra_cells; - + matrix = gap_align->sbp->matrix->data; if (gap_align->positionBased) { pssm = gap_align->sbp->psi_matrix->pssm->data; @@ -1008,13 +1014,13 @@ s_RestrictedGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, gap_extend = score_params->gap_extend; gap_open_extend = gap_open + gap_extend; x_dropoff = gap_align->gap_x_dropoff; - + if (x_dropoff < gap_open_extend) x_dropoff = gap_open_extend; - - if(N <= 0 || M <= 0) + + if(N <= 0 || M <= 0) return 0; - + if (gap_extend > 0) num_extra_cells = x_dropoff / gap_extend + 3; else @@ -1032,16 +1038,16 @@ s_RestrictedGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, score = -gap_open_extend; score_array[0].best = 0; score_array[0].best_gap = -gap_open_extend; - + for (i = 1; i <= N; i++) { - if (score < -x_dropoff) + if (score < -x_dropoff) break; score_array[i].best = score; - score_array[i].best_gap = score - gap_open_extend; + score_array[i].best_gap = score - gap_open_extend; score -= gap_extend; } - + b_size = i; best_score = 0; first_b_index = 0; @@ -1050,7 +1056,7 @@ s_RestrictedGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, b_increment = -1; else b_increment = 1; - + for (a_index = 1; a_index <= M; a_index++) { if (!(gap_align->positionBased)) { @@ -1062,7 +1068,7 @@ s_RestrictedGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, else { if(reverse_sequence) matrix_row = pssm[M - a_index]; - else + else matrix_row = pssm[a_index + query_offset]; } @@ -1077,8 +1083,8 @@ s_RestrictedGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, /* The double loop that computes the alignment is essentially unchanged from that of Blast_SemiGappedAlign. The only - real difference is that a gap in A or B is not allowed to - start unless the offset of the gap is divisible by + real difference is that a gap in A or B is not allowed to + start unless the offset of the gap is divisible by RESTRICT_SIZE. This allows the ordinary dynamic programming recurrence relations to be simplified */ @@ -1088,7 +1094,7 @@ s_RestrictedGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, or updating score_gap_row */ for (b_index = first_b_index; b_index < b_size; b_index++) { - + b_ptr += b_increment; next_score = score_array[b_index].best + matrix_row[ *b_ptr ]; @@ -1120,10 +1126,10 @@ s_RestrictedGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, b_gap += RESTRICT_SIZE; score_gap_col = score_array[b_index].best_gap; - + if (score < score_gap_col) score = score_gap_col; - + if (best_score - score > x_dropoff) { score_array[b_index].best = MININT; if (b_index == first_b_index) @@ -1136,9 +1142,9 @@ s_RestrictedGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, *a_offset = a_index; *b_offset = b_index; } - + score_gap_col -= gap_extend; - score_array[b_index].best_gap = + score_array[b_index].best_gap = MAX(score - gap_open_extend, score_gap_col); score_array[b_index].best = score; } @@ -1153,7 +1159,7 @@ s_RestrictedGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, /* gap may start in A */ for (b_index = first_b_index; b_index < b_size; b_index++) { - + b_ptr += b_increment; next_score = score_array[b_index].best + matrix_row[ *b_ptr ]; @@ -1164,7 +1170,7 @@ s_RestrictedGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, if (score < score_gap_row) score = score_gap_row; - + if (best_score - score > x_dropoff) { score_array[b_index].best = MININT; if (b_index == first_b_index) @@ -1177,15 +1183,15 @@ s_RestrictedGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, *a_offset = a_index; *b_offset = b_index; } - + score_gap_row -= gap_extend; - score_gap_row = MAX(score - gap_open_extend, + score_gap_row = MAX(score - gap_open_extend, score_gap_row); score_array[b_index].best = score; } } else { - + /* the ordinary case: a gap may start in A or B and the full three-term recurrence must be computed. This happens once every @@ -1193,12 +1199,12 @@ s_RestrictedGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, b_gap += RESTRICT_SIZE; score_gap_col = score_array[b_index].best_gap; - + if (score < score_gap_col) score = score_gap_col; if (score < score_gap_row) score = score_gap_row; - + if (best_score - score > x_dropoff) { score_array[b_index].best = MININT; if (b_index == first_b_index) @@ -1211,12 +1217,12 @@ s_RestrictedGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, *a_offset = a_index; *b_offset = b_index; } - + score_gap_row -= gap_extend; score_gap_col -= gap_extend; - score_array[b_index].best_gap = + score_array[b_index].best_gap = MAX(score - gap_open_extend, score_gap_col); - score_gap_row = MAX(score - gap_open_extend, + score_gap_row = MAX(score - gap_open_extend, score_gap_row); score_array[b_index].best = score; } @@ -1252,11 +1258,11 @@ s_RestrictedGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, else { /* The inner loop finished without failing the X-dropoff test; initialize extra bookkeeping structures until - the X dropoff test fails or we run out of letters in B. + the X dropoff test fails or we run out of letters in B. The next inner loop will have larger bounds. Note that if gaps in A are not allowed for this row, then - score_gap_row is -infinity and the loop below will not + score_gap_row is -infinity and the loop below will not extend the region to explore */ while (score_gap_row >= (best_score - x_dropoff) && b_size <= N) { @@ -1273,14 +1279,14 @@ s_RestrictedGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, b_size++; } } - + return best_score; } /** Editing script operations for out-of-frame traceback */ enum { SCRIPT_AHEAD_ONE_FRAME = 1, /**< Shift 1 frame in sequence A - (gap 2 nucleotides) */ + (gap 2 nucleotides) */ SCRIPT_AHEAD_TWO_FRAMES = 2, /**< Shift 2 frames in sequence A (gap 1 nucleotide) */ SCRIPT_NEXT_IN_FRAME = 3, /**< Shift to next base (substitution) */ @@ -1292,7 +1298,7 @@ enum { }; /** Low level function to perform gapped extension with out-of-frame - * gapping with traceback. + * gapping with traceback. * @param A The query sequence [in] * @param B The subject sequence [in] * @param M Maximal extension length in query [in] @@ -1300,14 +1306,14 @@ enum { * @param a_offset Resulting starting offset in query [out] * @param b_offset Resulting starting offset in subject [out] * @param edit_block Structure to hold generated traceback [out] - * @param gap_align Structure holding various information and allocated + * @param gap_align Structure holding various information and allocated * memory for the gapped alignment [in] * @param score_params Parameters related to scoring [in] * @param query_offset The starting offset in query [in] * @param reversed Has the sequence been reversed? Used for psi-blast [in] * @return The best alignment score found. */ -static Int4 +static Int4 s_OutOfFrameAlignWithTraceback(const Uint1* A, const Uint1* B, Int4 M, Int4 N, Int4* a_offset, Int4* b_offset, GapPrelimEditBlock *edit_block, BlastGapAlignStruct* gap_align, const BlastScoringParameters* score_params, @@ -1316,7 +1322,7 @@ s_OutOfFrameAlignWithTraceback(const Uint1* A, const Uint1* B, Int4 M, Int4 N, Int4 i, increment; /* sequence pointers and indices */ Int4 a_index; Int4 b_index, b_size, first_b_index, last_b_index; - + BlastGapDP* score_array; Int4 gap_open; /* alignment penalty variables */ @@ -1324,23 +1330,23 @@ s_OutOfFrameAlignWithTraceback(const Uint1* A, const Uint1* B, Int4 M, Int4 N, Int4 gap_open_extend; Int4 shift_penalty; Int4 x_dropoff; - + Int4** matrix = NULL; /* pointers to the score matrix */ Int4** pssm = NULL; Int4* matrix_row = NULL; - + Int4 score; /* score tracking variables */ - Int4 score_row1; - Int4 score_row2; + Int4 score_row1; + Int4 score_row2; Int4 score_row3; - Int4 score_gap_col; - Int4 score_col1; - Int4 score_col2; + Int4 score_gap_col; + Int4 score_col1; + Int4 score_col2; Int4 score_col3; - Int4 score_other_frame1; - Int4 score_other_frame2; + Int4 score_other_frame1; + Int4 score_other_frame2; Int4 best_score; - + GapStateArrayStruct* state_struct; Uint1** edit_script; Uint1* edit_script_row; @@ -1363,15 +1369,15 @@ s_OutOfFrameAlignWithTraceback(const Uint1* A, const Uint1* B, Int4 M, Int4 N, gap_open_extend = gap_open + gap_extend; shift_penalty = score_params->shift_pen; x_dropoff = gap_align->gap_x_dropoff; - + if (x_dropoff < gap_open_extend) x_dropoff = gap_open_extend; - - if(N <= 0 || M <= 0) + + if(N <= 0 || M <= 0) return 0; - + /* Initialize traceback information. edit_script[] is - a 2-D array which is filled in row by row as the + a 2-D array which is filled in row by row as the dynamic programming takes place */ s_GapPurgeState(gap_align->state_struct); @@ -1380,8 +1386,8 @@ s_OutOfFrameAlignWithTraceback(const Uint1* A, const Uint1* B, Int4 M, Int4 N, MxN. To save on memory, each row of the array is allocated separately. edit_script[i] points to the storage reserved for row i, and edit_start_offset[i] gives the offset into - the B sequence corresponding to element 0 of edit_script[i] - + the B sequence corresponding to element 0 of edit_script[i] + Also make the number of edit script rows grow dynamically */ edit_script_num_rows = 100; @@ -1390,8 +1396,8 @@ s_OutOfFrameAlignWithTraceback(const Uint1* A, const Uint1* B, Int4 M, Int4 N, /* allocate storage for the first row of the traceback array. Because row elements correspond to gaps in A, - the alignment can only go at most x_dropoff/gap_extend - positions, in all three frames, before failing the + the alignment can only go at most x_dropoff/gap_extend + positions, in all three frames, before failing the X dropoff criterion */ if (gap_extend > 0) @@ -1417,10 +1423,10 @@ s_OutOfFrameAlignWithTraceback(const Uint1* A, const Uint1* B, Int4 M, Int4 N, score = -gap_open_extend; score_array[0].best = 0; score_array[0].best_gap = -gap_open_extend; - + for (i = 3; i <= N + 2; i += 3) { score_array[i].best = score; - score_array[i].best_gap = score - gap_open_extend; + score_array[i].best_gap = score - gap_open_extend; edit_script_row[i] = SCRIPT_GAP_IN_B; score_array[i-1].best = MININT; @@ -1431,12 +1437,12 @@ s_OutOfFrameAlignWithTraceback(const Uint1* A, const Uint1* B, Int4 M, Int4 N, score_array[i-2].best_gap = MININT; edit_script_row[i-2] = SCRIPT_GAP_IN_B; - if (score < -x_dropoff) + if (score < -x_dropoff) break; score -= gap_extend; } - - /* The inner loop below examines letters of B from + + /* The inner loop below examines letters of B from index 'first_b_index' to 'b_size' */ score_array[i].best = MININT; @@ -1454,39 +1460,39 @@ s_OutOfFrameAlignWithTraceback(const Uint1* A, const Uint1* B, Int4 M, Int4 N, B -= 2; increment = 1; } - + for (a_index = 1; a_index <= M; a_index++) { /* Set up the next row of the edit script; this involves allocating memory for the row, then pointing to it. It is not necessary to allocate space for offsets less - than first_b_index (since the inner loop will never - look at them). + than first_b_index (since the inner loop will never + look at them). - It is unknown at this point how far to the right the + It is unknown at this point how far to the right the current traceback row will extend; all that's known for sure is that the previous row fails the X-dropoff test after b_size cells, and that the current row can go at most num_extra_cells beyond that before failing the test */ if (gap_extend > 0) - state_struct = s_GapGetState(&gap_align->state_struct, + state_struct = s_GapGetState(&gap_align->state_struct, b_size - first_b_index + num_extra_cells); else - state_struct = s_GapGetState(&gap_align->state_struct, + state_struct = s_GapGetState(&gap_align->state_struct, N + 5 - first_b_index); if (a_index == edit_script_num_rows) { edit_script_num_rows = edit_script_num_rows * 2; - edit_script = (Uint1 **)realloc(edit_script, + edit_script = (Uint1 **)realloc(edit_script, edit_script_num_rows * sizeof(Uint1 *)); - edit_start_offset = (Int4 *)realloc(edit_start_offset, + edit_start_offset = (Int4 *)realloc(edit_start_offset, edit_script_num_rows * sizeof(Int4)); } - edit_script[a_index] = state_struct->state_array + + edit_script[a_index] = state_struct->state_array + state_struct->used + 1; edit_start_offset[a_index] = first_b_index; @@ -1502,20 +1508,20 @@ s_OutOfFrameAlignWithTraceback(const Uint1* A, const Uint1* B, Int4 M, Int4 N, else { if(reversed) matrix_row = pssm[M - a_index]; - else + else matrix_row = pssm[a_index + query_offset]; } score = MININT; - score_row1 = MININT; - score_row2 = MININT; + score_row1 = MININT; + score_row2 = MININT; score_row3 = MININT; - score_gap_col = MININT; - score_col1 = MININT; - score_col2 = MININT; + score_gap_col = MININT; + score_col1 = MININT; + score_col2 = MININT; score_col3 = MININT; - score_other_frame1 = MININT; - score_other_frame2 = MININT; + score_other_frame1 = MININT; + score_other_frame2 = MININT; last_b_index = first_b_index; b_index = first_b_index; @@ -1560,7 +1566,7 @@ s_OutOfFrameAlignWithTraceback(const Uint1* A, const Uint1* B, Int4 M, Int4 N, } if (best_score - score > x_dropoff) { - if (first_b_index == b_index) + if (first_b_index == b_index) first_b_index = b_index + 1; else score_array[b_index].best = MININT; @@ -1574,7 +1580,7 @@ s_OutOfFrameAlignWithTraceback(const Uint1* A, const Uint1* B, Int4 M, Int4 N, } else { if (best_score - score > x_dropoff) { - if (first_b_index == b_index) + if (first_b_index == b_index) first_b_index = b_index + 1; else score_array[b_index].best = MININT; @@ -1642,7 +1648,7 @@ s_OutOfFrameAlignWithTraceback(const Uint1* A, const Uint1* B, Int4 M, Int4 N, if (score < MAX(score_gap_col, score_row2)) { score = MAX(score_gap_col, score_row2); if (best_score - score > x_dropoff) { - if (first_b_index == b_index) + if (first_b_index == b_index) first_b_index = b_index + 1; else score_array[b_index].best = MININT; @@ -1650,7 +1656,7 @@ s_OutOfFrameAlignWithTraceback(const Uint1* A, const Uint1* B, Int4 M, Int4 N, else { if (score == score_gap_col) script = SCRIPT_OOF_OPEN_GAP | SCRIPT_GAP_IN_A; - else + else script = SCRIPT_OOF_OPEN_GAP | SCRIPT_GAP_IN_B; last_b_index = b_index; @@ -1661,7 +1667,7 @@ s_OutOfFrameAlignWithTraceback(const Uint1* A, const Uint1* B, Int4 M, Int4 N, } else { if (best_score - score > x_dropoff) { - if (first_b_index == b_index) + if (first_b_index == b_index) first_b_index = b_index + 1; else score_array[b_index].best = MININT; @@ -1729,7 +1735,7 @@ s_OutOfFrameAlignWithTraceback(const Uint1* A, const Uint1* B, Int4 M, Int4 N, if (score < MAX(score_gap_col, score_row3)) { score = MAX(score_gap_col, score_row3); if (best_score - score > x_dropoff) { - if (first_b_index == b_index) + if (first_b_index == b_index) first_b_index = b_index + 1; else score_array[b_index].best = MININT; @@ -1737,7 +1743,7 @@ s_OutOfFrameAlignWithTraceback(const Uint1* A, const Uint1* B, Int4 M, Int4 N, else { if (score == score_gap_col) script = SCRIPT_OOF_OPEN_GAP | SCRIPT_GAP_IN_A; - else + else script = SCRIPT_OOF_OPEN_GAP | SCRIPT_GAP_IN_B; last_b_index = b_index; @@ -1748,7 +1754,7 @@ s_OutOfFrameAlignWithTraceback(const Uint1* A, const Uint1* B, Int4 M, Int4 N, } else { if (best_score - score > x_dropoff) { - if (first_b_index == b_index) + if (first_b_index == b_index) first_b_index = b_index + 1; else score_array[b_index].best = MININT; @@ -1780,9 +1786,9 @@ s_OutOfFrameAlignWithTraceback(const Uint1* A, const Uint1* B, Int4 M, Int4 N, } edit_script_row[b_index++] = script; } - + /* Finish aligning if the best scores for all positions - of B will fail the X-dropoff test, i.e. the inner loop + of B will fail the X-dropoff test, i.e. the inner loop bounds have converged to each other */ if (first_b_index == b_size) @@ -1810,9 +1816,9 @@ s_OutOfFrameAlignWithTraceback(const Uint1* A, const Uint1* B, Int4 M, Int4 N, else { /* The inner loop finished without failing the X-dropoff test; initialize extra bookkeeping structures until - the X dropoff test fails or we run out of letters in B. - The next inner loop will have larger bounds. - + the X dropoff test fails or we run out of letters in B. + The next inner loop will have larger bounds. + Keep initializing extra structures until the X dropoff test fails in all frames for this row */ @@ -1823,19 +1829,19 @@ s_OutOfFrameAlignWithTraceback(const Uint1* A, const Uint1* B, Int4 M, Int4 N, score_array[b_size].best = score_row1; score_array[b_size].best_gap = score_row1 - gap_open_extend; score_row1 -= gap_extend; - edit_script_row[b_size] = SCRIPT_OOF_OPEN_GAP | + edit_script_row[b_size] = SCRIPT_OOF_OPEN_GAP | SCRIPT_GAP_IN_B; score_array[b_size+1].best = score_row2; score_array[b_size+1].best_gap = score_row2 - gap_open_extend; score_row2 -= gap_extend; - edit_script_row[b_size+1] = SCRIPT_OOF_OPEN_GAP | + edit_script_row[b_size+1] = SCRIPT_OOF_OPEN_GAP | SCRIPT_GAP_IN_B; score_array[b_size+2].best = score_row3; score_array[b_size+2].best_gap = score_row3 - gap_open_extend; score_row3 -= gap_extend; - edit_script_row[b_size+2] = SCRIPT_OOF_OPEN_GAP | + edit_script_row[b_size+2] = SCRIPT_OOF_OPEN_GAP | SCRIPT_GAP_IN_B; b_size += 3; score -= gap_extend; @@ -1868,7 +1874,7 @@ s_OutOfFrameAlignWithTraceback(const Uint1* A, const Uint1* B, Int4 M, Int4 N, at offset zero of B, so a correction is needed to point to the correct position */ - next_script = + next_script = edit_script[a_index][b_index - edit_start_offset[a_index]]; switch (script) { @@ -1916,56 +1922,56 @@ s_OutOfFrameAlignWithTraceback(const Uint1* A, const Uint1* B, Int4 M, Int4 N, * @param b_offset Resulting starting offset in subject [out] * @param score_only Only find the score, without saving traceback [in] * @param edit_block Structure to hold generated traceback [out] - * @param gap_align Structure holding various information and allocated + * @param gap_align Structure holding various information and allocated * memory for the gapped alignment [in] * @param score_params Parameters related to scoring [in] * @param query_offset The starting offset in query [in] * @param reversed Has the sequence been reversed? Used for psi-blast [in] * @return The best alignment score found. */ -static Int4 +static Int4 s_OutOfFrameGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, Int4* a_offset, Int4* b_offset, Boolean score_only, - GapPrelimEditBlock *edit_block, BlastGapAlignStruct* gap_align, + GapPrelimEditBlock *edit_block, BlastGapAlignStruct* gap_align, const BlastScoringParameters* score_params, Int4 query_offset, Boolean reversed) { Int4 i, increment; /* sequence pointers and indices */ Int4 a_index; Int4 b_index, b_size, first_b_index, last_b_index; - + Int4 gap_open; /* alignment penalty variables */ Int4 gap_extend; Int4 gap_open_extend; Int4 shift_penalty; Int4 x_dropoff; - + BlastGapDP* score_array; Int4 num_extra_cells; Int4** matrix = NULL; /* pointers to the score matrix */ Int4** pssm = NULL; Int4* matrix_row = NULL; - + Int4 score; /* score tracking variables */ - Int4 score_row1; - Int4 score_row2; + Int4 score_row1; + Int4 score_row2; Int4 score_row3; - Int4 score_gap_col; - Int4 score_col1; - Int4 score_col2; + Int4 score_gap_col; + Int4 score_col1; + Int4 score_col2; Int4 score_col3; - Int4 score_other_frame1; - Int4 score_other_frame2; + Int4 score_other_frame1; + Int4 score_other_frame2; Int4 best_score; - + if (!score_only) { - return s_OutOfFrameAlignWithTraceback(A, B, M, N, a_offset, b_offset, - edit_block, gap_align, - score_params, query_offset, + return s_OutOfFrameAlignWithTraceback(A, B, M, N, a_offset, b_offset, + edit_block, gap_align, + score_params, query_offset, reversed); } - + /* do initialization and sanity-checking */ matrix = gap_align->sbp->matrix->data; @@ -1979,13 +1985,13 @@ s_OutOfFrameGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, gap_open_extend = gap_open + gap_extend; shift_penalty = score_params->shift_pen; x_dropoff = gap_align->gap_x_dropoff; - + if (x_dropoff < gap_open_extend) x_dropoff = gap_open_extend; - - if(N <= 0 || M <= 0) + + if(N <= 0 || M <= 0) return 0; - + /* Allocate and fill in the auxiliary bookeeping structures. Since A and B could be very large, maintain a window of auxiliary structures only large enough to contain to current @@ -2009,20 +2015,20 @@ s_OutOfFrameGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, score = -gap_open_extend; score_array[0].best = 0; score_array[0].best_gap = -gap_open_extend; - + for (i = 3; i <= N + 2; i += 3) { score_array[i].best = score; - score_array[i].best_gap = score - gap_open_extend; + score_array[i].best_gap = score - gap_open_extend; score_array[i-1].best = MININT; score_array[i-1].best_gap = MININT; score_array[i-2].best = MININT; score_array[i-2].best_gap = MININT; - if (score < -x_dropoff) + if (score < -x_dropoff) break; score -= gap_extend; } - - /* The inner loop below examines letters of B from + + /* The inner loop below examines letters of B from index 'first_b_index' to 'b_size' */ b_size = i - 2; @@ -2039,10 +2045,10 @@ s_OutOfFrameGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, B -= 2; increment = 1; } - + for (a_index = 1; a_index <= M; a_index++) { - /* pick out the row of the score matrix + /* pick out the row of the score matrix appropriate for A[a_index] */ if (!(gap_align->positionBased)) { @@ -2051,21 +2057,21 @@ s_OutOfFrameGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, else { if(reversed) matrix_row = pssm[M - a_index]; - else + else matrix_row = pssm[a_index + query_offset]; } /* initialize running-score variables */ score = MININT; - score_row1 = MININT; - score_row2 = MININT; + score_row1 = MININT; + score_row2 = MININT; score_row3 = MININT; - score_gap_col = MININT; - score_col1 = MININT; - score_col2 = MININT; + score_gap_col = MININT; + score_col1 = MININT; + score_col2 = MININT; score_col3 = MININT; - score_other_frame1 = MININT; - score_other_frame2 = MININT; + score_other_frame1 = MININT; + score_other_frame2 = MININT; last_b_index = first_b_index; b_index = first_b_index; @@ -2075,7 +2081,7 @@ s_OutOfFrameGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, /* Pick the best score among all frames */ score = MAX(score_other_frame1, score_other_frame2) - shift_penalty; - score = MAX(score, score_col1) + + score = MAX(score, score_col1) + matrix_row[ B[ b_index * increment ] ]; score_other_frame1 = MAX(score_col1, score_array[b_index].best); score_col1 = score_array[b_index].best; @@ -2091,14 +2097,14 @@ s_OutOfFrameGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, /* the current best score failed the X-dropoff criterion. Note that this does not stop the inner loop, only forces future iterations to - skip this column of B. - + skip this column of B. + Also, if the very first letter of B that was tested failed the X dropoff criterion, make - sure future inner loops start one letter to + sure future inner loops start one letter to the right */ - if (first_b_index == b_index) + if (first_b_index == b_index) first_b_index = b_index + 1; else score_array[b_index].best = MININT; @@ -2117,7 +2123,7 @@ s_OutOfFrameGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, /* the current best score failed the X-dropoff criterion. */ - if (first_b_index == b_index) + if (first_b_index == b_index) first_b_index = b_index + 1; else score_array[b_index].best = MININT; @@ -2141,7 +2147,7 @@ s_OutOfFrameGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, score -= gap_open_extend; score_row1 -= gap_extend; score_row1 = MAX(score, score_row1); - score_array[b_index].best_gap = MAX(score, + score_array[b_index].best_gap = MAX(score, score_gap_col - gap_extend); } } @@ -2165,7 +2171,7 @@ s_OutOfFrameGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, is the updating of the other_frame best scores */ score = MAX(score_other_frame1, score_other_frame2) - shift_penalty; - score = MAX(score, score_col2) + + score = MAX(score, score_col2) + matrix_row[ B[ b_index * increment ] ]; score_other_frame2 = MAX(score_col2, score_array[b_index].best); score_col2 = score_array[b_index].best; @@ -2174,7 +2180,7 @@ s_OutOfFrameGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, if (score < MAX(score_gap_col, score_row2)) { score = MAX(score_gap_col, score_row2); if (best_score - score > x_dropoff) { - if (first_b_index == b_index) + if (first_b_index == b_index) first_b_index = b_index + 1; else score_array[b_index].best = MININT; @@ -2188,7 +2194,7 @@ s_OutOfFrameGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, } else { if (best_score - score > x_dropoff) { - if (first_b_index == b_index) + if (first_b_index == b_index) first_b_index = b_index + 1; else score_array[b_index].best = MININT; @@ -2204,7 +2210,7 @@ s_OutOfFrameGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, score -= gap_open_extend; score_row2 -= gap_extend; score_row2 = MAX(score, score_row2); - score_array[b_index].best_gap = MAX(score, + score_array[b_index].best_gap = MAX(score, score_gap_col - gap_extend); } } @@ -2220,7 +2226,7 @@ s_OutOfFrameGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, /* FRAME 2 */ score = MAX(score_other_frame1, score_other_frame2) - shift_penalty; - score = MAX(score, score_col3) + + score = MAX(score, score_col3) + matrix_row[ B[ b_index * increment ] ]; score_other_frame1 = score_other_frame2; score_other_frame2 = MAX(score_col3, score_array[b_index].best); @@ -2230,7 +2236,7 @@ s_OutOfFrameGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, if (score < MAX(score_gap_col, score_row3)) { score = MAX(score_gap_col, score_row3); if (best_score - score > x_dropoff) { - if (first_b_index == b_index) + if (first_b_index == b_index) first_b_index = b_index + 1; else score_array[b_index].best = MININT; @@ -2244,7 +2250,7 @@ s_OutOfFrameGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, } else { if (best_score - score > x_dropoff) { - if (first_b_index == b_index) + if (first_b_index == b_index) first_b_index = b_index + 1; else score_array[b_index].best = MININT; @@ -2260,15 +2266,15 @@ s_OutOfFrameGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, score -= gap_open_extend; score_row3 -= gap_extend; score_row3 = MAX(score, score_row3); - score_array[b_index].best_gap = MAX(score, + score_array[b_index].best_gap = MAX(score, score_gap_col - gap_extend); } } b_index++; } - + /* Finish aligning if the best scores for all positions - of B will fail the X-dropoff test, i.e. the inner loop + of B will fail the X-dropoff test, i.e. the inner loop bounds have converged to each other */ if (first_b_index == b_size) @@ -2296,9 +2302,9 @@ s_OutOfFrameGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, else { /* The inner loop finished without failing the X-dropoff test; initialize extra bookkeeping structures until - the X dropoff test fails or we run out of letters in B. - The next inner loop will have larger bounds. - + the X dropoff test fails or we run out of letters in B. + The next inner loop will have larger bounds. + Keep initializing extra structures until the X dropoff test fails in all frames for this row */ @@ -2346,14 +2352,14 @@ s_OutOfFrameGappedAlign(const Uint1* A, const Uint1* B, Int4 M, Int4 N, * @param init_hsp Initial HSP [in] */ static NCBI_INLINE Int4 -s_GetUngappedHSPContext(const BlastQueryInfo* query_info, +s_GetUngappedHSPContext(const BlastQueryInfo* query_info, const BlastInitHSP* init_hsp) { return BSearchContextInfo(init_hsp->offsets.qs_offsets.q_off, query_info); } /** Adjust the HSP offsets in the initial ungapped HSP structure given the - * query start + * query start * @param init_hsp Initial HSP [in|out] * @param query_start Starting offset of the query sequence in the query info * structure [in] @@ -2390,7 +2396,7 @@ s_SetUpLocalBlastSequenceBlk(const BLAST_SequenceBlk* concatenated_query, together in a special sequence. */ Int4 query_end_pt = 0; Int4 mixed_frame_context = context - context % CODON_LENGTH; - + *query_start = query_info->contexts[mixed_frame_context].query_offset; query_end_pt = query_info->contexts[mixed_frame_context+CODON_LENGTH-1].query_offset + @@ -2412,19 +2418,19 @@ s_SetUpLocalBlastSequenceBlk(const BLAST_SequenceBlk* concatenated_query, * the concatenated sequence and retrieve relevant portions of the query * sequence data. * @param query Query sequence block [in] - * @param query_info Query information structure, including context offsets + * @param query_info Query information structure, including context offsets * array [in] * @param init_hsp Initial HSP, this will be modified to hold the adjusted * offsets [in] [out] - * @param query_out query sequence block with modified sequence + * @param query_out query sequence block with modified sequence * pointer and sequence length [out] * @param context Which context this HSP belongs to? [out] */ -static void -s_AdjustHspOffsetsAndGetQueryData(const BLAST_SequenceBlk* query, - const BlastQueryInfo* query_info, - BlastInitHSP* init_hsp, - BLAST_SequenceBlk* query_out, +static void +s_AdjustHspOffsetsAndGetQueryData(const BLAST_SequenceBlk* query, + const BlastQueryInfo* query_info, + BlastInitHSP* init_hsp, + BLAST_SequenceBlk* query_out, Int4* context) { Int4 query_start = 0; @@ -2435,7 +2441,7 @@ s_AdjustHspOffsetsAndGetQueryData(const BLAST_SequenceBlk* query, ASSERT(init_hsp); ASSERT(context); - ASSERT(init_hsp->ungapped_data == NULL || + ASSERT(init_hsp->ungapped_data == NULL || init_hsp->ungapped_data->q_start >= 0); *context = s_GetUngappedHSPContext(query_info, init_hsp); s_SetUpLocalBlastSequenceBlk(query, query_info, *context, @@ -2470,14 +2476,14 @@ Blast_PrelimEditBlockToGapEditScript (GapPrelimEditBlock* rev_prelim_tback, return NULL; /* The fwd_prelim_tback script will get reversed here as the traceback started from the highest scoring point - and worked backwards. The rev_prelim_tback script does NOT get reversed. Since it was reversed when the + and worked backwards. The rev_prelim_tback script does NOT get reversed. Since it was reversed when the traceback was produced it's already "forward" */ if (fwd_prelim_tback->num_ops > 0 && rev_prelim_tback->num_ops > 0 && - fwd_prelim_tback->edit_ops[(fwd_prelim_tback->num_ops)-1].op_type == + fwd_prelim_tback->edit_ops[(fwd_prelim_tback->num_ops)-1].op_type == rev_prelim_tback->edit_ops[(rev_prelim_tback->num_ops)-1].op_type) merge_ops = TRUE; - + size = fwd_prelim_tback->num_ops+rev_prelim_tback->num_ops; if (merge_ops) size--; @@ -2514,7 +2520,7 @@ Blast_PrelimEditBlockToGapEditScript (GapPrelimEditBlock* rev_prelim_tback, return esp; } -/** Fills the BlastGapAlignStruct structure with the results +/** Fills the BlastGapAlignStruct structure with the results * of a greedy gapped extension. * @param gap_align the initialized gapped alignment structure [in] [out] * @param q_start The starting offset in query [in] @@ -2527,9 +2533,9 @@ Blast_PrelimEditBlockToGapEditScript (GapPrelimEditBlock* rev_prelim_tback, * @param esp The edit script containing the traceback information [in] */ static Int2 -s_BlastGreedyGapAlignStructFill(BlastGapAlignStruct* gap_align, - Int4 q_start, Int4 s_start, - Int4 q_end, Int4 s_end, +s_BlastGreedyGapAlignStructFill(BlastGapAlignStruct* gap_align, + Int4 q_start, Int4 s_start, + Int4 q_end, Int4 s_end, Int4 q_seed_start, Int4 s_seed_start, Int4 score, GapEditScript* esp) { @@ -2675,8 +2681,8 @@ static void s_ReduceGaps(GapEditScript* esp, const Uint1 *q, const Uint1 *s, q += esp->num[i]; s += esp->num[i]; continue; - } - if (i>1 && esp->op_type[i] != esp->op_type[i-2] + } + if (i>1 && esp->op_type[i] != esp->op_type[i-2] && esp->num[i-2] > 0) { d = esp->num[i] + esp->num[i-1] + esp->num[i-2]; if (d == 3) { @@ -2729,10 +2735,10 @@ static void s_ReduceGaps(GapEditScript* esp, const Uint1 *q, const Uint1 *s, s_RebuildEditScript(esp); } -Int2 -BLAST_GreedyGappedAlignment(const Uint1* query, const Uint1* subject, +Int2 +BLAST_GreedyGappedAlignment(const Uint1* query, const Uint1* subject, Int4 query_length, Int4 subject_length, BlastGapAlignStruct* gap_align, - const BlastScoringParameters* score_params, + const BlastScoringParameters* score_params, Int4 q_off, Int4 s_off, Boolean compressed_subject, Boolean do_traceback, Boolean * fence_hit) { @@ -2750,10 +2756,10 @@ BLAST_GreedyGappedAlignment(const Uint1* query, const Uint1* subject, GapEditScript* esp = NULL; Int4 q_seed_start = q_off; Int4 s_seed_start = s_off; - + q_avail = query_length - q_off; s_avail = subject_length - s_off; - + q = query + q_off; if (!compressed_subject) { s = subject + s_off; @@ -2765,21 +2771,21 @@ BLAST_GreedyGappedAlignment(const Uint1* query, const Uint1* subject, } X = gap_align->gap_x_dropoff; - + if (do_traceback) { fwd_prelim_tback = gap_align->fwd_prelim_tback; rev_prelim_tback = gap_align->rev_prelim_tback; GapPrelimEditBlockReset(fwd_prelim_tback); GapPrelimEditBlockReset(rev_prelim_tback); } - + /* extend to the right */ while (TRUE) { Int4 new_dist, xdrop; score = BLAST_AffineGreedyAlign(q, q_avail, s, s_avail, FALSE, X, - score_params->reward, -score_params->penalty, + score_params->reward, -score_params->penalty, score_params->gap_open, score_params->gap_extend, - &q_ext_r, &s_ext_r, gap_align->greedy_align_mem, + &q_ext_r, &s_ext_r, gap_align->greedy_align_mem, fwd_prelim_tback, rem, fence_hit, &fwd_start_point); if (score >=0) break; @@ -2787,7 +2793,7 @@ BLAST_GreedyGappedAlignment(const Uint1* query, const Uint1* subject, new_dist = gap_align->greedy_align_mem->max_dist * 2; xdrop = gap_align->greedy_align_mem->xdrop; s_BlastGreedyAlignsFree(gap_align->greedy_align_mem); - gap_align->greedy_align_mem = + gap_align->greedy_align_mem = s_BlastGreedyAlignMemAlloc(score_params, NULL, new_dist, xdrop); if (!gap_align->greedy_align_mem) { @@ -2802,11 +2808,11 @@ BLAST_GreedyGappedAlignment(const Uint1* query, const Uint1* subject, /* extend to the left */ while (TRUE) { Int4 new_dist, xdrop, score1; - score1 = BLAST_AffineGreedyAlign(query, q_off, - subject, s_off, TRUE, X, - score_params->reward, -score_params->penalty, - score_params->gap_open, score_params->gap_extend, - &q_ext_l, &s_ext_l, gap_align->greedy_align_mem, + score1 = BLAST_AffineGreedyAlign(query, q_off, + subject, s_off, TRUE, X, + score_params->reward, -score_params->penalty, + score_params->gap_open, score_params->gap_extend, + &q_ext_l, &s_ext_l, gap_align->greedy_align_mem, rev_prelim_tback, rem, fence_hit, &rev_start_point); if (score1 >=0) { score += score1; @@ -2817,7 +2823,7 @@ BLAST_GreedyGappedAlignment(const Uint1* query, const Uint1* subject, new_dist = gap_align->greedy_align_mem->max_dist * 2; xdrop = gap_align->greedy_align_mem->xdrop; s_BlastGreedyAlignsFree(gap_align->greedy_align_mem); - gap_align->greedy_align_mem = + gap_align->greedy_align_mem = s_BlastGreedyAlignMemAlloc(score_params, NULL, new_dist, xdrop); if (!gap_align->greedy_align_mem) { @@ -2826,18 +2832,18 @@ BLAST_GreedyGappedAlignment(const Uint1* query, const Uint1* subject, } } - /* In basic case the greedy algorithm returns number of + /* In basic case the greedy algorithm returns number of differences, hence we need to convert it to score */ if (score_params->gap_open==0 && score_params->gap_extend==0) { - score = - (q_ext_r + s_ext_r + q_ext_l + s_ext_l)*score_params->reward/2 - + score = + (q_ext_r + s_ext_r + q_ext_l + s_ext_l)*score_params->reward/2 - score*(score_params->reward - score_params->penalty); } else if (score_params->reward % 2 == 1) { score /= 2; } if (do_traceback) { - esp = Blast_PrelimEditBlockToGapEditScript(rev_prelim_tback, + esp = Blast_PrelimEditBlockToGapEditScript(rev_prelim_tback, fwd_prelim_tback); /* check for possible gap elimination */ ASSERT(!compressed_subject); @@ -2864,7 +2870,7 @@ BLAST_GreedyGappedAlignment(const Uint1* query, const Uint1* subject, if (q_seed_start_r < q_box_r && s_seed_start_r < s_box_r) { valid_seed_len_r = MIN(q_box_r - q_seed_start_r, s_box_r - s_seed_start_r); - valid_seed_len_r = MIN(valid_seed_len_r, + valid_seed_len_r = MIN(valid_seed_len_r, fwd_start_point.match_length) / 2; } else { q_seed_start_r = q_off; @@ -2874,7 +2880,7 @@ BLAST_GreedyGappedAlignment(const Uint1* query, const Uint1* subject, if (q_seed_start_l > q_box_l && s_seed_start_l > s_box_l) { valid_seed_len_l = MIN(q_seed_start_l - q_box_l, s_seed_start_l - s_box_l); - valid_seed_len_l = MIN(valid_seed_len_l, + valid_seed_len_l = MIN(valid_seed_len_l, rev_start_point.match_length) / 2; } else { q_seed_start_l = q_off; @@ -2890,16 +2896,16 @@ BLAST_GreedyGappedAlignment(const Uint1* query, const Uint1* subject, s_seed_start = s_seed_start_l - valid_seed_len_l; } } - - s_BlastGreedyGapAlignStructFill(gap_align, - q_off-q_ext_l, s_off-s_ext_l, - q_off+q_ext_r, s_off+s_ext_r, + + s_BlastGreedyGapAlignStructFill(gap_align, + q_off-q_ext_l, s_off-s_ext_l, + q_off+q_ext_r, s_off+s_ext_r, q_seed_start, s_seed_start, score, esp); return 0; } -/** Performs dynamic programming style gapped extension, given an initial +/** Performs dynamic programming style gapped extension, given an initial * HSP (offset pair), two sequence blocks and scoring and extension options. * Note: traceback is not done in this function. * @param query_blk The query sequence [in] @@ -2908,27 +2914,27 @@ BLAST_GreedyGappedAlignment(const Uint1* query, const Uint1* subject, * @param score_params Parameters related to scoring [in] * @param init_hsp The initial HSP that needs to be extended [in] */ -static Int2 -s_BlastDynProgNtGappedAlignment(BLAST_SequenceBlk* query_blk, - BLAST_SequenceBlk* subject_blk, BlastGapAlignStruct* gap_align, +static Int2 +s_BlastDynProgNtGappedAlignment(BLAST_SequenceBlk* query_blk, + BLAST_SequenceBlk* subject_blk, BlastGapAlignStruct* gap_align, const BlastScoringParameters* score_params, BlastInitHSP* init_hsp) { - Int4 q_length, s_length; + Int4 q_length, s_length; Int4 private_q_start, private_s_start; Int4 score_right = 0, score_left = 0; Uint1 offset_adjustment; Uint1* query = query_blk->sequence; Uint1* subject = subject_blk->sequence; - /* If subject offset is not at the start of a full byte, + /* If subject offset is not at the start of a full byte, s_BlastAlignPackedNucl won't work, so shift the alignment start - to the next multiple of 4 subject letters. Note that the - shift amount is always nonzero, so a left extension always happens - (and has a few presumed exact matches to start with). In the case - of the smallest ungapped alignment (4 nucleotides), this can + to the next multiple of 4 subject letters. Note that the + shift amount is always nonzero, so a left extension always happens + (and has a few presumed exact matches to start with). In the case + of the smallest ungapped alignment (4 nucleotides), this can conceivably put the start point at the end of one sequence */ - offset_adjustment = COMPRESSION_RATIO - + offset_adjustment = COMPRESSION_RATIO - (init_hsp->offsets.qs_offsets.s_off % COMPRESSION_RATIO); q_length = init_hsp->offsets.qs_offsets.q_off + offset_adjustment; s_length = init_hsp->offsets.qs_offsets.s_off + offset_adjustment; @@ -2942,24 +2948,24 @@ s_BlastDynProgNtGappedAlignment(BLAST_SequenceBlk* query_blk, } /* perform extension to left */ - score_left = s_BlastAlignPackedNucl(query, subject, q_length, s_length, - &private_q_start, &private_s_start, gap_align, + score_left = s_BlastAlignPackedNucl(query, subject, q_length, s_length, + &private_q_start, &private_s_start, gap_align, score_params, TRUE); - if (score_left < 0) + if (score_left < 0) return -1; gap_align->query_start = q_length - private_q_start; gap_align->subject_start = s_length - private_s_start; /* perform extension to right */ - if (q_length < query_blk->length && + if (q_length < query_blk->length && s_length < subject_blk->length) { - score_right = s_BlastAlignPackedNucl(query+q_length-1, - subject+(s_length+3)/COMPRESSION_RATIO - 1, - query_blk->length-q_length, + score_right = s_BlastAlignPackedNucl(query+q_length-1, + subject+(s_length+3)/COMPRESSION_RATIO - 1, + query_blk->length-q_length, subject_blk->length-s_length, &(gap_align->query_stop), &(gap_align->subject_stop), gap_align, score_params, FALSE); - if (score_right < 0) + if (score_right < 0) return -1; gap_align->query_stop += q_length; gap_align->subject_stop += s_length; @@ -2988,18 +2994,18 @@ s_BlastDynProgNtGappedAlignment(BLAST_SequenceBlk* query_blk, * @param reverse_sequence Reverse the sequence. * @return The best alignment score found. */ -static Int4 -s_BlastAlignPackedNucl(Uint1* B, Uint1* A, Int4 N, Int4 M, - Int4* b_offset, Int4* a_offset, +static Int4 +s_BlastAlignPackedNucl(Uint1* B, Uint1* A, Int4 N, Int4 M, + Int4* b_offset, Int4* a_offset, BlastGapAlignStruct* gap_align, - const BlastScoringParameters* score_params, + const BlastScoringParameters* score_params, Boolean reverse_sequence) -{ +{ Int4 i; /* sequence pointers and indices */ Int4 a_index, a_base_pair; Int4 b_index, b_size, first_b_index, last_b_index, b_increment; Uint1* b_ptr; - + BlastGapDP* score_array; Int4 num_extra_cells; @@ -3007,16 +3013,16 @@ s_BlastAlignPackedNucl(Uint1* B, Uint1* A, Int4 N, Int4 M, Int4 gap_extend; Int4 gap_open_extend; Int4 x_dropoff; - + Int4* *matrix; /* pointers to the score matrix */ Int4* matrix_row; - + Int4 score; /* score tracking variables */ Int4 score_gap_row; Int4 score_gap_col; Int4 next_score; Int4 best_score; - + /* do initialization and sanity-checking */ matrix = gap_align->sbp->matrix->data; @@ -3026,13 +3032,13 @@ s_BlastAlignPackedNucl(Uint1* B, Uint1* A, Int4 N, Int4 M, gap_extend = score_params->gap_extend; gap_open_extend = gap_open + gap_extend; x_dropoff = gap_align->gap_x_dropoff; - + if (x_dropoff < gap_open_extend) x_dropoff = gap_open_extend; - - if(N <= 0 || M <= 0) + + if(N <= 0 || M <= 0) return 0; - + /* Allocate and fill in the auxiliary bookeeping structures. Since A and B could be very large, maintain a window of auxiliary structures only large enough to contain the current @@ -3056,17 +3062,17 @@ s_BlastAlignPackedNucl(Uint1* B, Uint1* A, Int4 N, Int4 M, score = -gap_open_extend; score_array[0].best = 0; score_array[0].best_gap = -gap_open_extend; - + for (i = 1; i <= N; i++) { - if (score < -x_dropoff) + if (score < -x_dropoff) break; score_array[i].best = score; - score_array[i].best_gap = score - gap_open_extend; + score_array[i].best_gap = score - gap_open_extend; score -= gap_extend; } - - /* The inner loop below examines letters of B from + + /* The inner loop below examines letters of B from index 'first_b_index' to 'b_size' */ b_size = i; @@ -3076,19 +3082,19 @@ s_BlastAlignPackedNucl(Uint1* B, Uint1* A, Int4 N, Int4 M, b_increment = -1; else b_increment = 1; - + for (a_index = 1; a_index <= M; a_index++) { - /* pick out the row of the score matrix + /* pick out the row of the score matrix appropriate for A[a_index] */ if(reverse_sequence) { - a_base_pair = NCBI2NA_UNPACK_BASE(A[(M-a_index)/4], + a_base_pair = NCBI2NA_UNPACK_BASE(A[(M-a_index)/4], ((a_index-1)%4)); matrix_row = matrix[a_base_pair]; - } + } else { - a_base_pair = NCBI2NA_UNPACK_BASE(A[1+((a_index-1)/4)], + a_base_pair = NCBI2NA_UNPACK_BASE(A[1+((a_index-1)/4)], (3-((a_index-1)%4))); matrix_row = matrix[a_base_pair]; } @@ -3108,7 +3114,7 @@ s_BlastAlignPackedNucl(Uint1* B, Uint1* A, Int4 N, Int4 M, b_ptr += b_increment; score_gap_col = score_array[b_index].best_gap; next_score = score_array[b_index].best + matrix_row[ *b_ptr ]; - + if (score < score_gap_col) score = score_gap_col; @@ -3120,11 +3126,11 @@ s_BlastAlignPackedNucl(Uint1* B, Uint1* A, Int4 N, Int4 M, /* the current best score failed the X-dropoff criterion. Note that this does not stop the inner loop, only forces future iterations to - skip this column of B. + skip this column of B. Also, if the very first letter of B that was tested failed the X dropoff criterion, make - sure future inner loops start one letter to + sure future inner loops start one letter to the right */ if (b_index == first_b_index) @@ -3141,7 +3147,7 @@ s_BlastAlignPackedNucl(Uint1* B, Uint1* A, Int4 N, Int4 M, } /* If starting a gap at this position will improve - the best row or column score, update them to + the best row or column score, update them to reflect that. */ score_gap_row -= gap_extend; @@ -3155,9 +3161,9 @@ s_BlastAlignPackedNucl(Uint1* B, Uint1* A, Int4 N, Int4 M, score = next_score; } - + /* Finish aligning if the best scores for all positions - of B will fail the X-dropoff test, i.e. the inner loop + of B will fail the X-dropoff test, i.e. the inner loop bounds have converged to each other */ if (first_b_index == b_size) @@ -3183,7 +3189,7 @@ s_BlastAlignPackedNucl(Uint1* B, Uint1* A, Int4 N, Int4 M, else { /* The inner loop finished without failing the X-dropoff test; initialize extra bookkeeping structures until - the X dropoff test fails or we run out of letters in B. + the X dropoff test fails or we run out of letters in B. The next inner loop will have larger bounds */ while (score_gap_row >= (best_score - x_dropoff) && b_size <= N) { @@ -3200,7 +3206,7 @@ s_BlastAlignPackedNucl(Uint1* B, Uint1* A, Int4 N, Int4 M, b_size++; } } - + return best_score; } @@ -3215,7 +3221,7 @@ BlastGetOffsetsForGappedAlignment (const Uint1* query, const Uint1* subject, Int4 s_length = hsp->subject.end - hsp->subject.offset; int q_start = hsp->query.offset; int s_start = hsp->subject.offset; - + if (q_length <= HSP_MAX_WINDOW) { *q_retval = q_start + q_length/2; *s_retval = s_start + q_length/2; @@ -3279,12 +3285,12 @@ BlastGetOffsetsForGappedAlignment (const Uint1* query, const Uint1* subject, return FALSE; } -void +void BlastGetStartForGappedAlignmentNucl (const Uint1* query, const Uint1* subject, BlastHSP* hsp) { /* We will stop when the identity count reaches to this number */ - const Int4 HSP_MAX_IDENT_RUN = 20; + int hspMaxIdentRun = 10; const Uint1 *q, *s; Int4 index, max_offset, score, max_score, q_start, s_start, q_len; Boolean match, prev_match; @@ -3299,14 +3305,15 @@ BlastGetStartForGappedAlignmentNucl (const Uint1* query, const Uint1* subject, q_len = hsp->query.end; while ((q-query < q_len) && (*q++ == *s++)) { score++; - if (score > HSP_MAX_IDENT_RUN) return; + if (score > hspMaxIdentRun) return; } q = query + q_start; s = subject + s_start; while ((q-query >= 0) && (*q-- == *s--)) { score++; - if (score > HSP_MAX_IDENT_RUN) return; + if (score > hspMaxIdentRun) return; } + hspMaxIdentRun *= 1.5; /* Demand larger value if we move */ /* if the old value is not ok, try to find a better point */ q_start = hsp->query.gapped_start - offset; s_start = hsp->subject.gapped_start - offset; @@ -3317,7 +3324,7 @@ BlastGetStartForGappedAlignmentNucl (const Uint1* query, const Uint1* subject, max_offset = q_start; score = 0; match = FALSE; - prev_match = FALSE; + prev_match = FALSE; for (index = q_start; index < q_start + q_len; index++) { match = (*q++ == *s++); if (match != prev_match) { @@ -3330,12 +3337,12 @@ BlastGetStartForGappedAlignmentNucl (const Uint1* query, const Uint1* subject, } } else if (match) { ++score; - if (score > HSP_MAX_IDENT_RUN) { - max_offset = index - HSP_MAX_IDENT_RUN/2; + if (score > hspMaxIdentRun) { + max_offset = index - hspMaxIdentRun/2; hsp->query.gapped_start = max_offset; hsp->subject.gapped_start = max_offset + s_start - q_start; return; - } + } } } if (match && score > max_score) { @@ -3348,15 +3355,15 @@ BlastGetStartForGappedAlignmentNucl (const Uint1* query, const Uint1* subject, } } -Int4 +Int4 BlastGetStartForGappedAlignment (const Uint1* query, const Uint1* subject, - const BlastScoreBlk* sbp, Uint4 q_start, Uint4 q_length, + const BlastScoreBlk* sbp, Uint4 q_start, Uint4 q_length, Uint4 s_start, Uint4 s_length) { Int4 index1, max_offset, score, max_score, hsp_end; const Uint1* query_var,* subject_var; Boolean positionBased = (sbp->psi_matrix != NULL); - + if (q_length <= HSP_MAX_WINDOW) { max_offset = q_start + q_length/2; return max_offset; @@ -3392,15 +3399,15 @@ BlastGetStartForGappedAlignment (const Uint1* query, const Uint1* subject, } if (max_score > 0) max_offset -= HSP_MAX_WINDOW/2; - else + else max_offset = q_start; return max_offset; } -Int2 BLAST_GetGappedScore (EBlastProgramType program_number, - BLAST_SequenceBlk* query, BlastQueryInfo* query_info, - BLAST_SequenceBlk* subject, +Int2 BLAST_GetGappedScore (EBlastProgramType program_number, + BLAST_SequenceBlk* query, BlastQueryInfo* query_info, + BLAST_SequenceBlk* subject, BlastGapAlignStruct* gap_align, const BlastScoringParameters* score_params, const BlastExtensionParameters* ext_params, @@ -3444,11 +3451,12 @@ Int2 BLAST_GetGappedScore (EBlastProgramType program_number, return 0; is_prot = (program_number != eBlastTypeBlastn && - program_number != eBlastTypePhiBlastn); + program_number != eBlastTypePhiBlastn && + program_number != eBlastTypeMapping); is_greedy = (ext_params->options->ePrelimGapExt == eGreedyScoreOnly); - /* turn on approximate gapped alignment if 1) the search - specifies it, and 2) the first, highest-scoring ungapped + /* turn on approximate gapped alignment if 1) the search + specifies it, and 2) the first, highest-scoring ungapped alignment in init_hitlist scores below a reduced cutoff. The second condition is used to avoid computing approximate alignments that experiment shows are likely to be thrown @@ -3458,7 +3466,7 @@ Int2 BLAST_GetGappedScore (EBlastProgramType program_number, int i; Boolean* found = calloc(query_info->last_context + 1, sizeof(Boolean)); - restricted_align_array = + restricted_align_array = (Boolean*)calloc(Blast_GetQueryIndexFromContext( query_info->last_context, program_number) + 1, @@ -3518,7 +3526,7 @@ Int2 BLAST_GetGappedScore (EBlastProgramType program_number, rps_cutoff_index = subject->oid; else rps_cutoff_index = subject->oid * NUM_FRAMES + - BLAST_FrameToContext(subject->frame, + BLAST_FrameToContext(subject->frame, program_number); } @@ -3526,7 +3534,7 @@ Int2 BLAST_GetGappedScore (EBlastProgramType program_number, if (*hsp_list_ptr == NULL) *hsp_list_ptr = hsp_list = Blast_HSPListNew(kHspNumMax); - else + else hsp_list = *hsp_list_ptr; /* Initialize the interval tree with the maximum possible @@ -3535,11 +3543,11 @@ Int2 BLAST_GetGappedScore (EBlastProgramType program_number, except for out-of-frame tblastn. In that case, subject->length is the length of one strand of the subject sequence, but the subject offsets of each ungapped alignment are wrt all six subject - frames concatenated together. Finally, add 1 to the maximum, + frames concatenated together. Finally, add 1 to the maximum, to account for HSPs that include the end of a sequence */ if (Blast_SubjectIsTranslated(program_number) && - score_params->options->is_ooframe) { + score_params->options->is_ooframe) { /* OOF search only supported for tblastn and blastx. (blastx does not have a translated subject, so can't get here.) */ ASSERT(program_number == eBlastTypeTblastn); @@ -3554,14 +3562,14 @@ Int2 BLAST_GetGappedScore (EBlastProgramType program_number, if (!tree) return BLASTERR_MEMORY; - + init_hsp_array = init_hitlist->init_hsp_array; found_high_score = (Int4*) calloc(query_info->num_queries, sizeof(Int4)); if (hit_params->low_score) { for (index=0; indextotal; index++) { - int query_index = + int query_index = Blast_GetQueryIndexFromQueryOffset(init_hsp_array[index].offsets.qs_offsets.q_off, program_number, query_info); if (init_hsp_array[index].ungapped_data->score > hit_params->low_score[query_index]) found_high_score[query_index] = 1; @@ -3585,7 +3593,7 @@ Int2 BLAST_GetGappedScore (EBlastProgramType program_number, } init_hsp = &tmp_init_hsp; - s_AdjustHspOffsetsAndGetQueryData(query, query_info, init_hsp, + s_AdjustHspOffsetsAndGetQueryData(query, query_info, init_hsp, &query_tmp, &context); query_index = Blast_GetQueryIndexFromContext(context, program_number); @@ -3611,7 +3619,7 @@ Int2 BLAST_GetGappedScore (EBlastProgramType program_number, } if (rpsblast_pssms) - gap_align->sbp->psi_matrix->pssm->data = rpsblast_pssms + + gap_align->sbp->psi_matrix->pssm->data = rpsblast_pssms + query_info->contexts[context].query_offset; if (!init_hsp->ungapped_data) { @@ -3652,27 +3660,27 @@ Int2 BLAST_GetGappedScore (EBlastProgramType program_number, if (gapped_stats) ++gapped_stats->extensions; - + if(is_prot && !score_params->options->is_ooframe) { - max_offset = - BlastGetStartForGappedAlignment(query_tmp.sequence, + max_offset = + BlastGetStartForGappedAlignment(query_tmp.sequence, subject->sequence, gap_align->sbp, init_hsp->ungapped_data->q_start, init_hsp->ungapped_data->length, init_hsp->ungapped_data->s_start, init_hsp->ungapped_data->length); - init_hsp->offsets.qs_offsets.s_off += + init_hsp->offsets.qs_offsets.s_off += max_offset - init_hsp->offsets.qs_offsets.q_off; init_hsp->offsets.qs_offsets.q_off = max_offset; } if (is_prot) { - status = s_BlastProtGappedAlignment(program_number, &query_tmp, - subject, gap_align, - score_params, init_hsp, + status = s_BlastProtGappedAlignment(program_number, &query_tmp, + subject, gap_align, + score_params, init_hsp, restricted_alignment, fence_hit); - + if (restricted_alignment && gap_align->score < cutoff && gap_align->score >= restricted_cutoff) { @@ -3682,7 +3690,7 @@ Int2 BLAST_GetGappedScore (EBlastProgramType program_number, could be highly suboptimal. Recomputing the alignment would resolve the ambiguity, but when the final list of HSPs contains a mix of approximate and exact gapped - alignments it's possible for a highly suboptimal + alignments it's possible for a highly suboptimal alignment to make it to the traceback phase, where its start point is reused. We sidestep this problem by throwing away all the previously computed gapped @@ -3709,7 +3717,7 @@ Int2 BLAST_GetGappedScore (EBlastProgramType program_number, status = BlastIntervalTreeAddHSP( hsp_list->hsp_array[index2], tree, - query_info, + query_info, eQueryAndSubject); hsp_list->hsp_array[index2] = NULL; @@ -3727,43 +3735,43 @@ Int2 BLAST_GetGappedScore (EBlastProgramType program_number, alignments for the current query */ redo_index = index; redo_query = query_index; - index = -1; + index = -1; continue; } } else if (is_greedy) { if (init_hsp->ungapped_data) { - init_hsp->offsets.qs_offsets.q_off = + init_hsp->offsets.qs_offsets.q_off = init_hsp->ungapped_data->q_start + init_hsp->ungapped_data->length/2; - init_hsp->offsets.qs_offsets.s_off = + init_hsp->offsets.qs_offsets.s_off = init_hsp->ungapped_data->s_start + init_hsp->ungapped_data->length/2; } status = BLAST_GreedyGappedAlignment( - query_tmp.sequence, subject->sequence, - query_tmp.length, subject->length, - gap_align, score_params, - init_hsp->offsets.qs_offsets.q_off, - init_hsp->offsets.qs_offsets.s_off, + query_tmp.sequence, subject->sequence, + query_tmp.length, subject->length, + gap_align, score_params, + init_hsp->offsets.qs_offsets.q_off, + init_hsp->offsets.qs_offsets.s_off, (Boolean) TRUE, FALSE, fence_hit); /* override the alignment start point with the estimate by the aligner of the best start point */ - init_hsp->offsets.qs_offsets.q_off = + init_hsp->offsets.qs_offsets.q_off = gap_align->greedy_query_seed_start; init_hsp->offsets.qs_offsets.s_off = gap_align->greedy_subject_seed_start; } else { /* Assuming the ungapped alignment is long enough to - contain an 8-letter seed of exact matches, start - the gapped alignment inside the first byte of the - seed that contains all matches. Note that even if - the ungapped alignment is not long enough, - s_BlastDynProgNtGappedAlignment will still round - the start point up to the first 4-base boundary + contain an 8-letter seed of exact matches, start + the gapped alignment inside the first byte of the + seed that contains all matches. Note that even if + the ungapped alignment is not long enough, + s_BlastDynProgNtGappedAlignment will still round + the start point up to the first 4-base boundary on the subject sequence */ if (s_end >= (Int4)init_hsp->offsets.qs_offsets.s_off + 8) { init_hsp->offsets.qs_offsets.s_off += 3; init_hsp->offsets.qs_offsets.q_off += 3; } - status = s_BlastDynProgNtGappedAlignment(&query_tmp, subject, + status = s_BlastDynProgNtGappedAlignment(&query_tmp, subject, gap_align, score_params, init_hsp); } @@ -3775,12 +3783,12 @@ Int2 BLAST_GetGappedScore (EBlastProgramType program_number, tree = Blast_IntervalTreeFree(tree); return status; } - + if (gap_align->score >= cutoff) { Int2 query_frame = 0; - /* For mixed-frame search, the query frame is determined + /* For mixed-frame search, the query frame is determined from the offset, not only from context. */ - if (score_params->options->is_ooframe && + if (score_params->options->is_ooframe && program_number == eBlastTypeBlastx) { query_frame = gap_align->query_start % CODON_LENGTH + 1; if ((context % NUM_FRAMES) >= CODON_LENGTH) @@ -3789,12 +3797,12 @@ Int2 BLAST_GetGappedScore (EBlastProgramType program_number, query_frame = query_info->contexts[context].frame; } - status = Blast_HSPInit(gap_align->query_start, - gap_align->query_stop, gap_align->subject_start, - gap_align->subject_stop, - init_hsp->offsets.qs_offsets.q_off, - init_hsp->offsets.qs_offsets.s_off, context, - query_frame, subject->frame, gap_align->score, + status = Blast_HSPInit(gap_align->query_start, + gap_align->query_stop, gap_align->subject_start, + gap_align->subject_stop, + init_hsp->offsets.qs_offsets.q_off, + init_hsp->offsets.qs_offsets.s_off, context, + query_frame, subject->frame, gap_align->score, &(gap_align->edit_script), &new_hsp); if (status) { @@ -3805,7 +3813,7 @@ Int2 BLAST_GetGappedScore (EBlastProgramType program_number, status = Blast_HSPListSaveHSP(hsp_list, new_hsp); if (status) break; - status = BlastIntervalTreeAddHSP(new_hsp, tree, query_info, + status = BlastIntervalTreeAddHSP(new_hsp, tree, query_info, eQueryAndSubject); if (status) break; @@ -3819,7 +3827,7 @@ Int2 BLAST_GetGappedScore (EBlastProgramType program_number, } } } - } + } sfree(found_high_score); if (restricted_align_array) { @@ -3843,20 +3851,20 @@ Int2 BLAST_GetGappedScore (EBlastProgramType program_number, * @param private_s_start Extent of alignment in subject [out] * @param score_only Return score only, without traceback [in] * @param edit_block Structure to hold generated traceback [out] - * @param gap_align Gapped alignment information and preallocated + * @param gap_align Gapped alignment information and preallocated * memory [in] [out] * @param score_params Scoring parameters [in] * @param psi_offset Starting position in PSI-BLAST matrix [in] * @param reversed Direction of the extension [in] - * @param switch_seq Sequences need to be switched for blastx, + * @param switch_seq Sequences need to be switched for blastx, * but not for tblastn [in] */ -static Int4 -s_OutOfFrameSemiGappedAlignWrap(const Uint1* query, const Uint1* subject, Int4 q_off, - Int4 s_off, Int4* private_q_start, Int4* private_s_start, - Boolean score_only, GapPrelimEditBlock *edit_block, - BlastGapAlignStruct* gap_align, - const BlastScoringParameters* score_params, Int4 psi_offset, +static Int4 +s_OutOfFrameSemiGappedAlignWrap(const Uint1* query, const Uint1* subject, Int4 q_off, + Int4 s_off, Int4* private_q_start, Int4* private_s_start, + Boolean score_only, GapPrelimEditBlock *edit_block, + BlastGapAlignStruct* gap_align, + const BlastScoringParameters* score_params, Int4 psi_offset, Boolean reversed, Boolean switch_seq) { if (switch_seq) { @@ -3870,24 +3878,24 @@ s_OutOfFrameSemiGappedAlignWrap(const Uint1* query, const Uint1* subject, Int4 q } } -/** Maximal subject length after which the offsets are adjusted to a +/** Maximal subject length after which the offsets are adjusted to a * subsequence. */ #define MAX_SUBJECT_OFFSET 90000 /** Approximate upper bound on a number of gaps in an HSP, needed to determine * the length of the subject subsequence to be retrieved for alignment with - * traceback. + * traceback. */ #define MAX_TOTAL_GAPS 3000 -void -AdjustSubjectRange(Int4* subject_offset_ptr, Int4* subject_length_ptr, +void +AdjustSubjectRange(Int4* subject_offset_ptr, Int4* subject_length_ptr, Int4 query_offset, Int4 query_length, Int4* start_shift) { Int4 s_offset; Int4 subject_length = *subject_length_ptr; Int4 max_extension_left, max_extension_right; - + /* If subject sequence is not too long, leave everything as is */ if (subject_length < MAX_SUBJECT_OFFSET) { *start_shift = 0; @@ -3895,7 +3903,7 @@ AdjustSubjectRange(Int4* subject_offset_ptr, Int4* subject_length_ptr, } s_offset = *subject_offset_ptr; - /* Maximal extension length is the remaining length in the query, plus + /* Maximal extension length is the remaining length in the query, plus an estimate of a maximal total number of gaps. */ max_extension_left = query_offset + MAX_TOTAL_GAPS; max_extension_right = query_length - query_offset + MAX_TOTAL_GAPS; @@ -3907,12 +3915,12 @@ AdjustSubjectRange(Int4* subject_offset_ptr, Int4* subject_length_ptr, *subject_offset_ptr = max_extension_left; } - *subject_length_ptr = + *subject_length_ptr = MIN(subject_length, s_offset + max_extension_right) - *start_shift; } /** Performs gapped extension for protein sequences, given two - * sequence blocks, scoring and extension options, and an initial HSP + * sequence blocks, scoring and extension options, and an initial HSP * with information from the previously performed ungapped extension * @param program BLAST program [in] * @param query_blk The query sequence block [in] @@ -3920,15 +3928,15 @@ AdjustSubjectRange(Int4* subject_offset_ptr, Int4* subject_length_ptr, * @param gap_align The auxiliary structure for gapped alignment [in] * @param score_params Parameters related to scoring [in] * @param init_hsp The initial HSP information [in] - * @param restricted_alignment If true and search is not out-of-frame, + * @param restricted_alignment If true and search is not out-of-frame, * use a faster approximate gapped alignment algorithm [in] * @param fence_hit If not NULL, pointer to a boolean that is set to * TRUE if gapped extension reaches a neighborhood * of the subject sequence that is not initialized [in][out] */ -static Int2 -s_BlastProtGappedAlignment(EBlastProgramType program, - BLAST_SequenceBlk* query_blk, BLAST_SequenceBlk* subject_blk, +static Int2 +s_BlastProtGappedAlignment(EBlastProgramType program, + BLAST_SequenceBlk* query_blk, BLAST_SequenceBlk* subject_blk, BlastGapAlignStruct* gap_align, const BlastScoringParameters* score_params, BlastInitHSP* init_hsp, Boolean restricted_alignment, @@ -3943,10 +3951,10 @@ s_BlastProtGappedAlignment(EBlastProgramType program, Int4 subject_length = subject_blk->length; Int4 subject_shift = 0; BlastScoringOptions *score_options = score_params->options; - + if (gap_align == NULL) return -1; - + if (score_options->is_ooframe) { ASSERT(program == eBlastTypeTblastn || program == eBlastTypeBlastx); @@ -3955,7 +3963,7 @@ s_BlastProtGappedAlignment(EBlastProgramType program, of the mixed-frame sequence corresponding to the reverse strand. */ if (program == eBlastTypeTblastn && subject_blk->frame < 0) init_hsp->offsets.qs_offsets.s_off -= subject_length + 1; - + s_length = init_hsp->offsets.qs_offsets.s_off; if (program == eBlastTypeBlastx) { @@ -3975,35 +3983,35 @@ s_BlastProtGappedAlignment(EBlastProgramType program, subject = subject_blk->sequence; } - AdjustSubjectRange(&s_length, &subject_length, q_length, query_length, + AdjustSubjectRange(&s_length, &subject_length, q_length, query_length, &subject_shift); found_start = FALSE; found_end = FALSE; - + /* Looking for "left" score */ score_left = 0; if (q_length != 0 && s_length != 0) { found_start = TRUE; if(score_options->is_ooframe) { - score_left = + score_left = s_OutOfFrameSemiGappedAlignWrap(query, subject, q_length, s_length, - &private_q_start, &private_s_start, TRUE, NULL, + &private_q_start, &private_s_start, TRUE, NULL, gap_align, score_params, q_length, TRUE, switch_seq); } else { if (restricted_alignment) { - score_left = s_RestrictedGappedAlign(query, subject+subject_shift, + score_left = s_RestrictedGappedAlign(query, subject+subject_shift, q_length, s_length, &private_q_start, &private_s_start, - gap_align, score_params, + gap_align, score_params, init_hsp->offsets.qs_offsets.q_off, TRUE); } else { - score_left = Blast_SemiGappedAlign(query, subject+subject_shift, + score_left = Blast_SemiGappedAlign(query, subject+subject_shift, q_length, s_length, - &private_q_start, &private_s_start, TRUE, - NULL, gap_align, score_params, - init_hsp->offsets.qs_offsets.q_off, + &private_q_start, &private_s_start, TRUE, + NULL, gap_align, score_params, + init_hsp->offsets.qs_offsets.q_off, FALSE, TRUE, fence_hit); } @@ -4016,46 +4024,46 @@ s_BlastProtGappedAlignment(EBlastProgramType program, if (q_length < query_length && s_length < subject_length) { found_end = TRUE; if(score_options->is_ooframe) { - score_right = - s_OutOfFrameSemiGappedAlignWrap(query-1, subject-1, + score_right = + s_OutOfFrameSemiGappedAlignWrap(query-1, subject-1, query_length-q_length+1, subject_length-s_length+1, - &(gap_align->query_stop), &(gap_align->subject_stop), - TRUE, NULL, gap_align, score_params, q_length, FALSE, + &(gap_align->query_stop), &(gap_align->subject_stop), + TRUE, NULL, gap_align, score_params, q_length, FALSE, switch_seq); gap_align->query_stop += q_length; gap_align->subject_stop += s_length + subject_shift; } else { if (restricted_alignment) { score_right = s_RestrictedGappedAlign( - query+init_hsp->offsets.qs_offsets.q_off, - subject+init_hsp->offsets.qs_offsets.s_off, - query_length-q_length, - subject_length-s_length, - &(gap_align->query_stop), - &(gap_align->subject_stop), - gap_align, score_params, + query+init_hsp->offsets.qs_offsets.q_off, + subject+init_hsp->offsets.qs_offsets.s_off, + query_length-q_length, + subject_length-s_length, + &(gap_align->query_stop), + &(gap_align->subject_stop), + gap_align, score_params, init_hsp->offsets.qs_offsets.q_off, FALSE); } else { score_right = Blast_SemiGappedAlign( - query+init_hsp->offsets.qs_offsets.q_off, - subject+init_hsp->offsets.qs_offsets.s_off, - query_length-q_length, - subject_length-s_length, - &(gap_align->query_stop), - &(gap_align->subject_stop), - TRUE, NULL, gap_align, score_params, - init_hsp->offsets.qs_offsets.q_off, FALSE, + query+init_hsp->offsets.qs_offsets.q_off, + subject+init_hsp->offsets.qs_offsets.s_off, + query_length-q_length, + subject_length-s_length, + &(gap_align->query_stop), + &(gap_align->subject_stop), + TRUE, NULL, gap_align, score_params, + init_hsp->offsets.qs_offsets.q_off, FALSE, FALSE, fence_hit); } - /* Make end offsets point to the byte after the end of the + /* Make end offsets point to the byte after the end of the alignment */ gap_align->query_stop += init_hsp->offsets.qs_offsets.q_off + 1; gap_align->subject_stop += init_hsp->offsets.qs_offsets.s_off + 1; } } - + if (found_start == FALSE) { /* impossible for in-frame */ gap_align->query_start = init_hsp->offsets.qs_offsets.q_off; gap_align->subject_start = init_hsp->offsets.qs_offsets.s_off; @@ -4064,7 +4072,7 @@ s_BlastProtGappedAlignment(EBlastProgramType program, gap_align->query_stop = init_hsp->offsets.qs_offsets.q_off; gap_align->subject_stop = init_hsp->offsets.qs_offsets.s_off; } - + gap_align->score = score_right+score_left; return 0; @@ -4091,7 +4099,7 @@ s_BlastOOFTracebackToGapEditScript(GapPrelimEditBlock *rev_prelim_tback, GapPrelimEditBlock *tmp_prelim_tback; Int4 i, num_nuc; int extra_needed=0; - + /* prepend a substitution, since the input sequences were shifted prior to the OOF alignment */ @@ -4117,7 +4125,7 @@ s_BlastOOFTracebackToGapEditScript(GapPrelimEditBlock *rev_prelim_tback, /* Propagating the initial extra substitution requires that edit operations which are not in-frame gaps must 'flow through' an in-frame gap; the last non-gap - operation before the gap will appear after the gap. + operation before the gap will appear after the gap. This could mean either one or two edit blocks getting created */ @@ -4139,8 +4147,8 @@ s_BlastOOFTracebackToGapEditScript(GapPrelimEditBlock *rev_prelim_tback, } /* Handle the crossing over from the left extension to - the right extension. Begin by writing out the final - group of ops from the left extension, except for the + the right extension. Begin by writing out the final + group of ops from the left extension, except for the one op that must be merged */ last_num--; @@ -4193,7 +4201,7 @@ s_BlastOOFTracebackToGapEditScript(GapPrelimEditBlock *rev_prelim_tback, for (i=0; isize; i++) { int total_actions=0; - /* Count the number of nucleotides in the next + /* Count the number of nucleotides in the next traceback operation and delete any traceback operations that would make the alignment too long. This check is not needed for in-frame alignment because the @@ -4207,7 +4215,7 @@ s_BlastOOFTracebackToGapEditScript(GapPrelimEditBlock *rev_prelim_tback, total_actions = last_op * e_script->num[i]; if (num_nuc + total_actions >= nucl_align_length) { - e_script->num[i] = (nucl_align_length - num_nuc + + e_script->num[i] = (nucl_align_length - num_nuc + last_op - 1) / last_op; break; /* We delete the rest of the script. */ } @@ -4267,13 +4275,13 @@ s_BlastOOFTracebackToGapEditScript(GapPrelimEditBlock *rev_prelim_tback, return 0; } -Int2 BLAST_GappedAlignmentWithTraceback(EBlastProgramType program, - const Uint1* query, const Uint1* subject, BlastGapAlignStruct* gap_align, +Int2 BLAST_GappedAlignmentWithTraceback(EBlastProgramType program, + const Uint1* query, const Uint1* subject, BlastGapAlignStruct* gap_align, const BlastScoringParameters* score_params, Int4 q_start, Int4 s_start, Int4 query_length, Int4 subject_length, Boolean * fence_hit) { - Boolean found_start, found_end; + Boolean found_end; Int4 score_right, score_left, private_q_length, private_s_length; Int4 q_length, s_length; Boolean is_ooframe = score_params->options->is_ooframe; @@ -4281,23 +4289,22 @@ Int2 BLAST_GappedAlignmentWithTraceback(EBlastProgramType program, Boolean switch_seq = FALSE; GapPrelimEditBlock *fwd_prelim_tback; GapPrelimEditBlock *rev_prelim_tback; - + if (gap_align == NULL) return -1; - + fwd_prelim_tback = gap_align->fwd_prelim_tback; rev_prelim_tback = gap_align->rev_prelim_tback; GapPrelimEditBlockReset(fwd_prelim_tback); GapPrelimEditBlockReset(rev_prelim_tback); - found_start = FALSE; found_end = FALSE; - + q_length = query_length; s_length = subject_length; if (is_ooframe) { - /* The mixed frame sequence is shifted to the 3rd position, so its - maximal available length for extension is less by 2 than its + /* The mixed frame sequence is shifted to the 3rd position, so its + maximal available length for extension is less by 2 than its total length. */ switch_seq = (program == eBlastTypeBlastx); if (switch_seq) { @@ -4308,60 +4315,59 @@ Int2 BLAST_GappedAlignmentWithTraceback(EBlastProgramType program, } score_left = 0; - found_start = TRUE; - + if(is_ooframe) { /* NB: Left extension does not include starting point corresponding to the offset pair; the right extension does. */ score_left = - s_OutOfFrameSemiGappedAlignWrap(query+q_start, subject+s_start, - q_start, s_start, &private_q_length, &private_s_length, - FALSE, rev_prelim_tback, gap_align, score_params, q_start, + s_OutOfFrameSemiGappedAlignWrap(query+q_start, subject+s_start, + q_start, s_start, &private_q_length, &private_s_length, + FALSE, rev_prelim_tback, gap_align, score_params, q_start, TRUE, switch_seq); gap_align->query_start = q_start - private_q_length; gap_align->subject_start = s_start - private_s_length; - } else { - /* NB: The left extension includes the starting point + } else { + /* NB: The left extension includes the starting point [q_start,s_start]; the right extension does not. */ - // score_left = + // score_left = // Blast_SemiGappedAlign(query, subject, q_start+1, s_start+1, // &private_q_length, &private_s_length, FALSE, rev_prelim_tback, // gap_align, score_params, q_start, FALSE, TRUE, // fence_hit); score_left = ALIGN_EX(query, subject, q_start+1, s_start+1, &private_q_length, &private_s_length, rev_prelim_tback, - gap_align, + gap_align, score_params, q_start, FALSE /*reversed*/, TRUE /*reverse_sequence*/, fence_hit); gap_align->query_start = q_start - private_q_length + 1; gap_align->subject_start = s_start - private_s_length + 1; } - + score_right = 0; - + if ((! (fence_hit && *fence_hit)) && (q_start < q_length) && (s_start < s_length)) { - + found_end = TRUE; if(is_ooframe) { - score_right = + score_right = s_OutOfFrameSemiGappedAlignWrap(query+q_start-1, subject+s_start-1, - q_length-q_start, s_length-s_start, + q_length-q_start, s_length-s_start, &private_q_length, &private_s_length, FALSE, fwd_prelim_tback, gap_align, score_params, q_start, FALSE, switch_seq); } else { - // score_right = - // Blast_SemiGappedAlign(query+q_start, subject+s_start, - // q_length-q_start-1, s_length-s_start-1, &private_q_length, - // &private_s_length, FALSE, fwd_prelim_tback, gap_align, + // score_right = + // Blast_SemiGappedAlign(query+q_start, subject+s_start, + // q_length-q_start-1, s_length-s_start-1, &private_q_length, + // &private_s_length, FALSE, fwd_prelim_tback, gap_align, // score_params, q_start, FALSE, FALSE, // fence_hit); - score_right = - ALIGN_EX(query+q_start, subject+s_start, - q_length-q_start-1, s_length-s_start-1, &private_q_length, - &private_s_length, fwd_prelim_tback, gap_align, + score_right = + ALIGN_EX(query+q_start, subject+s_start, + q_length-q_start-1, s_length-s_start-1, &private_q_length, + &private_s_length, fwd_prelim_tback, gap_align, score_params, q_start, FALSE, FALSE, fence_hit); } @@ -4369,12 +4375,7 @@ Int2 BLAST_GappedAlignmentWithTraceback(EBlastProgramType program, gap_align->query_stop = q_start + private_q_length + 1; gap_align->subject_stop = s_start + private_s_length + 1; } - - if (found_start == FALSE) { /* Start never found */ - gap_align->query_start = q_start; - gap_align->subject_start = s_start; - } - + if (found_end == FALSE) { gap_align->query_stop = q_start - 1; gap_align->subject_stop = s_start - 1; @@ -4383,15 +4384,15 @@ Int2 BLAST_GappedAlignmentWithTraceback(EBlastProgramType program, if(is_ooframe) { Int4 nucl_align_length; if (program == eBlastTypeBlastx) { - nucl_align_length = gap_align->query_stop - + nucl_align_length = gap_align->query_stop - gap_align->query_start; } else { - nucl_align_length = gap_align->subject_stop - + nucl_align_length = gap_align->subject_stop - gap_align->subject_start; } - status = s_BlastOOFTracebackToGapEditScript(rev_prelim_tback, - fwd_prelim_tback, nucl_align_length, + status = s_BlastOOFTracebackToGapEditScript(rev_prelim_tback, + fwd_prelim_tback, nucl_align_length, &gap_align->edit_script); } else { Int4 i; @@ -4400,10 +4401,10 @@ Int2 BLAST_GappedAlignmentWithTraceback(EBlastProgramType program, fwd_prelim_tback); /* rarely (typically when the scoring system changes between - the score-only and traceback stages, as happens with - composition-based statistics) it is possible to compute an + the score-only and traceback stages, as happens with + composition-based statistics) it is possible to compute an optimal alignment with a leading or trailing gap. Prune - these unneeded gaps here and update the score and + these unneeded gaps here and update the score and alignment boundaries */ gap_align->edit_script = esp; @@ -4411,12 +4412,12 @@ Int2 BLAST_GappedAlignmentWithTraceback(EBlastProgramType program, while (esp->size && esp->op_type[0] != eGapAlignSub) { score_left += score_params->gap_open + esp->num[0] * score_params->gap_extend; - + if (esp->op_type[0] == eGapAlignDel) gap_align->subject_start += esp->num[0]; else gap_align->query_start += esp->num[0]; - + for (i = 1; i < esp->size; i++) { esp->op_type[i-1] = esp->op_type[i]; esp->num[i-1] = esp->num[i]; @@ -4427,12 +4428,12 @@ Int2 BLAST_GappedAlignmentWithTraceback(EBlastProgramType program, while (esp->size && esp->op_type[i-1] != eGapAlignSub) { score_right += score_params->gap_open + esp->num[i-1] * score_params->gap_extend; - + if (esp->op_type[i-1] == eGapAlignDel) gap_align->subject_stop -= esp->num[i-1]; else gap_align->query_stop -= esp->num[i-1]; - + esp->size--; i--; ASSERT(esp->size == i); @@ -4445,9 +4446,9 @@ Int2 BLAST_GappedAlignmentWithTraceback(EBlastProgramType program, } Int2 BLAST_GetUngappedHSPList(BlastInitHitList* init_hitlist, - BlastQueryInfo* query_info, - BLAST_SequenceBlk* subject, - const BlastHitSavingOptions* hit_options, + BlastQueryInfo* query_info, + BLAST_SequenceBlk* subject, + const BlastHitSavingOptions* hit_options, BlastHSPList** hsp_list_ptr) { BlastHSPList* hsp_list = NULL; @@ -4472,26 +4473,26 @@ Int2 BLAST_GetUngappedHSPList(BlastInitHitList* init_hitlist, BlastUngappedData* ungapped_data=NULL; Int4 context = 0; init_hsp = &init_hitlist->init_hsp_array[index]; - if (!init_hsp->ungapped_data) + if (!init_hsp->ungapped_data) continue; if (!hsp_list) { hsp_list = Blast_HSPListNew(kHspNumMax); *hsp_list_ptr = hsp_list; } - /* Adjust the initial HSP's coordinates in case of concatenated + /* Adjust the initial HSP's coordinates in case of concatenated multiple queries/strands/frames */ context = s_GetUngappedHSPContext(query_info, init_hsp); s_AdjustInitialHSPOffsets(init_hsp, query_info->contexts[context].query_offset); ungapped_data = init_hsp->ungapped_data; - Blast_HSPInit(ungapped_data->q_start, + Blast_HSPInit(ungapped_data->q_start, ungapped_data->length+ungapped_data->q_start, - ungapped_data->s_start, + ungapped_data->s_start, ungapped_data->length+ungapped_data->s_start, - init_hsp->offsets.qs_offsets.q_off, - init_hsp->offsets.qs_offsets.s_off, - context, query_info->contexts[context].frame, + init_hsp->offsets.qs_offsets.q_off, + init_hsp->offsets.qs_offsets.s_off, + context, query_info->contexts[context].frame, subject->frame, ungapped_data->score, NULL, &new_hsp); Blast_HSPListSaveHSP(hsp_list, new_hsp); } diff --git a/c++/src/algo/blast/core/blast_hits.c b/c++/src/algo/blast/core/blast_hits.c index 2cf91cc2..b9b1abda 100644 --- a/c++/src/algo/blast/core/blast_hits.c +++ b/c++/src/algo/blast/core/blast_hits.c @@ -1,4 +1,4 @@ -/* $Id: blast_hits.c 500444 2016-05-04 17:46:06Z ivanov $ +/* $Id: blast_hits.c 516334 2016-10-12 17:30:52Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -30,11 +30,6 @@ * BLAST functions for saving hits after the (preliminary) gapped alignment */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_hits.c 500444 2016-05-04 17:46:06Z ivanov $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include @@ -42,6 +37,7 @@ static char const rcsid[] = #include #include "blast_hits_priv.h" #include "blast_itree.h" +#include "jumper.h" NCBI_XBLAST_EXPORT Int2 SBlastHitsParametersNew(const BlastHitSavingOptions* hit_options, @@ -111,6 +107,7 @@ BlastHSP* Blast_HSPFree(BlastHSP* hsp) if (!hsp) return NULL; hsp->gap_info = GapEditScriptDelete(hsp->gap_info); + hsp->map_info = BlastHSPMappingInfoFree(hsp->map_info); sfree(hsp->pat_info); sfree(hsp); return NULL; @@ -166,6 +163,28 @@ Blast_HSPInit(Int4 query_start, Int4 query_end, Int4 subject_start, return 0; } + +BlastHSPMappingInfo* BlastHSPMappingInfoFree(BlastHSPMappingInfo* info) +{ + if (!info) { + return NULL; + } + + info->edits = JumperEditsBlockFree(info->edits); + if (info->subject_overhangs) { + SequenceOverhangsFree(info->subject_overhangs); + } + sfree(info); + + return NULL; +} + +BlastHSPMappingInfo* BlastHSPMappingInfoNew(void) +{ + BlastHSPMappingInfo* retval = calloc(1, sizeof(BlastHSPMappingInfo)); + return retval; +} + Int4 BlastHspNumMax(Boolean gapped_calculation, const BlastHitSavingOptions* options) { Int4 retval=0; @@ -216,6 +235,98 @@ s_BlastHSPCopy(const BlastHSP* hsp) return new_hsp; } +/* Make a deep copy of an HSP */ +BlastHSP* Blast_HSPClone(const BlastHSP* hsp) +{ + BlastHSP* retval = NULL; + + if (!hsp) { + return NULL; + } + + retval = Blast_HSPNew(); + if (retval) { + retval->score = hsp->score; + retval->num_ident = hsp->num_ident; + memcpy(&retval->query, &hsp->query, sizeof(BlastSeg)); + memcpy(&retval->subject, &hsp->subject, sizeof(BlastSeg)); + retval->context = hsp->context; + retval->evalue = hsp->evalue; + retval->bit_score = hsp->bit_score; + retval->num = hsp->num; + retval->comp_adjustment_method = hsp->comp_adjustment_method; + retval->num_positives = hsp->num_positives; + + /* copy gapped traceback */ + if (hsp->gap_info) { + retval->gap_info = GapEditScriptDup(hsp->gap_info); + if (!retval->gap_info) { + Blast_HSPFree(retval); + return NULL; + } + } + + /* copy short read mapping data */ + if (hsp->map_info) { + retval->map_info = BlastHSPMappingInfoNew(); + if (!retval->map_info) { + Blast_HSPFree(retval); + return NULL; + } + retval->map_info->edits = + JumperEditsBlockDup(hsp->map_info->edits); + if (!retval->map_info->edits) { + Blast_HSPFree(retval); + return NULL; + } + retval->map_info->left_edge = hsp->map_info->left_edge; + retval->map_info->right_edge = hsp->map_info->right_edge; + + if (hsp->map_info->subject_overhangs) { + SequenceOverhangs* old = hsp->map_info->subject_overhangs; + SequenceOverhangs* copy = calloc(1, sizeof(SequenceOverhangs)); + if (!copy) { + Blast_HSPFree(retval); + return NULL; + } + + if (old->left && old->left_len > 0) { + copy->left_len = old->left_len; + copy->left = malloc(copy->left_len * sizeof(Uint1)); + if (!copy->left) { + SequenceOverhangsFree(copy); + Blast_HSPFree(retval); + return NULL; + } + memcpy(copy->left, old->left, + copy->left_len * sizeof(Uint1)); + } + + if (old->right && old->right_len > 0) { + copy->right_len = old->right_len; + copy->right = malloc(copy->right_len * sizeof(Uint1)); + if (!copy->right) { + SequenceOverhangsFree(copy); + Blast_HSPFree(retval); + } + memcpy(copy->right, old->right, + copy->right_len * sizeof(Uint1)); + } + + retval->map_info->subject_overhangs = copy; + } + } + + /* copy phi-blast pattern data */ + if (hsp->pat_info) { + retval->pat_info = + (SPHIHspInfo*) BlastMemDup(hsp->pat_info, sizeof(SPHIHspInfo)); + } + } + + return retval; +} + /** Count the number of occurrences of pattern in sequence, which * do not overlap by more than half the pattern match length. * @param query_info Query information structure, containing pattern info. [in] @@ -559,7 +670,6 @@ Blast_HSPReevaluateWithAmbiguitiesUngapped(BlastHSP* hsp, const Uint1* query_sta sum = 0; best_q_start = best_q_end = current_q_start = query; best_s_start = best_s_end = current_s_start = subject; - index = 0; for (index = 0; index < hsp_length; ++index) { sum += matrix[*query & kResidueMask][*subject]; @@ -1028,7 +1138,7 @@ Blast_HSPGetTargetTranslation(SBlastTargetTranslation* target_t, if (target_t->partial && (start || (stop < target_t->subject_blk->length / CODON_LENGTH -3))) { - const int kMaxTranslation = 2100; /* Needs to be divisible by three (?) */ + const int kMaxTranslation = 99; /* Needs to be divisible by three (?) */ Int4 nucl_length = 0; Int4 translation_length = 0; Int4 nucl_start = 0; @@ -2035,7 +2145,7 @@ Int2 Blast_HitListMerge(BlastHitList** old_hit_list_ptr, hsplist2->hsp_max, split_offsets, contexts_per_query, chunk_overlap_size, - allow_gap); + allow_gap, FALSE); } else { Blast_HSPListAppend(hitlist1->hsplist_array + i, @@ -2632,7 +2742,7 @@ Int2 Blast_HSPListsMerge(BlastHSPList** hsp_list_ptr, BlastHSPList** combined_hsp_list_ptr, Int4 hsp_num_max, Int4 *split_offsets, Int4 contexts_per_query, Int4 chunk_overlap_size, - Boolean allow_gap) + Boolean allow_gap, Boolean short_reads) { BlastHSPList* combined_hsp_list = *combined_hsp_list_ptr; BlastHSPList* hsp_list = *hsp_list_ptr; @@ -2743,6 +2853,13 @@ Int2 Blast_HSPListsMerge(BlastHSPList** hsp_list_ptr, if (!hsp2 || hsp1->context != hsp2->context) continue; + /* Short read qureies are shorter than the overlap region and may + already have a traceback */ + if (short_reads) { + hspp2[index2] = Blast_HSPFree(hsp2); + continue; + } + /* we have to determine the starting diagonal of one HSP and the ending diagonal of the other */ @@ -3138,9 +3255,12 @@ BlastHSPResults* Blast_HSPResultsFree(BlastHSPResults* results) if (!results) return NULL; - for (index = 0; index < results->num_queries; ++index) - Blast_HitListFree(results->hitlist_array[index]); - sfree(results->hitlist_array); + if (results->hitlist_array) + { + for (index = 0; index < results->num_queries; ++index) + Blast_HitListFree(results->hitlist_array[index]); + sfree(results->hitlist_array); + } sfree(results); return NULL; } @@ -3589,7 +3709,6 @@ s_TrimResultsByTotalHSPLimitEx(BlastHSPResults* results, } qsort((void*)everything_list, total_hsp_limit, sizeof(BlastHSPwOid), s_CompareOidHSPwOid); - subj_index = 0; subj_list = NULL; for(hsp_counter = 0; hsp_counter < total_hsp_limit; ++ hsp_counter) { @@ -3655,3 +3774,51 @@ Blast_HSPResultsFromHSPStreamWithLimitEx(BlastHSPStream* hsp_stream, } return retval; } + + +BlastHSPChain* Blast_HSPChainNew(void) +{ + BlastHSPChain* chain = calloc(1, sizeof(BlastHSPChain)); + return chain; +} + +BlastHSPChain* Blast_HSPChainFree(BlastHSPChain* ch) +{ + Int4 i; + + if (!ch) { + return NULL; + } + + for (i = 0;i < ch->num_hsps;i++) { + Blast_HSPFree(ch->hsp_array[i]); + } + sfree(ch->hsp_array); + sfree(ch); + + return NULL; +} + +BlastMappingResults* Blast_MappingResultsNew(void) +{ + BlastMappingResults* retval = calloc(1, sizeof(BlastMappingResults)); + return retval; +} + +BlastMappingResults* Blast_MappingResultsFree(BlastMappingResults* results) +{ + if (!results) { + return NULL; + } + + if (results->chain_array) { + Int4 i; + for (i = 0;i < results->num_results;i++) { + Blast_HSPChainFree(results->chain_array[i]); + } + sfree(results->chain_array); + } + sfree(results); + + return NULL; +} diff --git a/c++/src/algo/blast/core/blast_hspstream.c b/c++/src/algo/blast/core/blast_hspstream.c index 897519b8..018f78c6 100644 --- a/c++/src/algo/blast/core/blast_hspstream.c +++ b/c++/src/algo/blast/core/blast_hspstream.c @@ -1,4 +1,4 @@ -/* $Id: blast_hspstream.c 419225 2013-11-22 17:08:29Z camacho $ +/* $Id: blast_hspstream.c 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -32,11 +32,6 @@ * pass on to the traceback stage. */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_hspstream.c 419225 2013-11-22 17:08:29Z camacho $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include @@ -211,6 +206,29 @@ void BlastHSPStreamClose(BlastHSPStream* hsp_stream) hsp_stream->x_lock = MT_LOCK_Delete(hsp_stream->x_lock); } +void BlastHSPStreamMappingClose(BlastHSPStream* hsp_stream, + BlastMappingResults* results) +{ + if (!hsp_stream || !hsp_stream->writer) + return; + + (hsp_stream->writer->FinalFnPtr) + (hsp_stream->writer->data, results); + + hsp_stream->writer_finalized = TRUE; + hsp_stream->x_lock = MT_LOCK_Delete(hsp_stream->x_lock); +} + +void BlastHSPStreamSimpleClose(BlastHSPStream* hsp_stream) +{ + if (!hsp_stream) + return; + + s_FinalizeWriter(hsp_stream); + + hsp_stream->x_lock = MT_LOCK_Delete(hsp_stream->x_lock); +} + /** Closing the HSP after traceback is done. * This is mainly to provide a chance to apply post-traceback pipes. * @param hsp_stream The HSP stream to close [in] [out] @@ -644,6 +662,9 @@ BlastHSPStreamNew(EBlastProgramType program, hsp_stream->sorted_hsplists = (BlastHSPList **)malloc( hsp_stream->num_hsplists_alloc * sizeof(BlastHSPList *)); + + /* FIXME: This will not be needed for mapper when the new mapping + results structure is implemented */ hsp_stream->results = Blast_HSPResultsNew(num_queries); hsp_stream->results_sorted = FALSE; @@ -721,11 +742,13 @@ int BlastHSPStreamRegisterPipe(BlastHSPStream* hsp_stream, BlastHSPWriter* BlastHSPWriterNew (BlastHSPWriterInfo** writer_info, - BlastQueryInfo* query_info) + BlastQueryInfo* query_info, + BLAST_SequenceBlk* query) { BlastHSPWriter * writer = NULL; if(writer_info && *writer_info) { - writer = ((*writer_info)->NewFnPtr) ((*writer_info)->params, query_info); + writer = ((*writer_info)->NewFnPtr) ((*writer_info)->params, query_info, + query); sfree(*writer_info); } ASSERT(writer_info && *writer_info == NULL); diff --git a/c++/src/algo/blast/core/blast_hspstream_mt_utils.c b/c++/src/algo/blast/core/blast_hspstream_mt_utils.c index e46e3e59..b5eb867f 100644 --- a/c++/src/algo/blast/core/blast_hspstream_mt_utils.c +++ b/c++/src/algo/blast/core/blast_hspstream_mt_utils.c @@ -1,4 +1,4 @@ -/* $Id: blast_hspstream_mt_utils.c 496008 2016-03-23 11:29:15Z ivanov $ +/* $Id: blast_hspstream_mt_utils.c 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -32,11 +32,6 @@ * with the BlastHSPStream */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_hspstream_mt_utils.c 496008 2016-03-23 11:29:15Z ivanov $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include "blast_hspstream_mt_utils.h" /** Reset and free the BlastHSPStreamResultBatch structures contained in the diff --git a/c++/src/algo/blast/core/blast_hspstream_mt_utils.h b/c++/src/algo/blast/core/blast_hspstream_mt_utils.h index cc752e44..13e5474d 100644 --- a/c++/src/algo/blast/core/blast_hspstream_mt_utils.h +++ b/c++/src/algo/blast/core/blast_hspstream_mt_utils.h @@ -1,4 +1,4 @@ -/* $Id: blast_hspstream_mt_utils.h 496008 2016-03-23 11:29:15Z ivanov $ +/* $Id: blast_hspstream_mt_utils.h 495576 2016-03-18 14:26:46Z rackerst $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/algo/blast/core/blast_itree.c b/c++/src/algo/blast/core/blast_itree.c index f0c5a322..b2681963 100644 --- a/c++/src/algo/blast/core/blast_itree.c +++ b/c++/src/algo/blast/core/blast_itree.c @@ -1,4 +1,4 @@ -/* $Id: blast_itree.c 358499 2012-04-03 14:48:04Z coulouri $ +/* $Id: blast_itree.c 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -31,11 +31,6 @@ * Functions that implement an interval tree for fast HSP containment tests */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_itree.c 358499 2012-04-03 14:48:04Z coulouri $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include "blast_itree.h" #include "blast_gapalign_priv.h" #include "blast_hits_priv.h" diff --git a/c++/src/algo/blast/core/blast_kappa.c b/c++/src/algo/blast/core/blast_kappa.c index 8a37d1a0..0368bf3c 100644 --- a/c++/src/algo/blast/core/blast_kappa.c +++ b/c++/src/algo/blast/core/blast_kappa.c @@ -1,4 +1,4 @@ -/* $Id: blast_kappa.c 500367 2016-05-04 12:06:01Z ivanov $ +/* $Id: blast_kappa.c 516336 2016-10-12 17:31:41Z ivanov $ * ========================================================================== * * PUBLIC DOMAIN NOTICE @@ -32,11 +32,6 @@ * system for each match in blastpgp */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = -"$Id: blast_kappa.c 500367 2016-05-04 12:06:01Z ivanov $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include @@ -358,6 +353,12 @@ s_HSPListFromDistinctAlignments(BlastHSPList *hsp_list, return 0; } +Int4 s_GetSubjectLength(Int4 total_subj_length, EBlastProgramType program_number) +{ + return ((program_number == eBlastTypeRpsTblastn) ? + (GET_NUCL_LENGTH(total_subj_length) - 1 ) /3 : total_subj_length); +} + /** * Adding evalues to a list of HSPs and remove those that do not have @@ -404,8 +405,11 @@ s_HitlistEvaluateAndPurge(int * pbestScore, double *pbestEvalue, subject_length, sbp, hitParams->link_hsp_params, TRUE); } else { + + status = - Blast_HSPListGetEvalues(program_number, queryInfo, subject_length, + Blast_HSPListGetEvalues(program_number, queryInfo, + s_GetSubjectLength(subject_length, program_number), hsp_list, TRUE, FALSE, sbp, 0.0, /* use a non-zero gap decay only when linking HSPs */ @@ -478,10 +482,14 @@ s_ComputeNumIdentities(const BLAST_SequenceBlk* query_blk, if (program_number == eBlastTypeTblastn) { subject_blk = seq_arg.seq; - BlastTargetTranslationNew(subject_blk, gen_code_string, eBlastTypeTblastn, - kIsOutOfFrame, &target_t); - } - else { + BlastTargetTranslationNew( + subject_blk, + gen_code_string, + eBlastTypeTblastn, + kIsOutOfFrame, + &target_t + ); + } else { subject = seq_arg.seq->sequence; } } else { @@ -1568,6 +1576,9 @@ s_SequenceGetProteinRange(const BlastCompo_MatchingSequence * self, BlastKappa_SequenceInfo * local_data = self->local_data; BLAST_SequenceBlk * seq = self->local_data; + if (self->local_data == NULL) + return -1; + seqData->data = NULL; seqData->length = 0; /* Copy the entire sequence (necessary for SEG filtering.) */ @@ -1582,14 +1593,19 @@ s_SequenceGetProteinRange(const BlastCompo_MatchingSequence * self, origData = (self->index >= 0) ? local_data->seq_arg.seq->sequence : seq->sequence; + if((self->index < 0) && (align->frame != 0)) { + int i=0, offsets =0; + int f = GET_SEQ_FRAME(align->frame); + int nucl_length = GET_NUCL_LENGTH(self->length); + seqData->length = GET_TRANSLATED_LENGTH(nucl_length, f); + for(; i < f; i++) { + offsets = GET_TRANSLATED_LENGTH(nucl_length, i) +1; + origData += offsets; + } + } + /* Copy the sequence data */ for (idx = 0; idx < seqData->length; idx++) { - /* Copy the sequence data, replacing occurrences of amino acid - * number 24 (Selenocysteine) with number 3 (Cysteine). */ - if (origData[idx] != 24) { - seqData->data[idx] = origData[idx]; - } else { - seqData->data[idx] = 3; - } + seqData->data[idx] = origData[idx]; } if ( !(KAPPA_BLASTP_NO_SEG_SEQUENCE) ) { @@ -1884,6 +1900,7 @@ s_RedoOneAlignment(BlastCompo_Alignment * in_align, BlastGapAlignStruct* gapAlign = context->gap_align; /* The preliminary gapped HSP that were are recomputing */ BlastHSP * hsp = in_align->context; + Boolean fence_hit = FALSE; /* suppress unused parameter warnings; this is a callback function, so these parameter cannot be deleted */ @@ -1896,6 +1913,10 @@ s_RedoOneAlignment(BlastCompo_Alignment * in_align, gapAlign->gap_x_dropoff = gapping_params->x_dropoff; + /* + * Previously, last argument was NULL which could cause problems for + * tblastn. + */ status = BLAST_GappedAlignmentWithTraceback(context->prog_number, query_data->data, @@ -1904,7 +1925,7 @@ s_RedoOneAlignment(BlastCompo_Alignment * in_align, q_start, s_start, query_data->length, subject_data->length, - NULL); + &fence_hit); if (status == 0) { return s_NewAlignmentFromGapAlign(gapAlign, &gapAlign->edit_script, query_range, subject_range, @@ -2329,11 +2350,12 @@ s_GappingParamsNew(BlastKappa_GappingParamsContext * context, BlastCompo_GappingParams * gapping_params = NULL; gapping_params = malloc(sizeof(BlastCompo_GappingParams)); - if (gapping_params != NULL) { - gapping_params->gap_open = scoring->gap_open; - gapping_params->gap_extend = scoring->gap_extend; - gapping_params->context = context; - } + if (gapping_params == NULL) + return NULL; + + gapping_params->gap_open = scoring->gap_open; + gapping_params->gap_extend = scoring->gap_extend; + gapping_params->context = context; for (i = 0; i < num_queries; i++) { if (context->sbp->kbp_gap[i] != NULL && @@ -2360,7 +2382,7 @@ redo_align_callbacks = { /* Bit score per alignment position threshold for preliminaru near identical test */ -#define NEAR_IDENTICAL_BITS_PER_POSITION (1.75) +#define NEAR_IDENTICAL_BITS_PER_POSITION (1.74) /** * Read the parameters required for the Blast_RedoOneMatch* functions from @@ -2384,7 +2406,7 @@ s_GetAlignParams(BlastKappa_GappingParamsContext * context, Blast_MatrixInfo * scaledMatrixInfo; /* information about the scoring matrix */ /* does this kind of search translate the database sequence */ - int subject_is_translated = context->prog_number == eBlastTypeTblastn; + int subject_is_translated = (context->prog_number == eBlastTypeTblastn) || (context->prog_number == eBlastTypeRpsTblastn); int query_is_translated = context->prog_number == eBlastTypeBlastx; /* is this a positiion-based search */ Boolean positionBased = (Boolean) (context->sbp->psi_matrix != NULL); @@ -2997,7 +3019,10 @@ Blast_RedoAlignmentCore_MT(EBlastProgramType program_number, BlastHSPResults* local_results = NULL; BlastCompo_QueryInfo** query_info_tld = NULL; + int* numContexts_tld = NULL; + int* compositionTestIndex_tld = NULL; Blast_RedoAlignParams** redo_align_params_tld = NULL; + BLAST_SequenceBlk** subjectBlk_tld = NULL; Boolean positionBased = (Boolean) (sbp->psi_matrix != NULL); ECompoAdjustModes compo_adjust_mode = (ECompoAdjustModes) extendParams->options->compositionBasedStats; @@ -3013,7 +3038,8 @@ Blast_RedoAlignmentCore_MT(EBlastProgramType program_number, program_number == eBlastTypeTblastn || program_number == eBlastTypeBlastx || program_number == eBlastTypePsiBlast || - program_number == eBlastTypeRpsBlast); + program_number == eBlastTypeRpsBlast || + program_number == eBlastTypeRpsTblastn); if (0 == strcmp(scoringParams->options->matrix, "BLOSUM62_20") && compo_adjust_mode == eNoCompositionBasedStats) { @@ -3145,6 +3171,11 @@ Blast_RedoAlignmentCore_MT(EBlastProgramType program_number, sizeof(Blast_CompositionWorkspace*) ); + subjectBlk_tld = + (BLAST_SequenceBlk**) calloc( + actual_num_threads, + sizeof(BLAST_SequenceBlk*) + ); redo_align_params_tld = (Blast_RedoAlignParams**) calloc( actual_num_threads, @@ -3185,6 +3216,16 @@ Blast_RedoAlignmentCore_MT(EBlastProgramType program_number, actual_num_threads, sizeof(BlastCompo_QueryInfo*) ); + numContexts_tld = + (int*) calloc( + actual_num_threads, + sizeof(int) + ); + compositionTestIndex_tld = + (int*) calloc( + actual_num_threads, + sizeof(int) + ); int i; for (i = 0; i < actual_num_threads; ++i) { @@ -3205,12 +3246,16 @@ Blast_RedoAlignmentCore_MT(EBlastProgramType program_number, sbp->number_of_contexts ); - seqsrc_tld[i] = (BlastSeqSrc*) seqSrc; - gap_align_tld[i] = + numContexts_tld[i] = numContexts; + compositionTestIndex_tld[i] = compositionTestIndex; + seqsrc_tld[i] = BlastSeqSrcCopy(seqSrc); + gap_align_tld[i] = s_BlastGapAlignStruct_Copy(gapAlign, sbp_tld[i]); - score_params_tld[i] = scoringParams; - hit_params_tld[i] = (BlastHitSavingParameters*) hitParams; - results_tld[i] = Blast_HSPResultsNew(queryInfo->num_queries); + score_params_tld[i] = scoringParams; + hit_params_tld[i] = (BlastHitSavingParameters*) hitParams; + results_tld[i] = + Blast_HSPResultsNew(queryInfo->num_queries); + subjectBlk_tld[i] = subjectBlk; redoneMatches_tld[i] = (BlastCompo_Heap*) calloc(numQueries, sizeof(BlastCompo_Heap)); @@ -3359,323 +3404,335 @@ Blast_RedoAlignmentCore_MT(EBlastProgramType program_number, } Boolean interrupt = FALSE; - int b; -#pragma omp parallel for default(none) num_threads(actual_num_threads) \ - schedule(static) \ - if(actual_num_threads>1) \ - shared(interrupt, seqsrc_tld, score_params_tld, hit_params_tld, \ - gap_align_tld, results_tld, \ - redoneMatches_tld, \ - numQueries, numMatches, theseMatches, \ - numFrames, program_number, subjectBlk, positionBased, \ - default_db_genetic_code, localScalingFactor, queryInfo, \ - sbp, smithWaterman, compositionTestIndex, forbidden, \ - NRrecord_tld, actual_num_threads, sbp_tld, \ - matrix_tld, query_info_tld, numContexts, \ - genetic_code_string, queryBlk, compo_adjust_mode, \ - alignments_tld, incoming_align_set_tld, savedParams_tld, \ - scoringParams, redo_align_params_tld, \ - status_code_tld) - for (b = 0; b < numMatches; ++b) { +#pragma omp parallel \ + default(none) num_threads(actual_num_threads) \ + if(actual_num_threads>1) \ + shared(interrupt, seqsrc_tld, score_params_tld, hit_params_tld, \ + gap_align_tld, results_tld, \ + redoneMatches_tld, \ + stderr, \ + numQueries, numMatches, theseMatches, \ + numFrames, program_number, subjectBlk_tld, positionBased, \ + default_db_genetic_code, localScalingFactor, queryInfo, \ + sbp, smithWaterman, compositionTestIndex_tld, forbidden, \ + NRrecord_tld, actual_num_threads, sbp_tld, \ + matrix_tld, query_info_tld, numContexts_tld, \ + genetic_code_string, queryBlk, compo_adjust_mode, \ + alignments_tld, incoming_align_set_tld, savedParams_tld, \ + scoringParams, redo_align_params_tld, \ + status_code_tld) + { + int b; +#pragma omp for schedule(static) + for (b = 0; b < numMatches; ++b) { #pragma omp flush(interrupt) - if (!interrupt) { - BlastCompo_Alignment** alignments = NULL; - BlastCompo_Alignment** incoming_align_set = NULL; - Blast_CompositionWorkspace* NRrecord = NULL; - BlastCompo_QueryInfo* query_info = NULL; - - int numAligns[6]; - Blast_KarlinBlk* kbp = NULL; - BlastCompo_MatchingSequence matchingSeq = {0,}; - BlastHSPList* hsp_list = NULL; - BlastCompo_Alignment* incoming_aligns = NULL; - Blast_RedoAlignParams* redo_align_params; - double best_evalue; - Int4 best_score; - int query_index; - int context_index; - int frame_index; - void* discarded_aligns = NULL; - int tid = 0; - BlastSeqSrc* seqSrc; - BlastScoringParameters* scoringParams; - BlastHitSavingParameters* hitParams; - BlastCompo_Heap* redoneMatches; - BlastScoreBlk* sbp; - /* existing alignments for a match */ - Int4** matrix; /* score matrix */ - int* pStatusCode; - - double pvalueForThisPair = (-1); /* p-value for this match - for composition; -1 == no adjustment*/ - double LambdaRatio; /*lambda ratio*/ - + if (!interrupt) { + BlastCompo_Alignment** alignments = NULL; + BlastCompo_Alignment** incoming_align_set = NULL; + Blast_CompositionWorkspace* NRrecord = NULL; + BlastCompo_QueryInfo* query_info = NULL; + + int numAligns[6]; + Blast_KarlinBlk* kbp = NULL; + BlastCompo_MatchingSequence matchingSeq = {0,}; + BlastHSPList* hsp_list = NULL; + BlastCompo_Alignment* incoming_aligns = NULL; + Blast_RedoAlignParams* redo_align_params; + double best_evalue; + Int4 best_score; + int query_index; + int context_index; + int frame_index; + void* discarded_aligns = NULL; + BlastSeqSrc* seqSrc; + BlastScoringParameters* scoringParams; + BlastHitSavingParameters* hitParams; + BlastCompo_Heap* redoneMatches; + BlastScoreBlk* sbp; + BLAST_SequenceBlk* subjectBlk; + int numContexts; + int compositionTestIndex; + /* existing alignments for a match */ + Int4** matrix; /* score matrix */ + int* pStatusCode; + + double pvalueForThisPair = (-1); /* p-value for this match + for composition; -1 == no adjustment*/ + double LambdaRatio; /*lambda ratio*/ + + int tid = 0; #ifdef _OPENMP - tid = omp_get_thread_num(); + tid = omp_get_thread_num(); #endif - seqSrc = seqsrc_tld[tid]; - scoringParams = score_params_tld[tid]; - hitParams = hit_params_tld[tid]; - redoneMatches = redoneMatches_tld[tid]; - alignments = alignments_tld[tid]; - incoming_align_set = incoming_align_set_tld[tid]; - NRrecord = NRrecord_tld[tid]; - sbp = sbp_tld[tid]; - redo_align_params = redo_align_params_tld[tid]; - matrix = matrix_tld[tid]; - pStatusCode = &status_code_tld[tid]; - query_info = query_info_tld[tid]; - - BlastHSPList* localMatch = theseMatches[b]; - - if (localMatch->hsp_array == NULL) { - if (seqSrc) { - continue; - } + seqSrc = seqsrc_tld[tid]; + scoringParams = score_params_tld[tid]; + hitParams = hit_params_tld[tid]; + redoneMatches = redoneMatches_tld[tid]; + alignments = alignments_tld[tid]; + incoming_align_set = incoming_align_set_tld[tid]; + NRrecord = NRrecord_tld[tid]; + sbp = sbp_tld[tid]; + redo_align_params = redo_align_params_tld[tid]; + matrix = matrix_tld[tid]; + pStatusCode = &status_code_tld[tid]; + query_info = query_info_tld[tid]; + numContexts = numContexts_tld[tid]; + compositionTestIndex = compositionTestIndex_tld[tid]; + subjectBlk = subjectBlk_tld[tid]; + + BlastHSPList* localMatch = theseMatches[b]; + + if (localMatch->hsp_array == NULL) { + if (seqSrc) { + continue; + } #pragma omp critical(intrpt) - interrupt = TRUE; + interrupt = TRUE; #pragma omp flush(interrupt) - continue; - } - - if (BlastCompo_EarlyTermination( - localMatch->best_evalue, - redoneMatches, - numQueries - )) { - Blast_HSPListFree(localMatch); - if (seqSrc) { continue; } + + if (BlastCompo_EarlyTermination( + localMatch->best_evalue, + redoneMatches, + numQueries + )) { + Blast_HSPListFree(localMatch); + if (seqSrc) { + continue; + } #pragma omp critical(intrpt) - interrupt = TRUE; + interrupt = TRUE; #pragma omp flush(interrupt) - continue; - } - - query_index = localMatch->query_index; - context_index = query_index * numFrames; - /* Get the sequence for this match */ - if (seqSrc && BlastSeqSrcGetSupportsPartialFetching(seqSrc)) { - BLAST_SetupPartialFetching( - program_number, - (BlastSeqSrc*) seqSrc, - (const BlastHSPList**)&localMatch, - 1 - ); - } - - if (subjectBlk) { - matchingSeq.length = subjectBlk->length; - matchingSeq.index = -1; - matchingSeq.local_data = subjectBlk; - } else { - *pStatusCode = s_MatchingSequenceInitialize( - &matchingSeq, - program_number, - seqSrc, - default_db_genetic_code, - localMatch->oid - ); - if (*pStatusCode != 0) { - /* - * some sequences may have been excluded by membit filtering - * so this is not really an exception - */ - *pStatusCode = 0; - goto match_loop_cleanup; + continue; } - } - *pStatusCode = s_ResultHspToDistinctAlign( - incoming_align_set, /* o */ - numAligns, /* o */ - localMatch->hsp_array, /* i */ - localMatch->hspcnt, /* i */ - context_index, /* i */ - queryInfo, /* i */ - localScalingFactor /* i */ - ); - if (*pStatusCode != 0) { - goto match_loop_cleanup; - } - hsp_list = Blast_HSPListNew(0); - for (frame_index = 0; - frame_index < numFrames; - frame_index++, context_index++) { - incoming_aligns = incoming_align_set[frame_index]; - if (!incoming_aligns) { - continue; + query_index = localMatch->query_index; + context_index = query_index * numFrames; + /* Get the sequence for this match */ + if (seqSrc && BlastSeqSrcGetSupportsPartialFetching(seqSrc)) { + BLAST_SetupPartialFetching( + program_number, + (BlastSeqSrc*) seqSrc, + (const BlastHSPList**)&localMatch, + 1 + ); } - /* - * All alignments in thisMatch should be to the same query - */ - kbp = sbp->kbp_gap[context_index]; - if (smithWaterman) { - *pStatusCode = - Blast_RedoOneMatchSmithWaterman( - alignments, - redo_align_params, - incoming_aligns, - numAligns[frame_index], - kbp->Lambda, - kbp->logK, - &matchingSeq, - query_info, - numQueries, - matrix, - BLASTAA_SIZE, - NRrecord, - &forbidden, - redoneMatches, - &pvalueForThisPair, - compositionTestIndex, - &LambdaRatio - ); + + if (subjectBlk) { + matchingSeq.length = subjectBlk->length; + matchingSeq.index = -1; + matchingSeq.local_data = subjectBlk; } else { - *pStatusCode = - Blast_RedoOneMatch( - alignments, // thread-local - redo_align_params, // thread-local - incoming_aligns, // thread-local - numAligns[frame_index], // local - kbp->Lambda, // thread-local - &matchingSeq, // local - -1, // const - query_info, // thread-local - numContexts, // shared - matrix, // thread-local - BLASTAA_SIZE, // const - NRrecord, // thread-local - &pvalueForThisPair, // local - compositionTestIndex, // shared - &LambdaRatio // local - ); + *pStatusCode = s_MatchingSequenceInitialize( + &matchingSeq, + program_number, + seqSrc, + default_db_genetic_code, + localMatch->oid + ); + if (*pStatusCode != 0) { + /* + * some sequences may have been excluded by membit filtering + * so this is not really an exception + */ + *pStatusCode = 0; + goto match_loop_cleanup; + } } - + *pStatusCode = s_ResultHspToDistinctAlign( + incoming_align_set, /* o */ + numAligns, /* o */ + localMatch->hsp_array, /* i */ + localMatch->hspcnt, /* i */ + context_index, /* i */ + queryInfo, /* i */ + localScalingFactor /* i */ + ); if (*pStatusCode != 0) { goto match_loop_cleanup; } - if (alignments[context_index] != NULL) { - Int2 qframe = frame_index; - if (program_number == eBlastTypeBlastx) { - if (qframe < 3) { - qframe++; - } else { - qframe = 2 - qframe; - } + hsp_list = Blast_HSPListNew(0); + for (frame_index = 0; + frame_index < numFrames; + frame_index++, context_index++) { + incoming_aligns = incoming_align_set[frame_index]; + if (!incoming_aligns) { + continue; } - *pStatusCode = - s_HSPListFromDistinctAlignments(hsp_list, - &alignments[context_index], - matchingSeq.index, - queryInfo, qframe); - if (*pStatusCode) { + /* + * All alignments in thisMatch should be to the same query + */ + kbp = sbp->kbp_gap[context_index]; + if (smithWaterman) { + *pStatusCode = + Blast_RedoOneMatchSmithWaterman( + alignments, + redo_align_params, + incoming_aligns, + numAligns[frame_index], + kbp->Lambda, + kbp->logK, + &matchingSeq, + query_info, + numQueries, + matrix, + BLASTAA_SIZE, + NRrecord, + &forbidden, + redoneMatches, + &pvalueForThisPair, + compositionTestIndex, + &LambdaRatio + ); + } else { + *pStatusCode = + Blast_RedoOneMatch( + alignments, // thread-local + redo_align_params, // thread-local + incoming_aligns, // thread-local + numAligns[frame_index], // local + kbp->Lambda, // thread-local + &matchingSeq, // thread-local + -1, // const + query_info, // thread-local + numContexts, // thread-local + matrix, // thread-local + BLASTAA_SIZE, // const + NRrecord, // thread-local + &pvalueForThisPair, // local + compositionTestIndex, // thread-local + &LambdaRatio // local + ); + } + + if (*pStatusCode != 0) { goto match_loop_cleanup; } - } - BlastCompo_AlignmentsFree(&incoming_aligns, NULL); - incoming_align_set[frame_index] = NULL; - } - if (hsp_list->hspcnt > 1) { - s_HitlistReapContained(hsp_list->hsp_array, - &hsp_list->hspcnt); - } - *pStatusCode = - s_HitlistEvaluateAndPurge(&best_score, &best_evalue, - hsp_list, - seqSrc, - matchingSeq.length, - program_number, - queryInfo, context_index, - sbp, hitParams, - pvalueForThisPair, LambdaRatio, - matchingSeq.index); - if (*pStatusCode != 0) { - goto query_loop_cleanup; - } - if (best_evalue <= hitParams->options->expect_value) { - /* The best alignment is significant */ - s_HSPListNormalizeScores(hsp_list, kbp->Lambda, kbp->logK, - localScalingFactor); - s_ComputeNumIdentities( - queryBlk, - queryInfo, - subjectBlk, - seqSrc, - hsp_list, - scoringParams->options, - genetic_code_string, - sbp - ); - if (!seqSrc) { - goto query_loop_cleanup; - } - if (BlastCompo_HeapWouldInsert( - &redoneMatches[query_index], - best_evalue, - best_score, - localMatch->oid - )) { - *pStatusCode = - BlastCompo_HeapInsert( - &redoneMatches[query_index], - hsp_list, - best_evalue, - best_score, - localMatch->oid, - &discarded_aligns - ); - if (*pStatusCode == 0) { - hsp_list = NULL; + if (alignments[context_index] != NULL) { + Int2 qframe = frame_index; + if (program_number == eBlastTypeBlastx) { + if (qframe < 3) { + qframe++; + } else { + qframe = 2 - qframe; + } + } + *pStatusCode = + s_HSPListFromDistinctAlignments(hsp_list, + &alignments[context_index], + matchingSeq.index, + queryInfo, qframe); + if (*pStatusCode) { + goto match_loop_cleanup; + } } - } else { - hsp_list = Blast_HSPListFree(hsp_list); + BlastCompo_AlignmentsFree(&incoming_aligns, NULL); + incoming_align_set[frame_index] = NULL; } - if (*pStatusCode) { + if (hsp_list->hspcnt > 1) { + s_HitlistReapContained(hsp_list->hsp_array, + &hsp_list->hspcnt); + } + *pStatusCode = + s_HitlistEvaluateAndPurge(&best_score, &best_evalue, + hsp_list, + seqSrc, + matchingSeq.length, + program_number, + queryInfo, context_index, + sbp, hitParams, + pvalueForThisPair, LambdaRatio, + matchingSeq.index); + if (*pStatusCode != 0) { goto query_loop_cleanup; } - if (discarded_aligns != NULL) { - Blast_HSPListFree(discarded_aligns); + if (best_evalue <= hitParams->options->expect_value) { + /* The best alignment is significant */ + s_HSPListNormalizeScores(hsp_list, kbp->Lambda, kbp->logK, + localScalingFactor); + s_ComputeNumIdentities( + queryBlk, + queryInfo, + subjectBlk, + seqSrc, + hsp_list, + scoringParams->options, + genetic_code_string, + sbp + ); + if (!seqSrc) { + goto query_loop_cleanup; + } + if (BlastCompo_HeapWouldInsert( + &redoneMatches[query_index], + best_evalue, + best_score, + localMatch->oid + )) { + *pStatusCode = + BlastCompo_HeapInsert( + &redoneMatches[query_index], + hsp_list, + best_evalue, + best_score, + localMatch->oid, + &discarded_aligns + ); + if (*pStatusCode == 0) { + hsp_list = NULL; + } + } else { + hsp_list = Blast_HSPListFree(hsp_list); + } + + if (*pStatusCode) { + goto query_loop_cleanup; + } + if (discarded_aligns != NULL) { + Blast_HSPListFree(discarded_aligns); + } } - } query_loop_cleanup: match_loop_cleanup: - if (seqSrc) { - localMatch = Blast_HSPListFree(localMatch); - } else { - Blast_HSPListSwap(localMatch, hsp_list); - localMatch->oid = hsp_list->oid; - } - hsp_list = Blast_HSPListFree(hsp_list); - - if (*pStatusCode != 0) { - for (context_index = 0; - context_index < numContexts; - context_index++) { - BlastCompo_AlignmentsFree( - &alignments[context_index], - s_FreeEditScript - ); + if (seqSrc) { + localMatch = Blast_HSPListFree(localMatch); + } else { + Blast_HSPListSwap(localMatch, hsp_list); + localMatch->oid = hsp_list->oid; } - } - s_MatchingSequenceRelease(&matchingSeq); - BlastCompo_AlignmentsFree(&incoming_aligns, NULL); - if (*pStatusCode != 0 || !seqSrc) { + hsp_list = Blast_HSPListFree(hsp_list); + + if (*pStatusCode != 0) { + for (context_index = 0; + context_index < numContexts; + context_index++) { + BlastCompo_AlignmentsFree( + &alignments[context_index], + s_FreeEditScript + ); + } + } + s_MatchingSequenceRelease(&matchingSeq); + BlastCompo_AlignmentsFree(&incoming_aligns, NULL); + if (*pStatusCode != 0 || !seqSrc) { #pragma omp critical(intrpt) - interrupt = TRUE; + interrupt = TRUE; #pragma omp flush(interrupt) - continue; - } + continue; + } + + } /* end of if(!interrupt) */ + } +#pragma omp barrier - } /* end of if(!interrupt) */ + /* + * end of omp parallel section + */ } - /* - * end of omp parallel section - */ function_cleanup: @@ -3800,24 +3857,31 @@ function_cleanup: sfree(incoming_align_set_tld[i]); Blast_CompositionWorkspaceFree(&NRrecord_tld[i]); s_SavedParametersFree(&savedParams_tld[i]); + BlastSeqSrcFree(seqsrc_tld[i]); } - sfree(theseMatches); - sfree(NRrecord_tld); sfree(alignments_tld); - sfree(incoming_align_set_tld); - sfree(savedParams_tld); - sfree(sbp_tld); - sfree(matrix_tld); - sfree(seqsrc_tld); + sfree(compositionTestIndex_tld); sfree(gap_align_tld); - sfree(score_params_tld); - sfree(hit_params_tld); - sfree(results_tld); sfree(gapping_params_context_tld); + sfree(hit_params_tld); + sfree(incoming_align_set_tld); + sfree(matrix_tld); + sfree(NRrecord_tld); + sfree(numContexts_tld); + sfree(query_info_tld); sfree(redo_align_params_tld); sfree(redoneMatches_tld); + sfree(results_tld); + sfree(savedParams_tld); + sfree(sbp_tld); + sfree(score_params_tld); + sfree(seqsrc_tld); sfree(status_code_tld); - sfree(query_info_tld); + sfree(subjectBlk_tld); + sfree(theseMatches); return (Int2) status_code; } + + + diff --git a/c++/src/algo/blast/core/blast_lookup.c b/c++/src/algo/blast/core/blast_lookup.c index fb36d3ab..5b7c43e3 100644 --- a/c++/src/algo/blast/core/blast_lookup.c +++ b/c++/src/algo/blast/core/blast_lookup.c @@ -1,4 +1,4 @@ -/* $Id: blast_lookup.c 94150 2006-11-22 19:39:04Z papadopo $ +/* $Id: blast_lookup.c 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -30,11 +30,6 @@ #include -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_lookup.c 94150 2006-11-22 19:39:04Z papadopo $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - void BlastLookupAddWordHit(Int4 **backbone, Int4 wordsize, Int4 charsize, Uint1* seq, Int4 query_offset) @@ -136,3 +131,194 @@ void BlastLookupIndexQueryExactMatches(Int4 **backbone, } } + +BackboneCell* BackboneCellFree(BackboneCell* cell) +{ + BackboneCell* b = cell; + while (b) { + BackboneCell* next = b->next; + if (b->offsets) { + free(b->offsets); + } + sfree(b); + b = next; + } + + return NULL; +} + +BackboneCell* BackboneCellNew(Uint4 word, Int4 offset, Int4 size) +{ + BackboneCell* cell = calloc(1, sizeof(BackboneCell)); + if (!cell) { + BackboneCellFree(cell); + return NULL; + } + + cell->offsets = malloc(size * sizeof(Int4)); + if (!cell->offsets) { + BackboneCellFree(cell); + return NULL; + } + + cell->word = word; + cell->offsets[0] = offset; + cell->num_offsets = 1; + cell->allocated = size; + + return cell; +} + +#define MAX_WORD_COUNT (10) + +/* Test whether a word count is at least one and at most MAX_WORD_COUNT. + Counts are stored in 4 bits. */ +static Boolean s_TestCounts(Uint4 word, Uint1* counts) +{ + if (!(word & 1)) { + if ((counts[word / 2] >> 4) == 0 || + (counts[word / 2] >> 4) >= MAX_WORD_COUNT) { + return FALSE; + } + } + else { + if ((counts[word / 2] & 0xf) == 0 || + (counts[word / 2] & 0xf) >= MAX_WORD_COUNT) { + return FALSE; + } + } + + return TRUE; +} + +static Int2 s_AddWordHit(BackboneCell** backbone, Int4 wordsize, + Int4 charsize, Uint1* seq, Int4 offset, + TNaLookupHashFunction hash_func, Uint4 mask, + Uint1* counts) +{ + Uint4 large_index; + Int8 index; + Int4 i; + Int4 num_collisions = 0; + + /* convert a sequence from 4NA to 2NA */ + large_index = 0; + for (i = 0;i < wordsize;i++) { + large_index = (large_index << charsize) | seq[i]; + } + + /* if filtering by database word count, then do not add words + that do not appear in the database or appear to many times */ + if (counts && !s_TestCounts(large_index, counts)) { + return 0; + } + + index = (Int8)hash_func((Uint1*)&large_index, mask); + + /* if the hash table entry is emtpy, create a new cell */ + if (!backbone[index]) { + Int4 size = 8; + backbone[index] = BackboneCellNew(large_index, offset, size); + if (!backbone[index]) { + return -1; + } + } + else { + /* otherwiose check if the word was already added */ + + BackboneCell* b = backbone[index]; + while (b->next && b->word != large_index) { + b = b->next; + } + + /* if word was already added, add the new offset to an existing cell */ + if (b->word == large_index) { + if (b->num_offsets >= b->allocated) { + Int4 new_size = b->allocated * 2; + b->offsets = realloc(b->offsets, new_size * sizeof(Int4)); + if (!b->offsets) { + return -1; + } + b->allocated = new_size; + } + b->offsets[b->num_offsets++] = offset; + } + else { + /* otherwise creare a new cell */ + + Int4 size = 8; + ASSERT(!b->next); + b->next = BackboneCellNew(large_index, offset, size); + if (!b->next) { + return -1; + } + + num_collisions++; + } + } + + return 0; +} + +void BlastHashLookupIndexQueryExactMatches(BackboneCell **backbone, + Int4 word_length, + Int4 charsize, + Int4 lut_word_length, + BLAST_SequenceBlk* query, + BlastSeqLoc* locations, + TNaLookupHashFunction hash_func, + Uint4 mask, + Uint1* counts) +{ + BlastSeqLoc *loc; + Int4 offset; + Uint1 *seq; + Uint1 *word_target; + Uint1 invalid_mask = 0xff << charsize; + + for (loc = locations; loc; loc = loc->next) { + Int4 from = loc->ssr->left; + Int4 to = loc->ssr->right; + + /* if this location is too small to fit a complete word, skip the + location */ + + if (word_length > to - from + 1) + continue; + + /* Indexing proceeds from the start point to the last offset + such that a full lookup table word can be created. word_target + points to the letter beyond which indexing is allowed */ + seq = query->sequence + from; + word_target = seq + lut_word_length; + + for (offset = from; offset <= to; offset++, seq++) { + + if (seq >= word_target) { + s_AddWordHit(backbone, + lut_word_length, charsize, + seq - lut_word_length, + offset - lut_word_length, + hash_func, mask, + counts); + } + + /* if the current word contains an ambiguity, skip all the + words that would contain that ambiguity */ + if (*seq & invalid_mask) + word_target = seq + lut_word_length + 1; + } + + /* handle the last word, without loading *seq */ + if (seq >= word_target) { + s_AddWordHit(backbone, + lut_word_length, charsize, + seq - lut_word_length, + offset - lut_word_length, + hash_func, mask, + counts); + } + + } +} + diff --git a/c++/src/algo/blast/core/blast_message.c b/c++/src/algo/blast/core/blast_message.c index e0d4b184..6271a291 100644 --- a/c++/src/algo/blast/core/blast_message.c +++ b/c++/src/algo/blast/core/blast_message.c @@ -1,4 +1,4 @@ -/* $Id: blast_message.c 442874 2014-08-07 19:26:31Z camacho $ +/* $Id: blast_message.c 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -29,11 +29,6 @@ * the BLAST code as a wrapper for error and warning messages. */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_message.c 442874 2014-08-07 19:26:31Z camacho $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include diff --git a/c++/src/algo/blast/core/blast_nalookup.c b/c++/src/algo/blast/core/blast_nalookup.c index e81c82b4..2e19c29a 100644 --- a/c++/src/algo/blast/core/blast_nalookup.c +++ b/c++/src/algo/blast/core/blast_nalookup.c @@ -1,4 +1,4 @@ -/* $Id: blast_nalookup.c 435845 2014-05-21 14:12:49Z fongah2 $ +/* $Id: blast_nalookup.c 506275 2016-07-06 14:42:04Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -34,11 +34,6 @@ #include #include -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_nalookup.c 435845 2014-05-21 14:12:49Z fongah2 $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - /** bitfield used to detect ambiguities in uncompressed * nucleotide letters */ @@ -71,6 +66,14 @@ BlastChooseNaLookupTable(const LookupTableOptions* lookup_options, return eMBLookupTable; } + /* always use megablast lookup table and word size 16 for mapping */ + if (Blast_ProgramIsMapping(lookup_options->program_number) && + lookup_options->word_size >= 16) { + + *lut_width = 16; + return eMBLookupTable; + } + switch(lookup_options->word_size) { case 4: case 5: @@ -810,6 +813,115 @@ s_FillDiscMBTable(BLAST_SequenceBlk* query, BlastSeqLoc* location, return 0; } +static Int2 +s_FillPV(BLAST_SequenceBlk* query, + BlastSeqLoc* location, + BlastMBLookupTable* mb_lt, + const LookupTableOptions* lookup_options) + +{ + BlastSeqLoc* loc; + /* 12-mers (or perhaps 8-mers) are used to build the lookup table + and this is what kLutWordLength specifies. */ + const Int4 kLutWordLength = mb_lt->lut_word_length; + const Int8 kLutMask = mb_lt->hashsize - 1; + /* The user probably specified a much larger word size (like 28) + and this is what full_word_size is. */ + Int4 full_word_size = mb_lt->word_length; + Int4 index; + PV_ARRAY_TYPE *pv_array; + Int4 pv_array_bts; + + ASSERT(mb_lt); + + pv_array = mb_lt->pv_array; + pv_array_bts = mb_lt->pv_array_bts; + + for (loc = location; loc; loc = loc->next) { + /* We want index to be always pointing to the start of the word. + Since sequence pointer points to the end of the word, subtract + word length from the loop boundaries. */ + Int4 from = loc->ssr->left; + Int4 to = loc->ssr->right - kLutWordLength; + Int8 ecode = 0; + Int4 last_offset; + Uint1* pos; + Uint1* seq; + Uint1 val; +// int counter = 1; /* collect this many adjacent words */ + + /* case of unmasked region >= kLutWordLength but < full_word_size, + so no hits should be generated. */ + if (full_word_size > (loc->ssr->right - loc->ssr->left + 1)) + continue; + + seq = query->sequence_start + from; + pos = seq + kLutWordLength; + + /* Also add 1 to all indices, because lookup table indices count + from 1. */ + from -= kLutWordLength - 2; + last_offset = to + 2; + + for (index = from; index <= last_offset; index++) { + val = *++seq; + /* if an ambiguity is encountered, do not add + any words that would contain it */ + if ((val & BLAST2NA_MASK) != 0) { + ecode = 0; + pos = seq + kLutWordLength; + continue; + } + + /* get next base */ + ecode = ((ecode << BITS_PER_NUC) & kLutMask) + val; + if (seq < pos) + continue; + + PV_SET(pv_array, ecode, pv_array_bts); + } + } + + return 0; +} + + +/* Remove words that appear in polyA tails from the lookup table: string of As, + string of Ts, and As and Ts with one error. */ +static Int2 s_RemovePolyAWords(BlastMBLookupTable* mb_lt) +{ + Int4 word_size = mb_lt->lut_word_length; + Int8 word; + Int4 i, k; + + ASSERT(word_size == 16); + + /* remove As and Ts */ + mb_lt->hashtable[0] = 0; + mb_lt->hashtable[(Int8)0xffffffff] = 0; + + /* remove As with a single error */ + for (i = 1;i < 4;i++) { + word = i; + for (k = 0;k < word_size;k++) { + mb_lt->hashtable[word << (k * 2)] = 0; + } + } + + /* remove Ts with a single error */ + for (i = 0;i < 3;i++) { + for (k = 0;k < word_size;k++) { + word = ((0xffffffff ^ (3 << k*2)) | (i << k*2)) & 0xffffffff; + mb_lt->hashtable[word] = 0; + } + } + + return 0; +} + + +#define MAX_WORD_COUNT (10) + /** Fills in the hashtable and next_pos fields of BlastMBLookupTable* * for the contiguous case. * @@ -822,14 +934,15 @@ s_FillDiscMBTable(BLAST_SequenceBlk* query, BlastSeqLoc* location, static Int2 s_FillContigMBTable(BLAST_SequenceBlk* query, BlastSeqLoc* location, - BlastMBLookupTable* mb_lt) - + BlastMBLookupTable* mb_lt, + const LookupTableOptions* lookup_options, + Uint1* counts) { BlastSeqLoc* loc; /* 12-mers (or perhaps 8-mers) are used to build the lookup table and this is what kLutWordLength specifies. */ const Int4 kLutWordLength = mb_lt->lut_word_length; - const Int4 kLutMask = mb_lt->hashsize - 1; + const Int8 kLutMask = mb_lt->hashsize - 1; /* The user probably specified a much larger word size (like 28) and this is what full_word_size is. */ Int4 full_word_size = mb_lt->word_length; @@ -845,7 +958,7 @@ s_FillContigMBTable(BLAST_SequenceBlk* query, const Int4 kCompressionFactor=2048; /* compress helper_array by this much */ Uint4 longest_chain; Uint4* helper_array; - + const Boolean kDbFilter = lookup_options->db_filter; ASSERT(mb_lt); @@ -861,17 +974,32 @@ s_FillContigMBTable(BLAST_SequenceBlk* query, if (helper_array == NULL) return -1; + /* if filtering by database word counts, then reset the pv array to avoid + too many bits set for database scanning */ + if (kDbFilter) { + memset(pv_array, 0, + (mb_lt->hashsize >> mb_lt->pv_array_bts) * PV_ARRAY_BYTES); + } + for (loc = location; loc; loc = loc->next) { /* We want index to be always pointing to the start of the word. Since sequence pointer points to the end of the word, subtract word length from the loop boundaries. */ Int4 from = loc->ssr->left; Int4 to = loc->ssr->right - kLutWordLength; - Int4 ecode = 0; + Int8 ecode = 0; Int4 last_offset; Uint1* pos; Uint1* seq; Uint1 val; +// int counter = 1; /* collect this many adjacent words */ + int shift = 0; + int pos_shift = 0; + if (lookup_options->stride > 0) { + shift = lookup_options->stride - 1; + pos_shift = kLutWordLength + 1; + } + /* case of unmasked region >= kLutWordLength but < full_word_size, so no hits should be generated. */ @@ -901,9 +1029,40 @@ s_FillContigMBTable(BLAST_SequenceBlk* query, if (seq < pos) continue; + /* if filtering by database word count, then do not add words + with too many counts */ + if (kDbFilter) { + if (!(ecode & 1)) { + if ((counts[ecode / 2] >> 4) >= MAX_WORD_COUNT) { + continue; + } + } + else { + if ((counts[ecode / 2] & 0xf) >= MAX_WORD_COUNT) { + continue; + } + } + } + + + /* collect 1 word and skip lookup_options->stride */ + + /* + if (!counter) { + pos = seq + lookup_options->stride; + counter = 1; + + continue; + } + if (lookup_options->stride) { + counter--; + } + */ + #ifdef LOOKUP_VERBOSE mb_lt->num_words_added++; #endif + if (mb_lt->hashtable[ecode] == 0) { #ifdef LOOKUP_VERBOSE mb_lt->num_unique_pos_added++; @@ -915,9 +1074,20 @@ s_FillContigMBTable(BLAST_SequenceBlk* query, } mb_lt->next_pos[index] = mb_lt->hashtable[ecode]; mb_lt->hashtable[ecode] = index; + + /* skip shift words */ + index += shift; + seq += shift; + pos = seq + pos_shift; } } + /* FIXME: should this be done only for spliced reads? */ + if (Blast_ProgramIsMapping(lookup_options->program_number) && + mb_lt->lut_word_length == 16) { + s_RemovePolyAWords(mb_lt); + } + longest_chain = 2; for (index = 0; index < mb_lt->hashsize / kCompressionFactor; index++) longest_chain = MAX(longest_chain, helper_array[index]); @@ -928,13 +1098,123 @@ s_FillContigMBTable(BLAST_SequenceBlk* query, } +/** Scan a subject sequecne and update words counters, for 16-base words with + * scan step of 1. The counters are 4-bit and counting is done up to 10. + * + * @param sequence Subject sequence [in] + * @param mb_lt Megablast lookup table [in|out] + * @param counts Word counters [in|out] + */ +static Int2 +s_MBCountWordsInSubject_16_1(const BLAST_SequenceBlk* sequence, + BlastMBLookupTable* mb_lt, + Uint1* counts) +{ + Uint1 *s; + Int4 i; + Int8 mask = mb_lt->hashsize - 1; + Int8 word, index, w; + const Int4 kNumWords + = sequence->length - mb_lt->lut_word_length; + + PV_ARRAY_TYPE* pv = mb_lt->pv_array; + Int4 pv_array_bts = mb_lt->pv_array_bts; + Int4 shift; + + if (!sequence || !counts || !mb_lt || !pv) { + return -1; + } + + ASSERT(mb_lt->lut_word_length == 16); + + /* scan the words in the sequence */ + shift = 8; + s = sequence->sequence; + w = (Int8)s[0] << 24 | (Int8)s[1] << 16 | (Int8)s[2] << 8 | s[3]; + for (i = 0;i < kNumWords;i++) { + + if (i % COMPRESSION_RATIO == 0) { + shift = 8; + w = (w << 8) | (Int8)s[i / COMPRESSION_RATIO + 4]; + } + else { + shift -= 2; + ASSERT(shift > 0); + } + + word = (w >> shift) & mask; + + /* skip words that do not appear in the query */ + if (!PV_TEST(pv, word, pv_array_bts)) { + continue; + } + + /* update the counter */ + index = word / 2; + if (word & 1) { + if ((counts[index] & 0xf) < MAX_WORD_COUNT) { + counts[index]++; + } + } + else { + if ((counts[index] >> 4) < MAX_WORD_COUNT) { + counts[index] += 1 << 4; + } + } + } + + return 0; +} + +/** Scan database sequences and count query words that appear in the database. + * Then reset pv_array bits that correspond to words that do not appear in + * in the database, or appear 10 or more times + * + * @param seq_src Source for subject sequences [in] + * @param mb_lt Megablast lookuptable [in|out] + */ +static Int2 +s_ScanSubjectForWordCounts(BlastSeqSrc* seq_src, + BlastMBLookupTable* mb_lt, + Uint1* counts) +{ + BlastSeqSrcIterator* itr; + BlastSeqSrcGetSeqArg seq_arg; + PV_ARRAY_TYPE* pv = mb_lt->pv_array; + + if (!seq_src || !pv || !counts) { + return -1; + } + + memset(&seq_arg, 0, sizeof(seq_arg)); + seq_arg.encoding = eBlastEncodingProtein; + + /* scan subject sequences and update the counters for each */ + BlastSeqSrcResetChunkIterator(seq_src); + itr = BlastSeqSrcIteratorNewEx(MAX(BlastSeqSrcGetNumSeqs(seq_src)/100,1)); + while ((seq_arg.oid = BlastSeqSrcIteratorNext(seq_src, itr)) + != BLAST_SEQSRC_EOF) { + + BlastSeqSrcGetSequence(seq_src, &seq_arg); + s_MBCountWordsInSubject_16_1(seq_arg.seq, mb_lt, counts); + BlastSeqSrcReleaseSequence(seq_src, &seq_arg); + } + + BlastSequenceBlkFree(seq_arg.seq); + BlastSeqSrcIteratorFree(itr); + + return 0; +} + + /* Documentation in mb_lookup.h */ Int2 BlastMBLookupTableNew(BLAST_SequenceBlk* query, BlastSeqLoc* location, BlastMBLookupTable** mb_lt_ptr, const LookupTableOptions* lookup_options, const QuerySetUpOptions* query_options, Int4 approx_table_entries, - Int4 lut_width) + Int4 lut_width, + BlastSeqSrc* seqsrc) { Int4 pv_size; Int2 status = 0; @@ -942,6 +1222,7 @@ Int2 BlastMBLookupTableNew(BLAST_SequenceBlk* query, BlastSeqLoc* location, const Int4 kTargetPVSize = 131072; const Int4 kSmallQueryCutoff = 15000; const Int4 kLargeQueryCutoff = 800000; + Uint1* counts = NULL; /* array of word counts */ *mb_lt_ptr = NULL; @@ -954,15 +1235,18 @@ Int2 BlastMBLookupTableNew(BLAST_SequenceBlk* query, BlastSeqLoc* location, if (mb_lt == NULL) { return -1; } - + ASSERT(lut_width >= 9); mb_lt->word_length = lookup_options->word_size; +/* mb_lt->skip = lookup_options->skip; */ + mb_lt->stride = lookup_options->stride > 0; mb_lt->lut_word_length = lut_width; - mb_lt->hashsize = 1 << (BITS_PER_NUC * mb_lt->lut_word_length); - mb_lt->hashtable = (Int4*)calloc(mb_lt->hashsize, sizeof(Int4)); + mb_lt->hashsize = 1ULL << (BITS_PER_NUC * mb_lt->lut_word_length); + + mb_lt->hashtable = (Int4*)calloc(mb_lt->hashsize, sizeof(Int4)); if (mb_lt->hashtable == NULL) { - BlastMBLookupTableDestruct(mb_lt); - return -1; + BlastMBLookupTableDestruct(mb_lt); + return -1; } if (location && @@ -983,20 +1267,44 @@ Int2 BlastMBLookupTableNew(BLAST_SequenceBlk* query, BlastSeqLoc* location, and large queries saturate it. In either case, cache is better used on something else */ - if (mb_lt->hashsize <= 8 * kTargetPVSize) - pv_size = mb_lt->hashsize >> PV_ARRAY_BTS; - else - pv_size = kTargetPVSize / PV_ARRAY_BYTES; + if (mb_lt->lut_word_length <= 12) { + if (mb_lt->hashsize <= 8 * kTargetPVSize) + pv_size = mb_lt->hashsize >> PV_ARRAY_BTS; + else + pv_size = kTargetPVSize / PV_ARRAY_BYTES; + } + else { + /* use 8M-byte pv array for large lut word (only size 16 implemented + currently) */ + pv_size = kTargetPVSize * 64 / PV_ARRAY_BYTES; + } - if(approx_table_entries <= kSmallQueryCutoff || - approx_table_entries >= kLargeQueryCutoff) { - pv_size = pv_size / 2; + if(!lookup_options->db_filter && + (approx_table_entries <= kSmallQueryCutoff || + approx_table_entries >= kLargeQueryCutoff)) { + pv_size = pv_size / 2; } + mb_lt->pv_array_bts = ilog2(mb_lt->hashsize / pv_size); mb_lt->pv_array = calloc(PV_ARRAY_BYTES, pv_size); if (mb_lt->pv_array == NULL) { - BlastMBLookupTableDestruct(mb_lt); - return -1; + BlastMBLookupTableDestruct(mb_lt); + return -1; + } + + + /* allocate word counters, to save memory we are using 4 bits per word */ + if (lookup_options->db_filter) { + counts = (Uint1*)calloc(mb_lt->hashsize / 2, sizeof(Uint1)); + if (counts == NULL) { + BlastMBLookupTableDestruct(mb_lt); + return -1; + } + } + + if (lookup_options->db_filter) { + s_FillPV(query, location, mb_lt, lookup_options); + s_ScanSubjectForWordCounts(seqsrc, mb_lt, counts); } if (lookup_options->mb_template_length > 0) { @@ -1007,9 +1315,20 @@ Int2 BlastMBLookupTableNew(BLAST_SequenceBlk* query, BlastSeqLoc* location, else { /* contiguous megablast */ mb_lt->scan_step = mb_lt->word_length - mb_lt->lut_word_length + 1; - status = s_FillContigMBTable(query, location, mb_lt); + status = s_FillContigMBTable(query, location, mb_lt, lookup_options, + counts); + + if (status) { + BlastMBLookupTableDestruct(mb_lt); + return -1; + } + } + + if (lookup_options->db_filter && counts) { + free(counts); } + if (status > 0) { BlastMBLookupTableDestruct(mb_lt); return status; @@ -1018,12 +1337,12 @@ Int2 BlastMBLookupTableNew(BLAST_SequenceBlk* query, BlastSeqLoc* location, *mb_lt_ptr = mb_lt; #ifdef LOOKUP_VERBOSE - printf("lookup table size: %d (%d letters)\n", mb_lt->hashsize, + printf("lookup table size: %ld (%d letters)\n", mb_lt->hashsize, mb_lt->lut_word_length); printf("words in table: %d\n", mb_lt->num_words_added); printf("filled entries: %d (%f%%)\n", mb_lt->num_unique_pos_added, 100.0 * mb_lt->num_unique_pos_added / mb_lt->hashsize); - printf("PV array size: %d bytes (%d table entries/bit)\n", + printf("PV array size: %d bytes (%ld table entries/bit)\n", pv_size * PV_ARRAY_BYTES, mb_lt->hashsize / (pv_size << PV_ARRAY_BTS)); printf("longest chain: %d\n", mb_lt->longest_chain); @@ -1031,6 +1350,7 @@ Int2 BlastMBLookupTableNew(BLAST_SequenceBlk* query, BlastSeqLoc* location, return 0; } + BlastMBLookupTable* BlastMBLookupTableDestruct(BlastMBLookupTable* mb_lt) { if (!mb_lt) @@ -1046,3 +1366,562 @@ BlastMBLookupTable* BlastMBLookupTableDestruct(BlastMBLookupTable* mb_lt) sfree(mb_lt); return mb_lt; } + + +/* Hash function: Fowler-Noll-Vo (FNV) hash + http://www.isthe.com/chongo/tech/comp/fnv/index.html */ +static Uint4 FNV_hash(Uint1* seq, Uint4 mask) +{ + const Uint4 fnv_prime = 16777619u; + const Uint4 fnv_offset_basis = 2166136261u; + Int4 i; + Uint4 hash; + + hash = fnv_offset_basis; + for (i = 0;i < 4;i++) { + hash *= fnv_prime; + hash ^= seq[i]; + } + + return hash & mask; +} + + +static Int2 +s_NaHashLookupFillPV(BLAST_SequenceBlk* query, + BlastSeqLoc* locations, + BlastNaHashLookupTable* lookup) +{ + BlastSeqLoc *loc; + Int4 word_length; + Int4 lut_word_length; + PV_ARRAY_TYPE* pv = NULL; + const Int4 pv_array_bts = lookup->pv_array_bts; + + ASSERT(lookup); + + word_length = lookup->word_length; + lut_word_length = lookup->lut_word_length; + pv = lookup->pv; + ASSERT(pv); + + for (loc = locations; loc; loc = loc->next) { + /* We want index to be always pointing to the start of the word. + Since sequence pointer points to the end of the word, subtract + word length from the loop boundaries. */ + Int4 from = loc->ssr->left; + Int4 to = loc->ssr->right; + Uint4 ecode = 0; + Uint1* pos; + Uint1* seq; + Uint1* end; + Uint1 base; + + /* case of unmasked region >= kLutWordLength but < full_word_size, + so no hits should be generated. */ + if (word_length > (loc->ssr->right - loc->ssr->left + 1)) { + continue; + } + + seq = query->sequence + from; + pos = seq + lut_word_length - 1; + end = query->sequence + to + 1; + + for (; seq < end; seq++) { + + base = *seq; + /* if an ambiguity is encountered, do not add + any words that would contain it */ + if ((base & BLAST2NA_MASK) != 0) { + ecode = 0; + pos = seq + lut_word_length; + continue; + } + + /* get next base */ + ecode = (ecode << BITS_PER_NUC) | base; + if (seq < pos) { + continue; + } + + PV_SET(pv, (Int8)ecode, pv_array_bts); + } + } + + return 0; +} + + +/** Scan a subject sequecne and update words counters, for 16-base words with + * scan step of 1. The counters are 4-bit and counting is done up to 10. + * + * @param sequence Subject sequence [in] + * @param lookup Hashed lookup table [in|out] + * @param counts Word counters [in|out] + */ +static Int2 +s_NaHashLookupCountWordsInSubject_16_1(const BLAST_SequenceBlk* sequence, + BlastNaHashLookupTable* lookup, + Uint1* counts) +{ + Uint1 *s; + Int4 i; + Int8 mask = (1ULL << (16 * BITS_PER_NUC)) - 1; + Int8 word, index, w; + const Int4 kNumWords + = sequence->length - lookup->lut_word_length; + + PV_ARRAY_TYPE* pv = lookup->pv; + Int4 pv_array_bts = lookup->pv_array_bts; + Int4 shift; + + if (!sequence || !counts || !lookup || !pv) { + return -1; + } + + ASSERT(lookup->lut_word_length == 16); + + /* scan the words in the sequence */ + shift = 8; + s = sequence->sequence; + w = (Int8)s[0] << 24 | (Int8)s[1] << 16 | (Int8)s[2] << 8 | s[3]; + for (i = 0;i < kNumWords;i++) { + + if (i % COMPRESSION_RATIO == 0) { + shift = 8; + w = (w << 8) | (Int8)s[i / COMPRESSION_RATIO + 4]; + } + else { + shift -= 2; + ASSERT(shift > 0); + } + + word = (w >> shift) & mask; + + /* skip words that do not appear in the query */ + if (!PV_TEST(pv, word, pv_array_bts)) { + continue; + } + + /* update the counter */ + index = word / 2; + if (word & 1) { + if ((counts[index] & 0xf) < MAX_WORD_COUNT) { + counts[index]++; + } + } + else { + if ((counts[index] >> 4) < MAX_WORD_COUNT) { + counts[index] += 1 << 4; + } + } + } + + return 0; +} + +/** Scan database sequences and count query words that appear in the database. + * Then reset pv_array bits that correspond to words that do not appear in + * in the database, or appear 10 or more times + * + * @param seq_src Source for subject sequences [in] + * @param lookup Hashed lookuptable [in|out] + */ +static Int2 +s_NaHashLookupScanSubjectForWordCounts(BlastSeqSrc* seq_src, + BlastNaHashLookupTable* lookup, + Uint1* counts) +{ + BlastSeqSrcIterator* itr; + BlastSeqSrcGetSeqArg seq_arg; + + if (!seq_src || !lookup || !lookup->pv || !counts) { + return -1; + } + + memset(&seq_arg, 0, sizeof(seq_arg)); + seq_arg.encoding = eBlastEncodingProtein; + + /* scan subject sequences and update the counters for each */ + BlastSeqSrcResetChunkIterator(seq_src); + itr = BlastSeqSrcIteratorNewEx(MAX(BlastSeqSrcGetNumSeqs(seq_src)/100,1)); + while ((seq_arg.oid = BlastSeqSrcIteratorNext(seq_src, itr)) + != BLAST_SEQSRC_EOF) { + + BlastSeqSrcGetSequence(seq_src, &seq_arg); + s_NaHashLookupCountWordsInSubject_16_1(seq_arg.seq, lookup, counts); + BlastSeqSrcReleaseSequence(seq_src, &seq_arg); + } + + BlastSequenceBlkFree(seq_arg.seq); + BlastSeqSrcIteratorFree(itr); + + return 0; +} + + +static void s_NaHashLookupRemoveWordFromThinBackbone( + BackboneCell** thin_backbone, + Uint4 word, + TNaLookupHashFunction hash_func, + Uint4 mask) +{ + BackboneCell* prev = NULL; + BackboneCell* next = NULL; + BackboneCell* b = NULL; + Int8 index = hash_func((Uint1*)&word, mask); + + if (!thin_backbone[index]) { + return; + } + + /* if word present in the first enrty for the hashed value */ + if (thin_backbone[index]->word == word) { + next = thin_backbone[index]->next; + thin_backbone[index]->next = NULL; + BackboneCellFree(thin_backbone[index]); + thin_backbone[index] = next; + + return; + } + + /* in case of a collision check the remaining words with the same hash + value */ + prev = thin_backbone[index]; + b = thin_backbone[index]->next; + for (; b; prev = prev->next, b = b->next) { + if (b->word == word) { + next = b->next; + b->next = NULL; + BackboneCellFree(b); + prev->next = next; + + break; + } + } +} + + +static Int2 s_NaHashLookupRemovePolyAWords(BackboneCell** thin_backbone, + Int4 size, + TNaLookupHashFunction hash_func, + Uint4 mask) +{ + Int4 word_size = 16; + Int8 word; + Int4 i, k; + + ASSERT(word_size == 16); + + /* remove As and Ts */ + s_NaHashLookupRemoveWordFromThinBackbone(thin_backbone, 0, hash_func, mask); + s_NaHashLookupRemoveWordFromThinBackbone(thin_backbone, 0xffffffff, + hash_func, mask); + + /* remove As with a single error */ + for (i = 1;i < 4;i++) { + word = i; + for (k = 0;k < word_size;k++) { + s_NaHashLookupRemoveWordFromThinBackbone(thin_backbone, + word << (k * 2), + hash_func, + mask); + } + } + + /* remove Ts with a single error */ + for (i = 0;i < 3;i++) { + for (k = 0;k < word_size;k++) { + word = ((0xffffffff ^ (3 << k*2)) | (i << k*2)) & 0xffffffff; + s_NaHashLookupRemoveWordFromThinBackbone(thin_backbone, word, + hash_func, mask); + } + } + + return 0; +} + + +/** Pack the data structures comprising a nucleotide lookup table + * into their final form + * @param thin_backbone structure containing indexed query offsets [in][out] + * @param lookup the lookup table [in] + */ +static void s_BlastNaHashLookupFinalize(BackboneCell** thin_backbone, + BlastNaHashLookupTable* lookup) +{ + Int4 i; + Int4 overflow_cells_needed = 0; + Int4 overflow_cursor = 0; + Int4 longest_chain = 0; + PV_ARRAY_TYPE *pv; + const Int4 pv_array_bts = lookup->pv_array_bts; +#ifdef LOOKUP_VERBOSE + Int4 backbone_occupancy = 0; + Int4 thick_backbone_occupancy = 0; + Int4 num_overflows = 0; + Int4 words_per_hash[5] = {0,}; +#endif + + ASSERT(lookup->lut_word_length == 16); + + /* allocate the new lookup table */ + lookup->thick_backbone = (NaHashLookupBackboneCell *)calloc( + lookup->backbone_size, + sizeof(NaHashLookupBackboneCell)); + ASSERT(lookup->thick_backbone != NULL); + + pv = lookup->pv; + ASSERT(pv != NULL); + /* reset PV array, it might have been set earlier to count database words, + and a few bits may need to be reset */ + memset(pv, 0, (lookup->backbone_size >> pv_array_bts) * PV_ARRAY_BYTES); + + /* remove polyA words from the lookup table */ + s_NaHashLookupRemovePolyAWords(thin_backbone, lookup->backbone_size, + lookup->hash_callback, lookup->mask); + + /* find out how many cells are needed for the overflow array */ + for (i = 0; i < lookup->backbone_size; i++) { + BackboneCell* b = thin_backbone[i]; + Int4 num_hits = 0; + Int4 num_words = 0; + for (; b; b = b->next) { + num_hits += b->num_offsets; + num_words++; + } + + if (num_words > NA_WORDS_PER_HASH || num_hits > NA_OFFSETS_PER_HASH) { + /* +1 because we store unhashed word to resolve hash collisions + +1 for number of offsets */ + overflow_cells_needed += num_hits + (num_words * 2); + } + longest_chain = MAX(longest_chain, num_hits); + } + + lookup->longest_chain = longest_chain; + + /* allocate the overflow array */ + if (overflow_cells_needed > 0) { + lookup->overflow = (Int4*)calloc(overflow_cells_needed, sizeof(Int4)); + ASSERT(lookup->overflow != NULL); + } + + /* for each position in the lookup table backbone, */ + for (i = 0; i < lookup->backbone_size; i++) { + + Int4 num_words = 0; + Int4 num_offsets = 0; + NaHashLookupBackboneCell* cell = lookup->thick_backbone + i; + BackboneCell* head = thin_backbone[i]; + BackboneCell* b = NULL; + Boolean is_overflow = FALSE; + + if (!head) { + continue; + } + +#ifdef LOOKUP_VERBOSE + thick_backbone_occupancy++; +#endif + + /* for each cell with the same hash value in the thin backbone + count number of words and offsets stored */ + for (b = head; b; b = b->next) { + num_words++; + num_offsets += b->num_offsets; + +#ifdef LOOKUP_VERBOSE + backbone_occupancy++; +#endif + } + cell->num_words = num_words; + +#ifdef LOOKUP_VERBOSE + words_per_hash[((num_words < 6) ? num_words : 5) - 1]++; +#endif + + /* if the thin cell stores at most 3 words and 9 offsets, store them + all in the thick backbone */ + if (num_words <= NA_WORDS_PER_HASH && + num_offsets <= NA_OFFSETS_PER_HASH) { + Int4 k = 0; + Int4 n = 0; + + for (b = head; b; b = b->next, k++) { + Int4 j; + cell->words[k] = b->word; + cell->num_offsets[k] = b->num_offsets; + + PV_SET(pv, (Int8)b->word, pv_array_bts); + + for (j = 0;j < b->num_offsets;j++) { + ASSERT(n <= NA_OFFSETS_PER_HASH); + cell->offsets[n++] = b->offsets[j]; + } + } + } + /* otherwise, store them in the overflow array */ + else if (num_words <= NA_WORDS_PER_HASH) { + Int4 k = 0; + for (b = head; b; b = b->next, k++) { + cell->words[k] = b->word; + } + is_overflow = TRUE; + } + else { + is_overflow = TRUE; + } + + /* add words and offsets to overflow array: word, number of offsets, + offsets */ + if (is_overflow) { +#ifdef LOOKUP_VERBOSE + num_overflows++; +#endif + cell->offsets[0] = overflow_cursor; + for (b = head; b; b = b->next) { + Int4 j; + lookup->overflow[overflow_cursor++] = *(Int4*)(&b->word); + lookup->overflow[overflow_cursor++] = b->num_offsets; + for (j = 0;j < b->num_offsets;j++) { + lookup->overflow[overflow_cursor++] = b->offsets[j]; + } + ASSERT(overflow_cursor <= overflow_cells_needed); + PV_SET(pv, (Int8)b->word, pv_array_bts); + } + } + + /* done with this chain */ + thin_backbone[i] = BackboneCellFree(thin_backbone[i]); + } + + lookup->offsets_size = overflow_cursor; + +#ifdef LOOKUP_VERBOSE + printf("backbone size: %d\n", lookup->backbone_size); + printf("backbone occupancy: %d (%f%%)\n", backbone_occupancy, + 100.0 * backbone_occupancy / lookup->backbone_size); + printf("thick_backbone occupancy: %d (%f%%)\n", + thick_backbone_occupancy, + 100.0 * thick_backbone_occupancy / lookup->backbone_size); + printf("num_overflows: %d\n", num_overflows); + printf("\tnumber of words per hash\tcount\n"); + { + Int4 ii; + for (ii = 0;ii < 5;ii++) { + printf("\t%d\t%d\n", ii + 1, words_per_hash[ii]); + } + } + printf("overflow size: %d\n", overflow_cells_needed); + printf("longest chain: %d\n", longest_chain); +#endif +} + + +BlastNaHashLookupTable* +BlastNaHashLookupTableDestruct(BlastNaHashLookupTable* lookup) +{ + sfree(lookup->thick_backbone); + sfree(lookup->overflow); + if (lookup->masked_locations) + lookup->masked_locations = BlastSeqLocFree(lookup->masked_locations); + sfree(lookup->pv); + sfree(lookup); + + return NULL; +} + + +Int4 BlastNaHashLookupTableNew(BLAST_SequenceBlk* query, + BlastSeqLoc* locations, + BlastNaHashLookupTable** lut, + const LookupTableOptions* opt, + const QuerySetUpOptions* query_options, + BlastSeqSrc* seqsrc) +{ + BackboneCell **thin_backbone = NULL; + BlastNaHashLookupTable *lookup = *lut = + (BlastNaHashLookupTable*) calloc(1, sizeof(BlastNaHashLookupTable)); + /* Number of possible 16-base words */ + const Int8 kNumWords = (1ULL << 32); + Uint1* counts = NULL; + Int4 num_hash_bits = 24; + Int8 database_length = 0LL; + + ASSERT(lookup != NULL); + + if (opt->db_filter && !seqsrc) { + return -1; + } + + /* use more bits for hash function for larger databases to decrease number + of collisions */ + /* FIXME: number of bits may also depend on concatenated query length */ + if (seqsrc) { + database_length = BlastSeqSrcGetTotLen(seqsrc); + } + if (database_length > 500000000L) { + num_hash_bits = 25; + } + + lookup->word_length = opt->word_size; + lookup->lut_word_length = 16; + /* 16-base words are hashed to 24-bit or 25-bit values */ + lookup->backbone_size = 1 << num_hash_bits; + lookup->mask = lookup->backbone_size - 1; + lookup->overflow = NULL; + lookup->scan_step = lookup->word_length - lookup->lut_word_length + 1; + lookup->hash_callback = FNV_hash; + + thin_backbone = (BackboneCell**)calloc(lookup->backbone_size, + sizeof(BackboneCell*)); + ASSERT(thin_backbone != NULL); + + /* PV array does not use hashing, and uses 64 words per bit */ + lookup->pv_array_bts = 11; + lookup->pv = (PV_ARRAY_TYPE*)calloc(kNumWords / 64 / PV_ARRAY_BYTES, + sizeof(PV_ARRAY_TYPE)); + ASSERT(lookup->pv); + + + /* allocate word counters, to save memory we are using 4 bits per word */ + if (opt->db_filter) { + ASSERT(lookup->word_length == 16); + counts = (Uint1*)calloc(kNumWords / 2, sizeof(Uint1)); + if (counts == NULL) { + sfree(thin_backbone); + BlastNaHashLookupTableDestruct(lookup); + return -1; + } + } + + /* count words in the database */ + if (opt->db_filter) { + s_NaHashLookupFillPV(query, locations, lookup); + s_NaHashLookupScanSubjectForWordCounts(seqsrc, lookup, counts); + } + + + BlastHashLookupIndexQueryExactMatches(thin_backbone, + lookup->word_length, + BITS_PER_NUC, + lookup->lut_word_length, + query, locations, + lookup->hash_callback, + lookup->mask, + counts); + if (locations && + lookup->word_length > lookup->lut_word_length && + s_HasMaskAtHashEnabled(query_options)) { + lookup->masked_locations = s_SeqLocListInvert(locations, query->length); + } + s_BlastNaHashLookupFinalize(thin_backbone, lookup); + sfree(thin_backbone); + if (counts) { + sfree(counts); + } + + return 0; +} + diff --git a/c++/src/algo/blast/core/blast_nascan.c b/c++/src/algo/blast/core/blast_nascan.c index 626040a1..1af5e3ec 100644 --- a/c++/src/algo/blast/core/blast_nascan.c +++ b/c++/src/algo/blast/core/blast_nascan.c @@ -1,4 +1,4 @@ -/* $Id: blast_nascan.c 431697 2014-04-07 15:06:02Z madden $ +/* $Id: blast_nascan.c 505619 2016-06-27 18:51:47Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -32,11 +32,6 @@ #include #include /* for NCBI2NA_UNPACK_BASE */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_nascan.c 431697 2014-04-07 15:06:02Z madden $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - /** * Retrieve the number of query offsets associated with this subject word. * @param lookup The lookup table to read from. [in] @@ -1389,7 +1384,7 @@ static void s_SmallNaChooseScanSubject(LookupTableWrap *lookup_wrap) * @return 1 if there are hits, 0 otherwise. */ static NCBI_INLINE Int4 s_BlastMBLookupHasHits(BlastMBLookupTable * lookup, - Int4 index) + Int8 index) { PV_ARRAY_TYPE *pv = lookup->pv_array; Int4 pv_array_bts = lookup->pv_array_bts; @@ -1409,7 +1404,7 @@ static NCBI_INLINE Int4 s_BlastMBLookupHasHits(BlastMBLookupTable * lookup, * @return The number of hits copied. */ static NCBI_INLINE Int4 s_BlastMBLookupRetrieve(BlastMBLookupTable * lookup, - Int4 index, + Int8 index, BlastOffsetPair * offset_pairs, Int4 s_off) { @@ -1433,7 +1428,7 @@ static NCBI_INLINE Int4 s_BlastMBLookupRetrieve(BlastMBLookupTable * lookup, * @return The number of hits copied. */ static NCBI_INLINE Int4 s_BlastMBLookupRetrieve2(BlastMBLookupTable * lookup, - Int4 index, + Int8 index, BlastOffsetPair * offset_pairs, Int4 s_off) { @@ -1493,8 +1488,8 @@ static Int4 s_MBScanSubject_Any(const LookupTableWrap* lookup_wrap, Uint1* s; Uint1* abs_start = subject->sequence; Int4 s_off; - Int4 index; - Int4 mask = mb_lt->hashsize - 1; + Int8 index; + Int8 mask = mb_lt->hashsize - 1; Int4 total_hits = 0; Int4 lut_word_length = mb_lt->lut_word_length; Int4 scan_step = mb_lt->scan_step; @@ -1503,7 +1498,8 @@ static Int4 s_MBScanSubject_Any(const LookupTableWrap* lookup_wrap, ASSERT(lut_word_length == 9 || lut_word_length == 10 || lut_word_length == 11 || - lut_word_length == 12); + lut_word_length == 12 || + lut_word_length == 16); /* Since the test for number of hits here is done after adding them, subtract the longest chain length from the allowed offset array size. */ @@ -1541,7 +1537,48 @@ static Int4 s_MBScanSubject_Any(const LookupTableWrap* lookup_wrap, } scan_range[0] = (s - abs_start)*COMPRESSION_RATIO; + } else if (lut_word_length == 16 && scan_step == 1) { + /* scan for lookup table width 16 and stride 1 */ + Int8 w; + Int4 shift; + + s = abs_start + (scan_range[0] / COMPRESSION_RATIO); + w = (Int8)s[0] << 24 | (Int8)s[1] << 16 | (Int8)s[2] << 8 | s[3]; + if (scan_range[0] % COMPRESSION_RATIO != 0) { + w = (w << 8) | (Int8)s[4]; + } + shift = 2 * (COMPRESSION_RATIO - (scan_range[0] % COMPRESSION_RATIO)); + for (; scan_range[0] <= scan_range[1]; scan_range[0] += scan_step) { + + if (scan_range[0] % COMPRESSION_RATIO == 0) { + s = abs_start + (scan_range[0] / COMPRESSION_RATIO); + w = (w << 8) | (Int8)s[4]; + shift = 8; + } + + index = (w >> shift) & mask; + + shift -= 2; + ASSERT(shift >= 0); + MB_ACCESS_HITS(); + } + + } else if (lut_word_length == 16) { + /* scan for lookup table width 16 and any stride */ + for (; scan_range[0] <= scan_range[1]; scan_range[0] += scan_step) { + + Int4 shift = 2 * (COMPRESSION_RATIO - (scan_range[0] % COMPRESSION_RATIO)); + s = abs_start + (scan_range[0] / COMPRESSION_RATIO); + Int8 w = (Int8)s[0] << 32 | (Int8)s[1] << 24 | (Int8)s[2] << 16 | + (Int8)s[3] << 8 | s[4]; + + index = (w >> shift) & mask; + + MB_ACCESS_HITS(); + } + } else if (lut_word_length > 9) { + ASSERT (lut_word_length <= 12); /* when the stride is not a multiple of 4, extra bases may occur both before and after every word read from @@ -2630,6 +2667,7 @@ static void s_MBChooseScanSubject(LookupTableWrap *lookup_wrap) break; case 12: + case 16: /* lookup tables of width 12 are only used for very large queries, and the latency of cache misses dominates the runtime in that @@ -2641,12 +2679,314 @@ static void s_MBChooseScanSubject(LookupTableWrap *lookup_wrap) } } +/** Diagnostics for scanning with NaHashLookupTable */ +typedef struct SNaHashLookupScanDiags +{ + Int4 not_pv; + Int4 not_backbone; + Int4 hits; + Int4 h_num_words[5]; + Int4 missed; + Int4 present; +} SNaHashLookupScanDiags; + + +static Int4 s_BlastNaHashLookupRetieveHits(BlastNaHashLookupTable* lookup, + Uint4 index, + Int4 s_off, + BlastOffsetPair* NCBI_RESTRICT offset_pairs, + SNaHashLookupScanDiags* diags) +{ + Int8 hashed_index; + const Int4 pv_array_bts = lookup->pv_array_bts; + const Uint4 kMask = lookup->mask; + Int4 num_hits = 0; + TNaLookupHashFunction hash_func = + (TNaLookupHashFunction)lookup->hash_callback; + + /* test word in pv array */ + if (!PV_TEST(lookup->pv, (Int8)index, pv_array_bts)) { +#ifdef SCAN_VERBOSE + diags->not_pv++; +#endif + return 0; + } + + /* access words in lookup table */ + hashed_index = hash_func((Uint1*)&index, kMask); + if (lookup->thick_backbone[hashed_index].num_words > 0) { + NaHashLookupBackboneCell* cell = + lookup->thick_backbone + hashed_index; + Int4 cursor = -1; + +#ifdef SCAN_VERBOSE + diags->hits++; + diags->h_num_words[ + ((lookup->thick_backbone[hashed_index].num_words < 5) ? + lookup->thick_backbone[hashed_index].num_words - 1 : + 4)]++; +#endif + + /* if words are in thick backbone */ + if (cell->num_words <= NA_WORDS_PER_HASH) { + Int4 i; + for (i = 0; i < cell->num_words; i++) { + + if (cell->words[i] == (Uint4)index) { + + /* if offsets are in thick backbone, access them */ + if (cell->num_offsets[i] > 0) { + /* get offsets */ + Int4 j; + Int4 start = 0; + +#ifdef SCAN_VERBOSE + diags->present++; +#endif + + for (j = 0;j < i;j++) { + start += cell->num_offsets[j]; + } + + for (j = 0;j < cell->num_offsets[i];j++) { + ASSERT(start + j <= NA_OFFSETS_PER_HASH); + offset_pairs[num_hits].qs_offsets.q_off + = cell->offsets[start + j]; + + offset_pairs[num_hits].qs_offsets.s_off + = s_off; + + ASSERT(offset_pairs[num_hits].qs_offsets.q_off + >= 0); + + num_hits++; + } + + } + else { + /* otherwise get pointer to the overflow array */ + cursor = cell->offsets[0]; + } + +#ifdef SCAN_VERBOSE + diags->missed--; +#endif + break; + } + } +#ifdef SCAN_VERBOSE + diags->missed++; +#endif + + } + else { + /* otherwise get pointer to the overflow array */ + cursor = cell->offsets[0]; + } + + /* aceess overflow array */ + if (cursor >= 0) { + Int4 k = 0; + Int4* overflow = lookup->overflow + cell->offsets[0]; + + /* cursor points to beginning of data for a given hashed + word; the data are: word, number of offsets, offsets, + next word, ... */ + for (k = 0; k < cell->num_words; k++) { + Uint4 word = *(Uint4*)(overflow); + Int4 num_offsets = overflow[1]; + Int4 i; + + if (word != index) { + overflow += num_offsets + 2; + continue; + } + +#ifdef SCAN_VERBOSE + diags->present++; +#endif + + overflow += 2; + for (i = 0;i < num_offsets;i++) { + offset_pairs[num_hits + i].qs_offsets.q_off = + overflow[i]; + + offset_pairs[num_hits + i].qs_offsets.s_off = + s_off; + + ASSERT(offset_pairs[num_hits + i]. + qs_offsets.q_off <= INT4_MAX); + } + num_hits += i; + +#ifdef SCAN_VERBOSE + diags->missed--; +#endif + break; + } +#ifdef SCAN_VERBOSE + diags->missed++; +#endif + } + } +#ifdef SCAN_VERBOSE + else { + diags->not_backbone++; + } +#endif + + return num_hits; +} + + +/** Scan the compressed subject sequence, returning 9-to-12 letter word hits + * with arbitrary stride. Assumes a megablast lookup table + * @param lookup_wrap Pointer to the (wrapper to) lookup table [in] + * @param subject The (compressed) sequence to be scanned for words [in] + * @param offset_pairs Array of query and subject positions where words are + * found [out] + * @param max_hits The allocated size of the above array - how many offsets + * can be returned [in] + * @param scan_range The starting and ending pos to be scanned [in] + * on exit, scan_range[0] is updated to be the stopping pos [out] +*/ +static Int4 s_BlastNaHashScanSubject_Any(const LookupTableWrap* lookup_wrap, + const BLAST_SequenceBlk* subject, + BlastOffsetPair* NCBI_RESTRICT offset_pairs, Int4 max_hits, + Int4* scan_range) +{ + BlastNaHashLookupTable* lookup = (BlastNaHashLookupTable*) lookup_wrap->lut; + Uint1* s; + Uint1* abs_start = subject->sequence; + Int8 mask = (1ULL << 32) - 1; + Int4 total_hits = 0; + Int4 lut_word_length = lookup->lut_word_length; + Int4 scan_step = lookup->scan_step; + SNaHashLookupScanDiags diags; + +#ifdef SCAN_VERBOSE + memset(&diags, 0, sizeof(SNaHashLookupScanDiags)); +#endif + + ASSERT(lookup_wrap->lut_type == eNaHashLookupTable); + ASSERT(lut_word_length == 16); + + /* Since the test for number of hits here is done after adding them, + subtract the longest chain length from the allowed offset array size. */ + max_hits -= lookup->longest_chain; + + if (lut_word_length == 16 && scan_step == 1) { + /* scan for lookup table width 16 and stride 1 */ + + Int8 w; + Int4 shift; + Uint4 index; + + s = abs_start + (scan_range[0] / COMPRESSION_RATIO); + w = (Int8)s[0] << 24 | (Int8)s[1] << 16 | (Int8)s[2] << 8 | s[3]; + if (scan_range[0] % COMPRESSION_RATIO != 0) { + w = (w << 8) | (Int8)s[4]; + } + shift = 2 * (COMPRESSION_RATIO - (scan_range[0] % COMPRESSION_RATIO)); + for (; scan_range[0] <= scan_range[1]; scan_range[0] += scan_step) { + + if (scan_range[0] % COMPRESSION_RATIO == 0) { + s = abs_start + (scan_range[0] / COMPRESSION_RATIO); + w = (w << 8) | (Int8)s[4]; + shift = 8; + } + + index = (Uint4)((w >> shift) & mask); + + shift -= 2; + ASSERT(shift >= 0); + + if (total_hits >= max_hits) + break; + + + total_hits += s_BlastNaHashLookupRetieveHits(lookup, index, + scan_range[0], offset_pairs + total_hits, + &diags); + } + } + else if (lut_word_length == 16) { + + Int8 w; + Int4 shift; + Uint4 index; + + for (; scan_range[0] <= scan_range[1]; scan_range[0] += scan_step) { + + s = abs_start + (scan_range[0] / COMPRESSION_RATIO); + w = (Int8)s[0] << 24 | (Int8)s[1] << 16 | (Int8)s[2] << 8 | s[3]; + if (scan_range[0] % COMPRESSION_RATIO != 0) { + w = (w << 8) | (Int8)s[4]; + shift = 2 * (COMPRESSION_RATIO - (scan_range[0] % COMPRESSION_RATIO)); + index = (Uint4)((w >> shift) & mask); + } + else { + index = (Uint4)w; + } + + if (total_hits >= max_hits) + break; + + total_hits += s_BlastNaHashLookupRetieveHits(lookup, index, + scan_range[0], offset_pairs + total_hits, + &diags); + } + } + else { + /* scanning modes with different strides are not implemented */ + ASSERT(0); + + return -1; + } + +#ifdef SCAN_VERBOSE + printf("Num words not in PV:\t%d\n", diags.not_pv); + printf("Num words not in backbone\t%d\n", diags.not_backbone); + printf("Num hash value hits in backbone:\t%d\n", diags.hits); + printf("\tNum query words with the same hash value\tCount\n"); + { + Int4 ii; + for (ii = 0;ii < 5;ii++) { + printf("\t%d\t%d\n", ii + 1, diags.h_num_words[ii]); + } + } + printf("Num backbone misses:\t%d\n", diags.missed); + printf("Num word hits:\t%d\n", diags.present); + printf("Total hits:\t%d\n", total_hits); + printf("\n"); +#endif + + return total_hits; +} + + +/** Choose the most appropriate function to scan through + * subject sequences, assuming a standard blastn lookup table + * @param lookup_wrap Structure containing lookup table [in][out] + */ +static void s_NaHashChooseScanSubject(LookupTableWrap *lookup_wrap) +{ + BlastNaHashLookupTable *lookup = (BlastNaHashLookupTable *)lookup_wrap->lut; + + ASSERT(lookup_wrap->lut_type == eNaHashLookupTable); + + lookup->scansub_callback = (void*)s_BlastNaHashScanSubject_Any; +} + + void BlastChooseNucleotideScanSubject(LookupTableWrap *lookup_wrap) { if (lookup_wrap->lut_type == eNaLookupTable) s_NaChooseScanSubject(lookup_wrap); else if (lookup_wrap->lut_type == eSmallNaLookupTable) s_SmallNaChooseScanSubject(lookup_wrap); + else if (lookup_wrap->lut_type == eNaHashLookupTable) + s_NaHashChooseScanSubject(lookup_wrap); else s_MBChooseScanSubject(lookup_wrap); } @@ -2658,6 +2998,10 @@ void * BlastChooseNucleotideScanSubjectAny(LookupTableWrap *lookup_wrap) if (lookup_wrap->lut_type == eSmallNaLookupTable) return (void *)s_BlastSmallNaScanSubject_Any; + + if (lookup_wrap->lut_type == eNaHashLookupTable) { + return (void*)s_BlastNaHashScanSubject_Any; + } return (void *)s_MBScanSubject_Any; } diff --git a/c++/src/algo/blast/core/blast_options.c b/c++/src/algo/blast/core/blast_options.c index b930f0e5..f50d59e5 100644 --- a/c++/src/algo/blast/core/blast_options.c +++ b/c++/src/algo/blast/core/blast_options.c @@ -1,4 +1,4 @@ -/* $Id: blast_options.c 493454 2016-02-26 19:57:55Z ivanov $ +/* $Id: blast_options.c 506100 2016-07-01 15:46:25Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -32,11 +32,6 @@ * */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_options.c 493454 2016-02-26 19:57:55Z ivanov $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include @@ -427,7 +422,8 @@ Int2 SBlastFilterOptionsValidate(EBlastProgramType program_number, const SBlastF if (filter_options->repeatFilterOptions) { - if (program_number != eBlastTypeBlastn) + if (program_number != eBlastTypeBlastn && + program_number != eBlastTypeMapping) { if (blast_message) Blast_MessageWrite(blast_message, eBlastSevError, kBlastMessageNoContext, @@ -446,7 +442,8 @@ Int2 SBlastFilterOptionsValidate(EBlastProgramType program_number, const SBlastF if (filter_options->dustOptions) { - if (program_number != eBlastTypeBlastn) + if (program_number != eBlastTypeBlastn && + program_number != eBlastTypeMapping) { if (blast_message) Blast_MessageWrite(blast_message, eBlastSevError, kBlastMessageNoContext, @@ -457,7 +454,8 @@ Int2 SBlastFilterOptionsValidate(EBlastProgramType program_number, const SBlastF if (filter_options->segOptions) { - if (program_number == eBlastTypeBlastn) + if (program_number == eBlastTypeBlastn && + program_number != eBlastTypeMapping) { if (blast_message) Blast_MessageWrite(blast_message, eBlastSevError, kBlastMessageNoContext, @@ -514,7 +512,8 @@ Int2 BLAST_FillQuerySetUpOptions(QuerySetUpOptions* options, if (strand_option && (program == eBlastTypeBlastn || program == eBlastTypePhiBlastn || - program == eBlastTypeBlastx || program == eBlastTypeTblastx)) { + program == eBlastTypeBlastx || program == eBlastTypeTblastx || + program == eBlastTypeMapping)) { options->strand_option = strand_option; } @@ -550,8 +549,9 @@ BlastInitialWordOptionsNew(EBlastProgramType program, if (*options == NULL) return BLASTERR_MEMORY; - if (program != eBlastTypeBlastn && - program != eBlastTypePhiBlastn) { /* protein-protein options. */ + if (/*program != eBlastTypeBlastn && + program != eBlastTypePhiBlastn */ + !Blast_ProgramIsNucleotide(program)) { /* protein-protein options. */ (*options)->window_size = BLAST_WINDOW_SIZE_PROT; (*options)->x_dropoff = BLAST_UNGAPPED_X_DROPOFF_PROT; (*options)->gap_trigger = BLAST_GAP_TRIGGER_PROT; @@ -579,6 +579,7 @@ BlastInitialWordOptionsValidate(EBlastProgramType program_number, /* PHI-BLAST has no ungapped extension phase. Megablast may not have it, but generally does now. */ if (program_number != eBlastTypeBlastn && + program_number != eBlastTypeMapping && (!Blast_ProgramIsPhiBlast(program_number)) && options->x_dropoff <= 0.0) { @@ -636,8 +637,9 @@ BlastExtensionOptionsNew(EBlastProgramType program, BlastExtensionOptions* *opti if (*options == NULL) return BLASTERR_MEMORY; - if (program != eBlastTypeBlastn && - program != eBlastTypePhiBlastn) /* protein-protein options. */ + if (/* program != eBlastTypeBlastn && + program != eBlastTypePhiBlastn*/ + !Blast_ProgramIsNucleotide(program)) /* protein-protein options. */ { (*options)->gap_x_dropoff = BLAST_GAP_X_DROPOFF_PROT; (*options)->gap_x_dropoff_final = @@ -657,6 +659,8 @@ BlastExtensionOptionsNew(EBlastProgramType program, BlastExtensionOptions* *opti (*options)->compositionBasedStats = eCompositionBasedStats; } + (*options)->max_mismatches = 5; + (*options)->mismatch_window = 10; (*options)->program_number = program; return 0; @@ -670,7 +674,8 @@ BLAST_FillExtensionOptions(BlastExtensionOptions* options, if (!options) return BLASTERR_INVALIDPARAM; - if (program == eBlastTypeBlastn || program == eBlastTypePhiBlastn) { + if (/*program == eBlastTypeBlastn || program == eBlastTypePhiBlastn*/ + Blast_ProgramIsNucleotide(program)) { if (greedy) { options->gap_x_dropoff = BLAST_GAP_X_DROPOFF_GREEDY; options->gap_x_dropoff_final = BLAST_GAP_X_DROPOFF_FINAL_NUCL; @@ -711,6 +716,7 @@ BlastExtensionOptionsValidate(EBlastProgramType program_number, return BLASTERR_INVALIDPARAM; if (program_number != eBlastTypeBlastn && + program_number != eBlastTypeMapping && (options->ePrelimGapExt == eGreedyScoreOnly || options->eTbackExt == eGreedyTbck)) { @@ -757,8 +763,9 @@ BlastScoringOptionsNew(EBlastProgramType program_number, BlastScoringOptions* *o if (*options == NULL) return BLASTERR_INVALIDPARAM; - if (program_number != eBlastTypeBlastn && - program_number != eBlastTypePhiBlastn) { /* protein-protein options. */ + if (/*program_number != eBlastTypeBlastn && + program_number != eBlastTypePhiBlastn*/ + !Blast_ProgramIsNucleotide(program_number)) {/*protein-protein options.*/ (*options)->shift_pen = INT2_MAX; (*options)->is_ooframe = FALSE; (*options)->gap_open = BLAST_GAP_OPEN_PROT; @@ -791,8 +798,9 @@ BLAST_FillScoringOptions(BlastScoringOptions* options, if (!options) return BLASTERR_INVALIDPARAM; - if (program_number != eBlastTypeBlastn && - program_number != eBlastTypePhiBlastn) { /* protein-protein options. */ + if (/*program_number != eBlastTypeBlastn && + program_number != eBlastTypePhiBlastn*/ + !Blast_ProgramIsNucleotide(program_number)) {/* protein-protein options. */ /* If matrix name is not provided, keep the default "BLOSUM62" value filled in BlastScoringOptionsNew, otherwise reset it. */ if (matrix) @@ -836,7 +844,8 @@ BlastScoringOptionsValidate(EBlastProgramType program_number, return BLASTERR_OPTION_PROGRAM_INVALID; } - if (program_number == eBlastTypeBlastn || program_number == eBlastTypePhiBlastn) + if (/*program_number == eBlastTypeBlastn || program_number == eBlastTypePhiBlastn*/ + Blast_ProgramIsNucleotide(program_number)) { // A penalty/reward of 0/0 is a signal that this is rmblastn // which allows specification of penalties as positive integers. @@ -849,7 +858,10 @@ BlastScoringOptionsValidate(EBlastProgramType program_number, return BLASTERR_OPTION_VALUE_INVALID; } - if (options->gapped_calculation && !BLAST_CheckRewardPenaltyScores(options->reward, options->penalty)) + /* !!! this is temporary until there is jumper or mapping options handle */ + if (0 && options->gapped_calculation && + !Blast_ProgramIsMapping(program_number) && + !BLAST_CheckRewardPenaltyScores(options->reward, options->penalty)) { Blast_MessageWrite(blast_msg, eBlastSevWarning, kBlastMessageNoContext, "BLASTN reward/penalty combination not supported for gapped search"); @@ -1041,6 +1053,7 @@ LookupTableOptionsNew(EBlastProgramType program_number, LookupTableOptions* *opt return BLASTERR_INVALIDPARAM; switch (program_number) { + case eBlastTypeMapping: case eBlastTypeBlastn: /* Blastn default is megablast. */ (*options)->word_size = BLAST_WORDSIZE_MEGABLAST; @@ -1077,6 +1090,7 @@ LookupTableOptionsNew(EBlastProgramType program_number, LookupTableOptions* *opt } (*options)->program_number = program_number; + (*options)->stride = 0; return 0; } @@ -1090,6 +1104,7 @@ BLAST_FillLookupTableOptions(LookupTableOptions* options, return BLASTERR_INVALIDPARAM; if (program_number == eBlastTypeBlastn) { + if (is_megablast) { options->lut_type = eMBLookupTable; options->word_size = BLAST_WORDSIZE_MEGABLAST; @@ -1097,6 +1112,9 @@ BLAST_FillLookupTableOptions(LookupTableOptions* options, options->lut_type = eNaLookupTable; options->word_size = BLAST_WORDSIZE_NUCL; } + } else if (program_number == eBlastTypeMapping) { + options->lut_type = eNaHashLookupTable; + options->word_size = BLAST_WORDSIZE_MAPPER; } else { options->lut_type = eAaLookupTable; } @@ -1127,7 +1145,8 @@ Int2 BLAST_GetSuggestedThreshold(EBlastProgramType program_number, const char* m const double kB62_threshold = 11; - if (program_number == eBlastTypeBlastn) + if (program_number == eBlastTypeBlastn || + program_number == eBlastTypeMapping) return 0; if (matrixName == NULL) @@ -1162,7 +1181,8 @@ Int2 BLAST_GetSuggestedWindowSize(EBlastProgramType program_number, const char* { const Int4 kB62_windowsize = 40; - if (program_number == eBlastTypeBlastn) + if (program_number == eBlastTypeBlastn || + program_number == eBlastTypeMapping) return 0; if (matrixName == NULL) @@ -1250,6 +1270,7 @@ LookupTableOptionsValidate(EBlastProgramType program_number, return 0; if (program_number != eBlastTypeBlastn && + program_number != eBlastTypeMapping && (!Blast_ProgramIsRpsBlast(program_number)) && options->threshold <= 0) { @@ -1265,12 +1286,15 @@ LookupTableOptionsValidate(EBlastProgramType program_number, "Word-size must be greater than zero"); return BLASTERR_OPTION_VALUE_INVALID; } - } else if (program_number == eBlastTypeBlastn && options->word_size < 4) + } else if (/*program_number == eBlastTypeBlastn*/ + Blast_ProgramIsNucleotide(program_number) && + !Blast_QueryIsPattern(program_number) && options->word_size < 4) { Blast_MessageWrite(blast_msg, eBlastSevError, kBlastMessageNoContext, "Word-size must be 4 or greater for nucleotide comparison"); return BLASTERR_OPTION_VALUE_INVALID; - } else if (program_number != eBlastTypeBlastn && options->word_size > 5) + } else if (program_number != eBlastTypeBlastn && + program_number != eBlastTypeMapping && options->word_size > 5) { if (program_number == eBlastTypeBlastp || program_number == eBlastTypeTblastn || @@ -1293,7 +1317,8 @@ LookupTableOptionsValidate(EBlastProgramType program_number, } } - if (program_number != eBlastTypeBlastn && + if (program_number != eBlastTypeBlastn && + program_number != eBlastTypeMapping && options->lut_type == eMBLookupTable) { Blast_MessageWrite(blast_msg, eBlastSevError, kBlastMessageNoContext, @@ -1323,7 +1348,10 @@ LookupTableOptionsValidate(EBlastProgramType program_number, } } - if (program_number == eBlastTypeBlastn && options->mb_template_length > 0) { + if (/*program_number == eBlastTypeBlastn &&*/ + Blast_ProgramIsNucleotide(program_number) && + !Blast_QueryIsPattern(program_number) && + options->mb_template_length > 0) { if (!s_DiscWordOptionsValidate(options->word_size, options->mb_template_length, options->mb_template_type, @@ -1335,6 +1363,21 @@ LookupTableOptionsValidate(EBlastProgramType program_number, return BLASTERR_OPTION_VALUE_INVALID; } } + + if (!Blast_ProgramIsNucleotide(program_number) && options->db_filter) { + Blast_MessageWrite(blast_msg, eBlastSevError, kBlastMessageNoContext, + "The limit_lookup option can only be used for " + "nucleotide searches"); + return BLASTERR_OPTION_VALUE_INVALID; + } + + if (options->db_filter && options->word_size < BLAST_WORDSIZE_MAPPER) { + Blast_MessageWrite(blast_msg, eBlastSevError, kBlastMessageNoContext, + "The limit_lookup option can only be used with " + "word size >= 16"); + return BLASTERR_OPTION_VALUE_INVALID; + } + return 0; } @@ -1431,7 +1474,8 @@ BlastHitSavingOptionsValidate(EBlastProgramType program_number, if (options->longest_intron != 0 && program_number != eBlastTypeTblastn && program_number != eBlastTypePsiTblastn && - program_number != eBlastTypeBlastx) { + program_number != eBlastTypeBlastx && + program_number != eBlastTypeMapping) { Blast_MessageWrite(blast_msg, eBlastSevError, kBlastMessageNoContext, "Uneven gap linking of HSPs is allowed for blastx, " "tblastn, and psitblastn only"); @@ -1605,32 +1649,45 @@ static Int2 s_BlastExtensionScoringOptionsValidate(EBlastProgramType program_num { if (score_options->gap_open == 0 && score_options->gap_extend == 0) { - if (ext_options->ePrelimGapExt != eGreedyScoreOnly && + if (ext_options->ePrelimGapExt != eGreedyScoreOnly && ext_options->eTbackExt != eGreedyTbck) - { - Blast_MessageWrite(blast_msg, eBlastSevWarning, kBlastMessageNoContext, - "Greedy extension must be used if gap existence and extension options are zero"); - return BLASTERR_OPTION_VALUE_INVALID; - } - } + { + Blast_MessageWrite(blast_msg, eBlastSevWarning, + kBlastMessageNoContext, + "Greedy extension must be used if gap existence and extension options are zero"); + return BLASTERR_OPTION_VALUE_INVALID; + } + } + } + + if (program_number == eBlastTypeMapping) { + if (ext_options->ePrelimGapExt != eJumperWithTraceback) { + + Blast_MessageWrite(blast_msg, eBlastSevWarning, + kBlastMessageNoContext, + "Jumper extension must be used for mapping"); + + return BLASTERR_OPTION_VALUE_INVALID; + } } if (ext_options->compositionBasedStats != eNoCompositionBasedStats) { - if (!Blast_QueryIsPssm(program_number) && program_number != eBlastTypeTblastn && - program_number != eBlastTypeBlastp && - program_number != eBlastTypeBlastx && - program_number != eBlastTypeRpsBlast && - program_number != eBlastTypePsiBlast) { + if (!Blast_QueryIsPssm(program_number) && program_number != eBlastTypeTblastn && + program_number != eBlastTypeBlastp && + program_number != eBlastTypeBlastx && + program_number != eBlastTypeRpsBlast && + program_number != eBlastTypeRpsTblastn && + program_number != eBlastTypePsiBlast) { Blast_MessageWrite(blast_msg, eBlastSevWarning, kBlastMessageNoContext, "Compositional adjustments are only supported with blastp, blastx, or tblastn"); return BLASTERR_OPTION_VALUE_INVALID; - } - if (!score_options->gapped_calculation) { + } + if (!score_options->gapped_calculation) { Blast_MessageWrite(blast_msg, eBlastSevWarning, kBlastMessageNoContext, "Compositional adjustments are only supported for gapped searches"); return BLASTERR_OPTION_VALUE_INVALID; - } + } } @@ -1824,7 +1881,6 @@ BlastHSPFilteringOptionsValidate(const BlastHSPFilteringOptions* opts) if ((opts->culling_stage & ePrelimSearch) && writer_found) { return 1; } - writer_found = (opts->culling_stage & ePrelimSearch ? TRUE : FALSE); return retval; } diff --git a/c++/src/algo/blast/core/blast_parameters.c b/c++/src/algo/blast/core/blast_parameters.c index cf87835d..360c31db 100644 --- a/c++/src/algo/blast/core/blast_parameters.c +++ b/c++/src/algo/blast/core/blast_parameters.c @@ -1,4 +1,4 @@ -/* $Id: blast_parameters.c 416177 2013-10-24 14:58:42Z camacho $ +/* $Id: blast_parameters.c 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -28,11 +28,6 @@ * Definitions for functions dealing with BLAST CORE parameter structures. */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_parameters.c 416177 2013-10-24 14:58:42Z camacho $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include @@ -137,6 +132,7 @@ static double s_GetCutoffEvalue(EBlastProgramType program) { switch(program) { + case eBlastTypeMapping: case eBlastTypeBlastn: return CUTOFF_E_BLASTN; case eBlastTypeBlastp: @@ -224,9 +220,10 @@ BlastInitialWordParametersNew(EBlastProgramType program_number, } } - if (program_number == eBlastTypeBlastn && - (query_info->contexts[query_info->last_context].query_offset + - query_info->contexts[query_info->last_context].query_length) > kQueryLenForHashTable) + if (Blast_ProgramIsNucleotide(program_number) && + !Blast_QueryIsPattern(program_number) && + (query_info->contexts[query_info->last_context].query_offset + + query_info->contexts[query_info->last_context].query_length) > kQueryLenForHashTable) p->container_type = eDiagHash; else p->container_type = eDiagArray; @@ -234,7 +231,7 @@ BlastInitialWordParametersNew(EBlastProgramType program_number, status = BlastInitialWordParametersUpdate(program_number, hit_params, sbp, query_info, subject_length, p); - if (program_number == eBlastTypeBlastn) { + if (program_number == eBlastTypeBlastn || program_number == eBlastTypeMapping) { Int4 i; Int4 reward = sbp->reward; Int4 penalty = sbp->penalty; @@ -352,7 +349,8 @@ BlastInitialWordParametersUpdate(EBlastProgramType program_number, /* include the length of reverse complement for blastn searchs. */ ASSERT(query_length > 0); - if (program_number == eBlastTypeBlastn) + if (program_number == eBlastTypeBlastn || + program_number == eBlastTypeMapping) query_length *= 2; kbp = kbp_array[context]; @@ -407,7 +405,8 @@ BlastInitialWordParametersUpdate(EBlastProgramType program_number, /* Nucleotide searches first compute an approximate ungapped alignment and compare it to a reduced ungapped cutoff score */ - if (program_number == eBlastTypeBlastn) { + if (program_number == eBlastTypeBlastn || + program_number == eBlastTypeMapping) { curr_cutoffs->reduced_nucl_cutoff_score = (Int4)(0.8 * new_cutoff); } } @@ -863,7 +862,8 @@ BlastHitSavingParametersUpdate(EBlastProgramType program_number, params->prelim_evalue = options->expect_value; /* evalue and prelim_evalue same if no CBS. */ // Set masklevel parameter -RMH- - if ( program_number == eBlastTypeBlastn && options->mask_level >= 0 ) + if ((program_number == eBlastTypeBlastn || + program_number == eBlastTypeMapping) && options->mask_level >= 0 ) params->mask_level = options->mask_level; /* Calculate cutoffs based on effective length information */ diff --git a/c++/src/algo/blast/core/blast_posit.c b/c++/src/algo/blast/core/blast_posit.c index 00d587ef..bc46f785 100644 --- a/c++/src/algo/blast/core/blast_posit.c +++ b/c++/src/algo/blast/core/blast_posit.c @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_posit.c 99676 2007-03-05 20:41:55Z kazimird $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/algo/blast/core/blast_program.c b/c++/src/algo/blast/core/blast_program.c index 303e4937..57b2465c 100644 --- a/c++/src/algo/blast/core/blast_program.c +++ b/c++/src/algo/blast/core/blast_program.c @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_program.c 97157 2007-01-19 14:27:24Z madden $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -77,6 +73,17 @@ Boolean Blast_ProgramIsPhiBlast(EBlastProgramType p) Boolean Blast_ProgramIsRpsBlast(EBlastProgramType p) { return SAFE_CAST_INT_TO_BOOLEAN(p & PSSM_SUBJECT_MASK); } +Boolean Blast_ProgramIsMapping(EBlastProgramType p) +{ return SAFE_CAST_INT_TO_BOOLEAN(p & MAPPING_MASK); } + +Boolean Blast_QueryIsPattern(EBlastProgramType p) +{ return SAFE_CAST_INT_TO_BOOLEAN(p & PATTERN_QUERY_MASK); } + +Boolean Blast_ProgramIsNucleotide(EBlastProgramType p) +{ return Blast_QueryIsNucleotide(p) && Blast_SubjectIsNucleotide(p) && + !Blast_QueryIsTranslated(p) && !Blast_SubjectIsTranslated(p);} + + Boolean Blast_ProgramIsValid(EBlastProgramType p) { switch (p) { @@ -91,6 +98,7 @@ Boolean Blast_ProgramIsValid(EBlastProgramType p) case eBlastTypeRpsTblastn: case eBlastTypePhiBlastp: case eBlastTypePhiBlastn: + case eBlastTypeMapping: return TRUE; break; default: diff --git a/c++/src/algo/blast/core/blast_psi.c b/c++/src/algo/blast/core/blast_psi.c index 591f1758..58dd59a8 100644 --- a/c++/src/algo/blast/core/blast_psi.c +++ b/c++/src/algo/blast/core/blast_psi.c @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_psi.c 459883 2015-02-23 16:45:34Z camacho $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/algo/blast/core/blast_psi_priv.c b/c++/src/algo/blast/core/blast_psi_priv.c index 080bd4a1..9be43c4d 100644 --- a/c++/src/algo/blast/core/blast_psi_priv.c +++ b/c++/src/algo/blast/core/blast_psi_priv.c @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_psi_priv.c 464171 2015-04-06 17:39:26Z boratyng $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/algo/blast/core/blast_query_info.c b/c++/src/algo/blast/core/blast_query_info.c index 7f05de91..cfe5a13f 100644 --- a/c++/src/algo/blast/core/blast_query_info.c +++ b/c++/src/algo/blast/core/blast_query_info.c @@ -1,4 +1,4 @@ -/* $Id: blast_query_info.c 419225 2013-11-22 17:08:29Z camacho $ +/* $Id: blast_query_info.c 517499 2016-10-25 17:20:41Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -32,11 +32,6 @@ */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_query_info.c 419225 2013-11-22 17:08:29Z camacho $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include @@ -97,6 +92,10 @@ BlastQueryInfo* BlastQueryInfoNew(EBlastProgramType program, int num_queries) ASSERT(retval->contexts[i].frame != INT1_MAX); retval->contexts[i].is_valid = TRUE; + + if (Blast_ProgramIsMapping(program)) { + retval->contexts[i].segment_flags = eNoSegments; + } } } @@ -170,7 +169,7 @@ Int4 BlastQueryInfoGetQueryLength(const BlastQueryInfo* qinfo, if (Blast_QueryIsTranslated(program)) { return s_GetTranslatedQueryDNALength(qinfo, query_index); - } else if (program == eBlastTypeBlastn) { + } else if (program == eBlastTypeBlastn || program == eBlastTypeMapping) { Int4 retval = qinfo->contexts[query_index*kNumContexts].query_length; if (retval <= 0) { retval = qinfo->contexts[query_index*kNumContexts+1].query_length; @@ -222,9 +221,17 @@ Int4 BSearchContextInfo(Int4 n, const BlastQueryInfo * A) Int4 m=0, b=0, e=0, size=0; size = A->last_context+1; - - b = 0; - e = size; + + if (A->min_length > 0 && A->max_length > 0 && A->first_context == 0) { + b = MIN(n / (A->max_length + 1), size - 1); + e = MIN(n / (A->min_length + 1) + 1, size); + ASSERT(e <= size); + } + else { + b = 0; + e = size; + } + while (b < e - 1) { m = (b + e) / 2; if (A->contexts[m].query_offset > n) diff --git a/c++/src/algo/blast/core/blast_seg.c b/c++/src/algo/blast/core/blast_seg.c index f83223be..b8229fdb 100644 --- a/c++/src/algo/blast/core/blast_seg.c +++ b/c++/src/algo/blast/core/blast_seg.c @@ -1,25 +1,25 @@ -/* $Id: blast_seg.c 473564 2015-07-21 15:29:04Z madden $ +/* $Id: blast_seg.c 510159 2016-08-11 11:28:47Z ivanov $ * =========================================================================== * - * PUBLIC DOMAIN NOTICE + * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information - * - * This software/database is a "United States Government Work" under the - * terms of the United States Copyright Act. It was written as part of - * the author's official duties as a United States Government employee and - * thus cannot be copyrighted. This software/database is freely available - * to the public for use. The National Library of Medicine and the U.S. - * Government have not placed any restriction on its use or reproduction. - * - * Although all reasonable efforts have been taken to ensure the accuracy - * and reliability of the software and data, the NLM and the U.S. - * Government do not and cannot warrant the performance or results that - * may be obtained by using this software or data. The NLM and the U.S. - * Government disclaim all warranties, express or implied, including + * + * This software/database is a "United States Government Work" under the + * terms of the United States Copyright Act. It was written as part of + * the author's official duties as a United States Government employee and + * thus cannot be copyrighted. This software/database is freely available + * to the public for use. The National Library of Medicine and the U.S. + * Government have not placed any restriction on its use or reproduction. + * + * Although all reasonable efforts have been taken to ensure the accuracy + * and reliability of the software and data, the NLM and the U.S. + * Government do not and cannot warrant the performance or results that + * may be obtained by using this software or data. The NLM and the U.S. + * Government disclaim all warranties, express or implied, including * warranties of performance, merchantability or fitness for any particular - * purpose. - * - * Please cite the author in any work or product based on this material. + * purpose. + * + * Please cite the author in any work or product based on this material. * * =========================================================================== * @@ -28,21 +28,18 @@ */ /** @file blast_seg.c - * A utility to find low complexity AA regions. This parallels functionality - * of seg.c from the C toolkit, but without using the structures generated + * A utility to find low complexity AA regions. This parallels functionality + * of seg.c from the C toolkit, but without using the structures generated * from ASN.1 spec. * @todo FIXME needs comments */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_seg.c 473564 2015-07-21 15:29:04Z madden $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include +#include + /** Declared in blast_def.h. */ const int kSegWindow = 12; @@ -50,1268 +47,1268 @@ const double kSegLocut = 2.2; const double kSegHicut = 2.5; /** Natural log of factorials: 0!, 1!, 2!, 3! */ -double lnfact[] = +double lnfact[] = { - 0.000000, 0.000000, 0.693147, 1.791759, 3.178054, 4.787492, 6.579251, 8.525161, - 10.604603, 12.801827, 15.104413, 17.502308, 19.987214, 22.552164, 25.191221, 27.899271, - 30.671860, 33.505073, 36.395445, 39.339884, 42.335616, 45.380139, 48.471181, 51.606676, - 54.784729, 58.003605, 61.261702, 64.557539, 67.889743, 71.257039, 74.658236, 78.092224, - 81.557959, 85.054467, 88.580828, 92.136176, 95.719695, 99.330612, 102.968199, 106.631760, - 110.320640, 114.034212, 117.771881, 121.533082, 125.317271, 129.123934, 132.952575, 136.802723, - 140.673924, 144.565744, 148.477767, 152.409593, 156.360836, 160.331128, 164.320112, 168.327445, - 172.352797, 176.395848, 180.456291, 184.533829, 188.628173, 192.739047, 196.866182, 201.009316, - 205.168199, 209.342587, 213.532241, 217.736934, 221.956442, 226.190548, 230.439044, 234.701723, - 238.978390, 243.268849, 247.572914, 251.890402, 256.221136, 260.564941, 264.921650, 269.291098, - 273.673124, 278.067573, 282.474293, 286.893133, 291.323950, 295.766601, 300.220949, 304.686857, - 309.164194, 313.652830, 318.152640, 322.663499, 327.185288, 331.717887, 336.261182, 340.815059, - 345.379407, 349.954118, 354.539086, 359.134205, 363.739376, 368.354496, 372.979469, 377.614198, - 382.258589, 386.912549, 391.575988, 396.248817, 400.930948, 405.622296, 410.322777, 415.032307, - 419.750806, 424.478193, 429.214392, 433.959324, 438.712914, 443.475088, 448.245773, 453.024896, - 457.812388, 462.608179, 467.412200, 472.224384, 477.044665, 481.872979, 486.709261, 491.553448, - 496.405478, 501.265291, 506.132825, 511.008023, 515.890825, 520.781174, 525.679014, 530.584288, - 535.496943, 540.416924, 545.344178, 550.278652, 555.220294, 560.169054, 565.124881, 570.087726, - 575.057539, 580.034273, 585.017879, 590.008312, 595.005524, 600.009471, 605.020106, 610.037386, - 615.061266, 620.091704, 625.128657, 630.172082, 635.221938, 640.278184, 645.340779, 650.409683, - 655.484857, 660.566261, 665.653857, 670.747608, 675.847474, 680.953420, 686.065407, 691.183401, - 696.307365, 701.437264, 706.573062, 711.714726, 716.862220, 722.015512, 727.174567, 732.339353, - 737.509837, 742.685987, 747.867770, 753.055156, 758.248113, 763.446610, 768.650617, 773.860103, - 779.075039, 784.295395, 789.521141, 794.752250, 799.988692, 805.230439, 810.477463, 815.729736, - 820.987232, 826.249922, 831.517780, 836.790780, 842.068894, 847.352098, 852.640365, 857.933670, - 863.231987, 868.535292, 873.843560, 879.156766, 884.474886, 889.797896, 895.125772, 900.458491, - 905.796029, 911.138363, 916.485471, 921.837329, 927.193915, 932.555207, 937.921183, 943.291821, - 948.667100, 954.046997, 959.431492, 964.820564, 970.214191, 975.612354, 981.015031, 986.422203, - 991.833849, 997.249950, 1002.670485, 1008.095435, 1013.524780, 1018.958502, 1024.396582, 1029.838999, - 1035.285737, 1040.736775, 1046.192096, 1051.651682, 1057.115514, 1062.583574, 1068.055844, 1073.532308, - 1079.012947, 1084.497744, 1089.986681, 1095.479743, 1100.976911, 1106.478169, 1111.983501, 1117.492889, - 1123.006318, 1128.523771, 1134.045232, 1139.570685, 1145.100114, 1150.633503, 1156.170838, 1161.712101, - 1167.257279, 1172.806355, 1178.359314, 1183.916142, 1189.476824, 1195.041344, 1200.609689, 1206.181843, - 1211.757792, 1217.337522, 1222.921018, 1228.508267, 1234.099254, 1239.693965, 1245.292387, 1250.894506, - 1256.500308, 1262.109780, 1267.722908, 1273.339679, 1278.960080, 1284.584097, 1290.211718, 1295.842930, - 1301.477720, 1307.116075, 1312.757982, 1318.403428, 1324.052403, 1329.704892, 1335.360884, 1341.020366, - 1346.683326, 1352.349753, 1358.019634, 1363.692957, 1369.369711, 1375.049884, 1380.733463, 1386.420439, - 1392.110798, 1397.804530, 1403.501624, 1409.202067, 1414.905850, 1420.612960, 1426.323387, 1432.037120, - 1437.754148, 1443.474460, 1449.198045, 1454.924892, 1460.654992, 1466.388333, 1472.124906, 1477.864699, - 1483.607702, 1489.353905, 1495.103298, 1500.855871, 1506.611613, 1512.370515, 1518.132566, 1523.897757, - 1529.666078, 1535.437519, 1541.212071, 1546.989723, 1552.770467, 1558.554292, 1564.341189, 1570.131149, - 1575.924163, 1581.720221, 1587.519313, 1593.321432, 1599.126567, 1604.934709, 1610.745850, 1616.559981, - 1622.377092, 1628.197175, 1634.020221, 1639.846221, 1645.675166, 1651.507049, 1657.341860, 1663.179590, - 1669.020232, 1674.863776, 1680.710215, 1686.559540, 1692.411742, 1698.266814, 1704.124747, 1709.985533, - 1715.849165, 1721.715633, 1727.584930, 1733.457047, 1739.331978, 1745.209714, 1751.090247, 1756.973569, - 1762.859673, 1768.748551, 1774.640196, 1780.534598, 1786.431752, 1792.331650, 1798.234283, 1804.139645, - 1810.047728, 1815.958524, 1821.872027, 1827.788229, 1833.707123, 1839.628702, 1845.552957, 1851.479884, - 1857.409473, 1863.341718, 1869.276612, 1875.214148, 1881.154319, 1887.097119, 1893.042539, 1898.990574, - 1904.941217, 1910.894460, 1916.850298, 1922.808722, 1928.769728, 1934.733307, 1940.699454, 1946.668161, - 1952.639423, 1958.613233, 1964.589584, 1970.568470, 1976.549884, 1982.533820, 1988.520272, 1994.509233, - 2000.500698, 2006.494659, 2012.491111, 2018.490048, 2024.491463, 2030.495350, 2036.501703, 2042.510516, - 2048.521784, 2054.535499, 2060.551656, 2066.570249, 2072.591272, 2078.614720, 2084.640586, 2090.668864, - 2096.699550, 2102.732636, 2108.768117, 2114.805988, 2120.846243, 2126.888876, 2132.933881, 2138.981253, - 2145.030987, 2151.083076, 2157.137515, 2163.194299, 2169.253423, 2175.314879, 2181.378665, 2187.444773, - 2193.513198, 2199.583936, 2205.656981, 2211.732327, 2217.809969, 2223.889902, 2229.972121, 2236.056620, - 2242.143395, 2248.232440, 2254.323750, 2260.417320, 2266.513144, 2272.611219, 2278.711537, 2284.814096, - 2290.918889, 2297.025912, 2303.135160, 2309.246627, 2315.360309, 2321.476201, 2327.594299, 2333.714596, - 2339.837089, 2345.961772, 2352.088641, 2358.217692, 2364.348918, 2370.482316, 2376.617881, 2382.755608, - 2388.895493, 2395.037530, 2401.181716, 2407.328045, 2413.476513, 2419.627116, 2425.779849, 2431.934707, - 2438.091686, 2444.250781, 2450.411988, 2456.575303, 2462.740721, 2468.908238, 2475.077848, 2481.249549, - 2487.423335, 2493.599202, 2499.777146, 2505.957163, 2512.139248, 2518.323397, 2524.509606, 2530.697870, - 2536.888185, 2543.080548, 2549.274953, 2555.471397, 2561.669876, 2567.870385, 2574.072920, 2580.277478, - 2586.484054, 2592.692644, 2598.903244, 2605.115850, 2611.330458, 2617.547065, 2623.765665, 2629.986255, - 2636.208831, 2642.433390, 2648.659926, 2654.888437, 2661.118919, 2667.351367, 2673.585777, 2679.822147, - 2686.060472, 2692.300747, 2698.542971, 2704.787138, 2711.033244, 2717.281287, 2723.531263, 2729.783166, - 2736.036995, 2742.292745, 2748.550413, 2754.809994, 2761.071486, 2767.334884, 2773.600185, 2779.867386, - 2786.136482, 2792.407471, 2798.680348, 2804.955110, 2811.231753, 2817.510275, 2823.790671, 2830.072937, - 2836.357071, 2842.643070, 2848.930928, 2855.220644, 2861.512213, 2867.805632, 2874.100898, 2880.398007, - 2886.696957, 2892.997742, 2899.300361, 2905.604810, 2911.911085, 2918.219184, 2924.529102, 2930.840837, - 2937.154385, 2943.469743, 2949.786908, 2956.105876, 2962.426644, 2968.749209, 2975.073568, 2981.399718, - 2987.727655, 2994.057376, 3000.388877, 3006.722157, 3013.057211, 3019.394037, 3025.732631, 3032.072990, - 3038.415112, 3044.758992, 3051.104629, 3057.452018, 3063.801157, 3070.152043, 3076.504672, 3082.859042, - 3089.215150, 3095.572992, 3101.932566, 3108.293868, 3114.656896, 3121.021647, 3127.388118, 3133.756305, - 3140.126206, 3146.497818, 3152.871137, 3159.246162, 3165.622889, 3172.001315, 3178.381438, 3184.763254, - 3191.146760, 3197.531955, 3203.918834, 3210.307396, 3216.697636, 3223.089553, 3229.483144, 3235.878406, - 3242.275335, 3248.673930, 3255.074188, 3261.476105, 3267.879679, 3274.284908, 3280.691788, 3287.100316, - 3293.510491, 3299.922310, 3306.335768, 3312.750865, 3319.167598, 3325.585963, 3332.005958, 3338.427580, - 3344.850827, 3351.275696, 3357.702184, 3364.130290, 3370.560009, 3376.991340, 3383.424280, 3389.858827, - 3396.294977, 3402.732729, 3409.172079, 3415.613026, 3422.055566, 3428.499697, 3434.945417, 3441.392723, - 3447.841612, 3454.292083, 3460.744132, 3467.197757, 3473.652955, 3480.109725, 3486.568063, 3493.027968, - 3499.489436, 3505.952465, 3512.417053, 3518.883198, 3525.350897, 3531.820147, 3538.290947, 3544.763293, - 3551.237184, 3557.712616, 3564.189589, 3570.668098, 3577.148143, 3583.629720, 3590.112827, 3596.597463, - 3603.083624, 3609.571308, 3616.060512, 3622.551236, 3629.043476, 3635.537230, 3642.032495, 3648.529270, - 3655.027552, 3661.527339, 3668.028629, 3674.531419, 3681.035707, 3687.541491, 3694.048769, 3700.557538, - 3707.067797, 3713.579542, 3720.092772, 3726.607485, 3733.123678, 3739.641349, 3746.160496, 3752.681117, - 3759.203210, 3765.726773, 3772.251802, 3778.778297, 3785.306255, 3791.835674, 3798.366551, 3804.898886, - 3811.432675, 3817.967916, 3824.504607, 3831.042747, 3837.582333, 3844.123363, 3850.665835, 3857.209747, - 3863.755097, 3870.301882, 3876.850101, 3883.399752, 3889.950832, 3896.503340, 3903.057274, 3909.612630, - 3916.169409, 3922.727607, 3929.287222, 3935.848253, 3942.410697, 3948.974552, 3955.539817, 3962.106490, - 3968.674567, 3975.244049, 3981.814932, 3988.387214, 3994.960895, 4001.535970, 4008.112440, 4014.690301, - 4021.269553, 4027.850192, 4034.432217, 4041.015626, 4047.600417, 4054.186589, 4060.774139, 4067.363066, - 4073.953367, 4080.545040, 4087.138085, 4093.732498, 4100.328279, 4106.925425, 4113.523934, 4120.123804, - 4126.725034, 4133.327622, 4139.931566, 4146.536864, 4153.143514, 4159.751515, 4166.360864, 4172.971560, - 4179.583601, 4186.196985, 4192.811711, 4199.427776, 4206.045179, 4212.663918, 4219.283991, 4225.905397, - 4232.528133, 4239.152198, 4245.777591, 4252.404308, 4259.032350, 4265.661713, 4272.292396, 4278.924398, - 4285.557717, 4292.192350, 4298.828297, 4305.465555, 4312.104122, 4318.743998, 4325.385180, 4332.027667, - 4338.671457, 4345.316548, 4351.962938, 4358.610627, 4365.259611, 4371.909890, 4378.561462, 4385.214325, - 4391.868478, 4398.523918, 4405.180645, 4411.838656, 4418.497950, 4425.158525, 4431.820380, 4438.483512, - 4445.147921, 4451.813605, 4458.480562, 4465.148790, 4471.818288, 4478.489054, 4485.161087, 4491.834385, - 4498.508947, 4505.184770, 4511.861853, 4518.540196, 4525.219795, 4531.900649, 4538.582758, 4545.266119, - 4551.950731, 4558.636592, 4565.323700, 4572.012055, 4578.701654, 4585.392497, 4592.084580, 4598.777904, - 4605.472466, 4612.168265, 4618.865299, 4625.563567, 4632.263068, 4638.963799, 4645.665759, 4652.368947, - 4659.073361, 4665.779001, 4672.485863, 4679.193947, 4685.903251, 4692.613774, 4699.325515, 4706.038471, - 4712.752642, 4719.468025, 4726.184620, 4732.902424, 4739.621438, 4746.341658, 4753.063083, 4759.785713, - 4766.509546, 4773.234579, 4779.960813, 4786.688244, 4793.416873, 4800.146697, 4806.877715, 4813.609926, - 4820.343328, 4827.077919, 4833.813700, 4840.550666, 4847.288819, 4854.028156, 4860.768675, 4867.510376, - 4874.253256, 4880.997315, 4887.742552, 4894.488964, 4901.236550, 4907.985310, 4914.735241, 4921.486343, - 4928.238613, 4934.992051, 4941.746655, 4948.502424, 4955.259356, 4962.017451, 4968.776706, 4975.537121, - 4982.298694, 4989.061423, 4995.825308, 5002.590347, 5009.356539, 5016.123882, 5022.892375, 5029.662017, - 5036.432806, 5043.204742, 5049.977822, 5056.752046, 5063.527412, 5070.303919, 5077.081566, 5083.860351, - 5090.640273, 5097.421330, 5104.203522, 5110.986848, 5117.771305, 5124.556892, 5131.343609, 5138.131454, - 5144.920426, 5151.710523, 5158.501745, 5165.294089, 5172.087555, 5178.882142, 5185.677848, 5192.474671, - 5199.272612, 5206.071668, 5212.871838, 5219.673121, 5226.475515, 5233.279021, 5240.083635, 5246.889358, - 5253.696187, 5260.504122, 5267.313161, 5274.123304, 5280.934548, 5287.746893, 5294.560338, 5301.374881, - 5308.190521, 5315.007257, 5321.825087, 5328.644011, 5335.464028, 5342.285135, 5349.107333, 5355.930619, - 5362.754992, 5369.580452, 5376.406998, 5383.234627, 5390.063339, 5396.893133, 5403.724007, 5410.555960, - 5417.388992, 5424.223101, 5431.058286, 5437.894545, 5444.731878, 5451.570283, 5458.409759, 5465.250306, - 5472.091921, 5478.934605, 5485.778355, 5492.623170, 5499.469050, 5506.315993, 5513.163998, 5520.013065, - 5526.863191, 5533.714376, 5540.566618, 5547.419917, 5554.274272, 5561.129681, 5567.986143, 5574.843657, - 5581.702222, 5588.561837, 5595.422500, 5602.284212, 5609.146970, 5616.010773, 5622.875621, 5629.741512, - 5636.608445, 5643.476419, 5650.345434, 5657.215487, 5664.086579, 5670.958707, 5677.831871, 5684.706069, - 5691.581301, 5698.457566, 5705.334862, 5712.213188, 5719.092544, 5725.972928, 5732.854339, 5739.736777, - 5746.620240, 5753.504726, 5760.390236, 5767.276768, 5774.164320, 5781.052893, 5787.942484, 5794.833093, - 5801.724719, 5808.617361, 5815.511017, 5822.405687, 5829.301370, 5836.198064, 5843.095769, 5849.994483, - 5856.894207, 5863.794937, 5870.696674, 5877.599417, 5884.503164, 5891.407915, 5898.313668, 5905.220423, - 5912.128178, 5919.036933, 5925.946687, 5932.857437, 5939.769185, 5946.681927, 5953.595665, 5960.510396, - 5967.426119, 5974.342834, 5981.260540, 5988.179235, 5995.098919, 6002.019590, 6008.941249, 6015.863892, - 6022.787521, 6029.712133, 6036.637729, 6043.564306, 6050.491864, 6057.420401, 6064.349918, 6071.280413, - 6078.211885, 6085.144333, 6092.077756, 6099.012153, 6105.947523, 6112.883866, 6119.821180, 6126.759465, - 6133.698719, 6140.638941, 6147.580131, 6154.522288, 6161.465410, 6168.409497, 6175.354548, 6182.300562, - 6189.247538, 6196.195476, 6203.144373, 6210.094229, 6217.045044, 6223.996816, 6230.949545, 6237.903229, - 6244.857868, 6251.813460, 6258.770006, 6265.727503, 6272.685952, 6279.645350, 6286.605698, 6293.566994, - 6300.529237, 6307.492427, 6314.456563, 6321.421643, 6328.387668, 6335.354635, 6342.322544, 6349.291394, - 6356.261185, 6363.231915, 6370.203584, 6377.176190, 6384.149733, 6391.124212, 6398.099626, 6405.075974, - 6412.053255, 6419.031469, 6426.010614, 6432.990690, 6439.971696, 6446.953631, 6453.936493, 6460.920283, - 6467.905000, 6474.890641, 6481.877208, 6488.864698, 6495.853111, 6502.842447, 6509.832703, 6516.823880, - 6523.815976, 6530.808991, 6537.802924, 6544.797774, 6551.793541, 6558.790222, 6565.787818, 6572.786328, - 6579.785750, 6586.786085, 6593.787330, 6600.789486, 6607.792552, 6614.796526, 6621.801408, 6628.807197, - 6635.813892, 6642.821493, 6649.829998, 6656.839407, 6663.849719, 6670.860933, 6677.873048, 6684.886064, - 6691.899979, 6698.914794, 6705.930506, 6712.947116, 6719.964622, 6726.983024, 6734.002320, 6741.022511, - 6748.043595, 6755.065571, 6762.088439, 6769.112198, 6776.136847, 6783.162386, 6790.188813, 6797.216127, - 6804.244328, 6811.273416, 6818.303389, 6825.334246, 6832.365988, 6839.398612, 6846.432118, 6853.466506, - 6860.501775, 6867.537923, 6874.574951, 6881.612857, 6888.651641, 6895.691301, 6902.731837, 6909.773249, - 6916.815535, 6923.858695, 6930.902728, 6937.947633, 6944.993410, 6952.040057, 6959.087574, 6966.135961, - 6973.185215, 6980.235338, 6987.286327, 6994.338183, 7001.390904, 7008.444490, 7015.498939, 7022.554252, - 7029.610428, 7036.667465, 7043.725362, 7050.784121, 7057.843738, 7064.904215, 7071.965549, 7079.027741, - 7086.090789, 7093.154693, 7100.219452, 7107.285065, 7114.351532, 7121.418852, 7128.487024, 7135.556047, - 7142.625922, 7149.696646, 7156.768219, 7163.840641, 7170.913911, 7177.988027, 7185.062991, 7192.138799, - 7199.215453, 7206.292951, 7213.371293, 7220.450477, 7227.530504, 7234.611372, 7241.693080, 7248.775629, - 7255.859017, 7262.943243, 7270.028307, 7277.114209, 7284.200947, 7291.288521, 7298.376929, 7305.466172, - 7312.556249, 7319.647159, 7326.738901, 7333.831475, 7340.924880, 7348.019114, 7355.114179, 7362.210072, - 7369.306793, 7376.404342, 7383.502718, 7390.601920, 7397.701947, 7404.802799, 7411.904475, 7419.006974, - 7426.110296, 7433.214440, 7440.319406, 7447.425192, 7454.531798, 7461.639223, 7468.747468, 7475.856530, - 7482.966409, 7490.077105, 7497.188617, 7504.300945, 7511.414087, 7518.528043, 7525.642812, 7532.758395, - 7539.874789, 7546.991994, 7554.110010, 7561.228837, 7568.348472, 7575.468917, 7582.590169, 7589.712229, - 7596.835096, 7603.958769, 7611.083247, 7618.208530, 7625.334617, 7632.461508, 7639.589202, 7646.717698, - 7653.846995, 7660.977094, 7668.107992, 7675.239691, 7682.372189, 7689.505485, 7696.639578, 7703.774469, - 7710.910156, 7718.046640, 7725.183918, 7732.321991, 7739.460858, 7746.600518, 7753.740971, 7760.882217, - 7768.024253, 7775.167081, 7782.310698, 7789.455105, 7796.600301, 7803.746286, 7810.893058, 7818.040617, - 7825.188963, 7832.338095, 7839.488012, 7846.638713, 7853.790199, 7860.942467, 7868.095519, 7875.249353, - 7882.403968, 7889.559364, 7896.715541, 7903.872497, 7911.030233, 7918.188747, 7925.348039, 7932.508108, - 7939.668954, 7946.830576, 7953.992973, 7961.156146, 7968.320093, 7975.484813, 7982.650306, 7989.816572, - 7996.983610, 8004.151419, 8011.319999, 8018.489349, 8025.659469, 8032.830357, 8040.002014, 8047.174439, - 8054.347631, 8061.521589, 8068.696313, 8075.871803, 8083.048057, 8090.225076, 8097.402859, 8104.581404, - 8111.760712, 8118.940782, 8126.121613, 8133.303205, 8140.485557, 8147.668669, 8154.852540, 8162.037169, - 8169.222556, 8176.408700, 8183.595601, 8190.783258, 8197.971671, 8205.160839, 8212.350761, 8219.541437, - 8226.732866, 8233.925048, 8241.117983, 8248.311668, 8255.506105, 8262.701293, 8269.897230, 8277.093916, - 8284.291352, 8291.489535, 8298.688466, 8305.888145, 8313.088570, 8320.289741, 8327.491657, 8334.694318, - 8341.897724, 8349.101873, 8356.306765, 8363.512401, 8370.718778, 8377.925897, 8385.133757, 8392.342357, - 8399.551697, 8406.761777, 8413.972595, 8421.184152, 8428.396447, 8435.609478, 8442.823246, 8450.037751, - 8457.252991, 8464.468966, 8471.685675, 8478.903119, 8486.121296, 8493.340205, 8500.559847, 8507.780221, - 8515.001326, 8522.223162, 8529.445728, 8536.669024, 8543.893049, 8551.117802, 8558.343284, 8565.569493, - 8572.796429, 8580.024091, 8587.252480, 8594.481593, 8601.711432, 8608.941995, 8616.173282, 8623.405293, - 8630.638026, 8637.871481, 8645.105658, 8652.340557, 8659.576176, 8666.812515, 8674.049574, 8681.287353, - 8688.525849, 8695.765064, 8703.004997, 8710.245647, 8717.487013, 8724.729095, 8731.971893, 8739.215406, - 8746.459634, 8753.704575, 8760.950230, 8768.196598, 8775.443679, 8782.691472, 8789.939976, 8797.189191, - 8804.439116, 8811.689752, 8818.941097, 8826.193151, 8833.445913, 8840.699383, 8847.953561, 8855.208446, - 8862.464037, 8869.720335, 8876.977337, 8884.235045, 8891.493457, 8898.752573, 8906.012393, 8913.272915, - 8920.534141, 8927.796068, 8935.058696, 8942.322026, 8949.586056, 8956.850786, 8964.116216, 8971.382345, - 8978.649172, 8985.916697, 8993.184920, 9000.453841, 9007.723457, 9014.993770, 9022.264779, 9029.536483, - 9036.808881, 9044.081973, 9051.355760, 9058.630239, 9065.905412, 9073.181276, 9080.457833, 9087.735080, - 9095.013019, 9102.291648, 9109.570967, 9116.850975, 9124.131672, 9131.413058, 9138.695132, 9145.977893, - 9153.261341, 9160.545476, 9167.830297, 9175.115803, 9182.401995, 9189.688871, 9196.976432, 9204.264676, - 9211.553604, 9218.843215, 9226.133507, 9233.424482, 9240.716138, 9248.008476, 9255.301493, 9262.595191, - 9269.889568, 9277.184625, 9284.480360, 9291.776773, 9299.073864, 9306.371632, 9313.670077, 9320.969199, - 9328.268996, 9335.569469, 9342.870617, 9350.172439, 9357.474936, 9364.778106, 9372.081949, 9379.386465, - 9386.691653, 9393.997513, 9401.304045, 9408.611247, 9415.919120, 9423.227662, 9430.536875, 9437.846756, - 9445.157306, 9452.468525, 9459.780411, 9467.092965, 9474.406185, 9481.720072, 9489.034625, 9496.349843, - 9503.665726, 9510.982275, 9518.299487, 9525.617363, 9532.935903, 9540.255105, 9547.574970, 9554.895497, - 9562.216686, 9569.538535, 9576.861046, 9584.184217, 9591.508047, 9598.832537, 9606.157686, 9613.483494, - 9620.809959, 9628.137082, 9635.464863, 9642.793300, 9650.122394, 9657.452144, 9664.782549, 9672.113609, - 9679.445324, 9686.777694, 9694.110717, 9701.444393, 9708.778722, 9716.113704, 9723.449338, 9730.785624, - 9738.122561, 9745.460148, 9752.798387, 9760.137275, 9767.476812, 9774.816999, 9782.157835, 9789.499319, - 9796.841450, 9804.184230, 9811.527656, 9818.871729, 9826.216448, 9833.561813, 9840.907823, 9848.254478, - 9855.601778, 9862.949721, 9870.298309, 9877.647540, 9884.997414, 9892.347930, 9899.699088, 9907.050888, - 9914.403329, 9921.756411, 9929.110133, 9936.464495, 9943.819497, 9951.175138, 9958.531418, 9965.888337, - 9973.245893, 9980.604087, 9987.962917, 9995.322385, 10002.682489, 10010.043229, 10017.404604, 10024.766615, - 10032.129260, 10039.492540, 10046.856453, 10054.221000, 10061.586180, 10068.951993, 10076.318438, 10083.685515, - 10091.053224, 10098.421564, 10105.790534, 10113.160135, 10120.530366, 10127.901226, 10135.272715, 10142.644833, - 10150.017579, 10157.390954, 10164.764956, 10172.139585, 10179.514840, 10186.890722, 10194.267231, 10201.644364, - 10209.022123, 10216.400507, 10223.779515, 10231.159147, 10238.539403, 10245.920282, 10253.301784, 10260.683908, - 10268.066655, 10275.450023, 10282.834012, 10290.218623, 10297.603854, 10304.989705, 10312.376176, 10319.763266, - 10327.150975, 10334.539303, 10341.928249, 10349.317813, 10356.707994, 10364.098793, 10371.490208, 10378.882240, - 10386.274887, 10393.668150, 10401.062029, 10408.456522, 10415.851629, 10423.247351, 10430.643686, 10438.040635, - 10445.438196, 10452.836370, 10460.235157, 10467.634555, 10475.034564, 10482.435185, 10489.836416, 10497.238258, - 10504.640709, 10512.043770, 10519.447441, 10526.851720, 10534.256607, 10541.662103, 10549.068206, 10556.474917, - 10563.882235, 10571.290159, 10578.698690, 10586.107826, 10593.517568, 10600.927915, 10608.338867, 10615.750423, - 10623.162584, 10630.575348, 10637.988715, 10645.402685, 10652.817258, 10660.232433, 10667.648210, 10675.064589, - 10682.481568, 10689.899149, 10697.317330, 10704.736111, 10712.155491, 10719.575471, 10726.996050, 10734.417227, - 10741.839003, 10749.261377, 10756.684348, 10764.107917, 10771.532082, 10778.956844, 10786.382202, 10793.808155, - 10801.234704, 10808.661848, 10816.089587, 10823.517920, 10830.946848, 10838.376369, 10845.806483, 10853.237190, - 10860.668489, 10868.100381, 10875.532865, 10882.965940, 10890.399607, 10897.833864, 10905.268712, 10912.704150, - 10920.140178, 10927.576795, 10935.014002, 10942.451797, 10949.890180, 10957.329152, 10964.768711, 10972.208858, - 10979.649592, 10987.090912, 10994.532819, 11001.975312, 11009.418390, 11016.862054, 11024.306302, 11031.751136, - 11039.196553, 11046.642555, 11054.089140, 11061.536308, 11068.984059, 11076.432393, 11083.881309, 11091.330807, - 11098.780887, 11106.231548, 11113.682789, 11121.134612, 11128.587014, 11136.039996, 11143.493558, 11150.947699, - 11158.402419, 11165.857718, 11173.313594, 11180.770049, 11188.227081, 11195.684690, 11203.142876, 11210.601639, - 11218.060978, 11225.520893, 11232.981383, 11240.442449, 11247.904089, 11255.366304, 11262.829093, 11270.292456, - 11277.756393, 11285.220903, 11292.685985, 11300.151641, 11307.617868, 11315.084668, 11322.552039, 11330.019981, - 11337.488494, 11344.957578, 11352.427232, 11359.897457, 11367.368250, 11374.839613, 11382.311546, 11389.784046, - 11397.257115, 11404.730752, 11412.204957, 11419.679729, 11427.155069, 11434.630975, 11442.107447, 11449.584486, - 11457.062090, 11464.540259, 11472.018994, 11479.498294, 11486.978158, 11494.458586, 11501.939579, 11509.421134, - 11516.903253, 11524.385935, 11531.869179, 11539.352986, 11546.837355, 11554.322285, 11561.807777, 11569.293829, - 11576.780443, 11584.267616, 11591.755350, 11599.243644, 11606.732496, 11614.221909, 11621.711879, 11629.202409, - 11636.693496, 11644.185142, 11651.677345, 11659.170105, 11666.663423, 11674.157296, 11681.651727, 11689.146713, - 11696.642255, 11704.138352, 11711.635005, 11719.132212, 11726.629974, 11734.128289, 11741.627159, 11749.126582, - 11756.626559, 11764.127088, 11771.628171, 11779.129805, 11786.631991, 11794.134730, 11801.638019, 11809.141860, - 11816.646252, 11824.151194, 11831.656686, 11839.162728, 11846.669320, 11854.176461, 11861.684151, 11869.192390, - 11876.701177, 11884.210512, 11891.720395, 11899.230826, 11906.741804, 11914.253328, 11921.765400, 11929.278017, - 11936.791181, 11944.304890, 11951.819145, 11959.333944, 11966.849289, 11974.365178, 11981.881611, 11989.398589, - 11996.916109, 12004.434174, 12011.952781, 12019.471931, 12026.991623, 12034.511858, 12042.032634, 12049.553952, - 12057.075811, 12064.598212, 12072.121152, 12079.644634, 12087.168655, 12094.693216, 12102.218317, 12109.743957, - 12117.270136, 12124.796854, 12132.324110, 12139.851904, 12147.380235, 12154.909105, 12162.438511, 12169.968454, - 12177.498934, 12185.029951, 12192.561503, 12200.093591, 12207.626215, 12215.159374, 12222.693067, 12230.227296, - 12237.762058, 12245.297355, 12252.833186, 12260.369549, 12267.906447, 12275.443877, 12282.981839, 12290.520334, - 12298.059361, 12305.598920, 12313.139010, 12320.679632, 12328.220784, 12335.762468, 12343.304681, 12350.847425, - 12358.390698, 12365.934501, 12373.478833, 12381.023694, 12388.569084, 12396.115002, 12403.661448, 12411.208422, - 12418.755924, 12426.303953, 12433.852509, 12441.401592, 12448.951201, 12456.501336, 12464.051997, 12471.603184, - 12479.154896, 12486.707134, 12494.259896, 12501.813182, 12509.366993, 12516.921328, 12524.476187, 12532.031569, - 12539.587474, 12547.143902, 12554.700852, 12562.258325, 12569.816320, 12577.374837, 12584.933875, 12592.493435, - 12600.053515, 12607.614116, 12615.175238, 12622.736880, 12630.299041, 12637.861722, 12645.424923, 12652.988643, - 12660.552881, 12668.117638, 12675.682913, 12683.248707, 12690.815018, 12698.381846, 12705.949192, 12713.517054, - 12721.085434, 12728.654329, 12736.223741, 12743.793669, 12751.364112, 12758.935071, 12766.506544, 12774.078533, - 12781.651036, 12789.224053, 12796.797584, 12804.371629, 12811.946188, 12819.521259, 12827.096844, 12834.672941, - 12842.249551, 12849.826673, 12857.404307, 12864.982452, 12872.561109, 12880.140277, 12887.719956, 12895.300146, - 12902.880845, 12910.462055, 12918.043775, 12925.626004, 12933.208742, 12940.791990, 12948.375746, 12955.960011, - 12963.544784, 12971.130065, 12978.715854, 12986.302150, 12993.888954, 13001.476264, 13009.064082, 13016.652405, - 13024.241235, 13031.830571, 13039.420413, 13047.010759, 13054.601612, 13062.192969, 13069.784830, 13077.377196, - 13084.970067, 13092.563441, 13100.157319, 13107.751700, 13115.346584, 13122.941972, 13130.537862, 13138.134254, - 13145.731148, 13153.328545, 13160.926443, 13168.524842, 13176.123742, 13183.723144, 13191.323046, 13198.923448, - 13206.524351, 13214.125753, 13221.727655, 13229.330056, 13236.932957, 13244.536356, 13252.140254, 13259.744650, - 13267.349545, 13274.954937, 13282.560827, 13290.167214, 13297.774099, 13305.381480, 13312.989359, 13320.597733, - 13328.206604, 13335.815970, 13343.425832, 13351.036190, 13358.647043, 13366.258390, 13373.870233, 13381.482570, - 13389.095401, 13396.708726, 13404.322544, 13411.936857, 13419.551662, 13427.166960, 13434.782751, 13442.399035, - 13450.015811, 13457.633079, 13465.250838, 13472.869089, 13480.487832, 13488.107065, 13495.726789, 13503.347004, - 13510.967709, 13518.588904, 13526.210589, 13533.832764, 13541.455428, 13549.078581, 13556.702223, 13564.326353, - 13571.950972, 13579.576080, 13587.201675, 13594.827757, 13602.454328, 13610.081385, 13617.708929, 13625.336960, - 13632.965478, 13640.594482, 13648.223972, 13655.853948, 13663.484409, 13671.115355, 13678.746787, 13686.378704, - 13694.011105, 13701.643990, 13709.277360, 13716.911213, 13724.545551, 13732.180371, 13739.815675, 13747.451462, - 13755.087732, 13762.724484, 13770.361718, 13777.999435, 13785.637633, 13793.276313, 13800.915474, 13808.555116, - 13816.195239, 13823.835843, 13831.476927, 13839.118492, 13846.760536, 13854.403060, 13862.046064, 13869.689547, - 13877.333509, 13884.977950, 13892.622869, 13900.268267, 13907.914143, 13915.560496, 13923.207328, 13930.854637, - 13938.502423, 13946.150686, 13953.799425, 13961.448642, 13969.098334, 13976.748503, 13984.399148, 13992.050268, - 13999.701863, 14007.353934, 14015.006480, 14022.659500, 14030.312995, 14037.966964, 14045.621407, 14053.276325, - 14060.931715, 14068.587579, 14076.243916, 14083.900726, 14091.558009, 14099.215765, 14106.873992, 14114.532692, - 14122.191863, 14129.851506, 14137.511620, 14145.172206, 14152.833262, 14160.494789, 14168.156787, 14175.819255, - 14183.482192, 14191.145600, 14198.809477, 14206.473824, 14214.138640, 14221.803924, 14229.469678, 14237.135900, - 14244.802590, 14252.469748, 14260.137374, 14267.805468, 14275.474029, 14283.143057, 14290.812553, 14298.482515, - 14306.152943, 14313.823838, 14321.495199, 14329.167026, 14336.839318, 14344.512076, 14352.185299, 14359.858987, - 14367.533140, 14375.207758, 14382.882840, 14390.558386, 14398.234396, 14405.910869, 14413.587806, 14421.265207, - 14428.943070, 14436.621397, 14444.300186, 14451.979437, 14459.659151, 14467.339326, 14475.019964, 14482.701063, - 14490.382623, 14498.064645, 14505.747127, 14513.430070, 14521.113474, 14528.797338, 14536.481662, 14544.166446, - 14551.851690, 14559.537393, 14567.223555, 14574.910176, 14582.597256, 14590.284795, 14597.972792, 14605.661248, - 14613.350161, 14621.039532, 14628.729361, 14636.419647, 14644.110390, 14651.801590, 14659.493247, 14667.185360, - 14674.877930, 14682.570956, 14690.264437, 14697.958375, 14705.652767, 14713.347616, 14721.042919, 14728.738677, - 14736.434889, 14744.131556, 14751.828678, 14759.526253, 14767.224282, 14774.922765, 14782.621701, 14790.321091, - 14798.020933, 14805.721228, 14813.421976, 14821.123176, 14828.824829, 14836.526933, 14844.229489, 14851.932497, - 14859.635956, 14867.339866, 14875.044227, 14882.749039, 14890.454302, 14898.160014, 14905.866177, 14913.572790, - 14921.279853, 14928.987365, 14936.695327, 14944.403737, 14952.112597, 14959.821905, 14967.531662, 14975.241867, - 14982.952521, 14990.663622, 14998.375171, 15006.087167, 15013.799611, 15021.512502, 15029.225840, 15036.939625, - 15044.653856, 15052.368533, 15060.083657, 15067.799226, 15075.515242, 15083.231702, 15090.948609, 15098.665960, - 15106.383756, 15114.101997, 15121.820683, 15129.539812, 15137.259386, 15144.979404, 15152.699866, 15160.420771, - 15168.142120, 15175.863912, 15183.586146, 15191.308824, 15199.031944, 15206.755506, 15214.479511, 15222.203958, - 15229.928846, 15237.654176, 15245.379948, 15253.106160, 15260.832814, 15268.559908, 15276.287444, 15284.015419, - 15291.743835, 15299.472691, 15307.201986, 15314.931722, 15322.661897, 15330.392511, 15338.123564, 15345.855056, - 15353.586986, 15361.319356, 15369.052163, 15376.785409, 15384.519092, 15392.253214, 15399.987773, 15407.722769, - 15415.458202, 15423.194072, 15430.930380, 15438.667123, 15446.404303, 15454.141920, 15461.879972, 15469.618460, - 15477.357384, 15485.096743, 15492.836537, 15500.576767, 15508.317431, 15516.058530, 15523.800064, 15531.542032, - 15539.284434, 15547.027270, 15554.770540, 15562.514243, 15570.258380, 15578.002949, 15585.747952, 15593.493388, - 15601.239256, 15608.985557, 15616.732290, 15624.479455, 15632.227051, 15639.975080, 15647.723540, 15655.472431, - 15663.221754, 15670.971507, 15678.721691, 15686.472306, 15694.223351, 15701.974826, 15709.726732, 15717.479067, - 15725.231832, 15732.985026, 15740.738650, 15748.492702, 15756.247184, 15764.002094, 15771.757433, 15779.513200, - 15787.269395, 15795.026019, 15802.783070, 15810.540549, 15818.298455, 15826.056788, 15833.815549, 15841.574736, - 15849.334350, 15857.094391, 15864.854858, 15872.615751, 15880.377070, 15888.138815, 15895.900986, 15903.663582, - 15911.426603, 15919.190050, 15926.953921, 15934.718217, 15942.482938, 15950.248083, 15958.013652, 15965.779645, - 15973.546062, 15981.312902, 15989.080166, 15996.847853, 16004.615964, 16012.384497, 16020.153453, 16027.922832, - 16035.692633, 16043.462856, 16051.233501, 16059.004568, 16066.776057, 16074.547967, 16082.320299, 16090.093052, - 16097.866225, 16105.639820, 16113.413835, 16121.188270, 16128.963126, 16136.738402, 16144.514098, 16152.290213, - 16160.066748, 16167.843703, 16175.621076, 16183.398869, 16191.177080, 16198.955710, 16206.734759, 16214.514226, - 16222.294111, 16230.074414, 16237.855135, 16245.636274, 16253.417830, 16261.199803, 16268.982193, 16276.765000, - 16284.548224, 16292.331865, 16300.115922, 16307.900395, 16315.685285, 16323.470590, 16331.256311, 16339.042447, - 16346.828999, 16354.615966, 16362.403348, 16370.191145, 16377.979356, 16385.767982, 16393.557023, 16401.346477, - 16409.136346, 16416.926628, 16424.717324, 16432.508434, 16440.299957, 16448.091893, 16455.884242, 16463.677003, - 16471.470178, 16479.263764, 16487.057764, 16494.852175, 16502.646998, 16510.442233, 16518.237879, 16526.033937, - 16533.830407, 16541.627287, 16549.424578, 16557.222280, 16565.020393, 16572.818916, 16580.617849, 16588.417193, - 16596.216946, 16604.017109, 16611.817682, 16619.618664, 16627.420055, 16635.221855, 16643.024065, 16650.826683, - 16658.629710, 16666.433145, 16674.236988, 16682.041239, 16689.845899, 16697.650966, 16705.456440, 16713.262322, - 16721.068612, 16728.875308, 16736.682411, 16744.489921, 16752.297838, 16760.106161, 16767.914890, 16775.724026, - 16783.533567, 16791.343514, 16799.153867, 16806.964625, 16814.775788, 16822.587357, 16830.399330, 16838.211708, - 16846.024491, 16853.837678, 16861.651270, 16869.465266, 16877.279665, 16885.094469, 16892.909676, 16900.725286, - 16908.541300, 16916.357717, 16924.174537, 16931.991760, 16939.809385, 16947.627413, 16955.445844, 16963.264676, - 16971.083910, 16978.903547, 16986.723585, 16994.544024, 17002.364865, 17010.186107, 17018.007750, 17025.829794, - 17033.652239, 17041.475084, 17049.298330, 17057.121976, 17064.946022, 17072.770468, 17080.595314, 17088.420559, - 17096.246204, 17104.072248, 17111.898691, 17119.725533, 17127.552774, 17135.380413, 17143.208451, 17151.036888, - 17158.865722, 17166.694955, 17174.524585, 17182.354613, 17190.185039, 17198.015862, 17205.847082, 17213.678699, - 17221.510714, 17229.343124, 17237.175932, 17245.009136, 17252.842736, 17260.676733, 17268.511125, 17276.345913, - 17284.181097, 17292.016676, 17299.852651, 17307.689020, 17315.525785, 17323.362945, 17331.200499, 17339.038448, - 17346.876791, 17354.715529, 17362.554661, 17370.394186, 17378.234105, 17386.074418, 17393.915125, 17401.756225, - 17409.597718, 17417.439604, 17425.281882, 17433.124554, 17440.967618, 17448.811074, 17456.654923, 17464.499164, - 17472.343796, 17480.188821, 17488.034237, 17495.880044, 17503.726243, 17511.572833, 17519.419814, 17527.267186, - 17535.114948, 17542.963101, 17550.811645, 17558.660579, 17566.509902, 17574.359616, 17582.209720, 17590.060213, - 17597.911096, 17605.762368, 17613.614029, 17621.466079, 17629.318518, 17637.171346, 17645.024562, 17652.878167, - 17660.732160, 17668.586541, 17676.441311, 17684.296468, 17692.152012, 17700.007944, 17707.864264, 17715.720971, - 17723.578065, 17731.435545, 17739.293413, 17747.151667, 17755.010308, 17762.869335, 17770.728748, 17778.588547, - 17786.448732, 17794.309303, 17802.170259, 17810.031601, 17817.893328, 17825.755440, 17833.617938, 17841.480820, - 17849.344086, 17857.207738, 17865.071773, 17872.936193, 17880.800997, 17888.666185, 17896.531757, 17904.397712, - 17912.264051, 17920.130774, 17927.997879, 17935.865368, 17943.733239, 17951.601493, 17959.470130, 17967.339150, - 17975.208551, 17983.078335, 17990.948501, 17998.819049, 18006.689979, 18014.561290, 18022.432983, 18030.305056, - 18038.177512, 18046.050348, 18053.923565, 18061.797163, 18069.671141, 18077.545500, 18085.420239, 18093.295358, - 18101.170858, 18109.046737, 18116.922996, 18124.799634, 18132.676652, 18140.554049, 18148.431825, 18156.309981, - 18164.188515, 18172.067428, 18179.946719, 18187.826389, 18195.706438, 18203.586864, 18211.467668, 18219.348850, - 18227.230410, 18235.112348, 18242.994663, 18250.877355, 18258.760424, 18266.643871, 18274.527694, 18282.411894, - 18290.296470, 18298.181423, 18306.066752, 18313.952458, 18321.838539, 18329.724997, 18337.611830, 18345.499038, - 18353.386622, 18361.274582, 18369.162916, 18377.051626, 18384.940710, 18392.830169, 18400.720003, 18408.610211, - 18416.500794, 18424.391750, 18432.283081, 18440.174786, 18448.066864, 18455.959316, 18463.852142, 18471.745341, - 18479.638913, 18487.532858, 18495.427176, 18503.321867, 18511.216930, 18519.112366, 18527.008175, 18534.904355, - 18542.800908, 18550.697833, 18558.595129, 18566.492797, 18574.390837, 18582.289248, 18590.188030, 18598.087184, - 18605.986708, 18613.886604, 18621.786870, 18629.687506, 18637.588513, 18645.489891, 18653.391638, 18661.293756, - 18669.196243, 18677.099100, 18685.002327, 18692.905923, 18700.809889, 18708.714224, 18716.618928, 18724.524001, - 18732.429442, 18740.335253, 18748.241431, 18756.147979, 18764.054894, 18771.962178, 18779.869829, 18787.777849, - 18795.686236, 18803.594991, 18811.504113, 18819.413602, 18827.323459, 18835.233683, 18843.144273, 18851.055231, - 18858.966555, 18866.878245, 18874.790302, 18882.702725, 18890.615515, 18898.528670, 18906.442191, 18914.356077, - 18922.270330, 18930.184947, 18938.099930, 18946.015279, 18953.930992, 18961.847070, 18969.763513, 18977.680320, - 18985.597492, 18993.515029, 19001.432929, 19009.351194, 19017.269823, 19025.188815, 19033.108171, 19041.027891, - 19048.947974, 19056.868421, 19064.789230, 19072.710403, 19080.631939, 19088.553837, 19096.476098, 19104.398722, - 19112.321708, 19120.245056, 19128.168766, 19136.092839, 19144.017273, 19151.942069, 19159.867226, 19167.792745, - 19175.718626, 19183.644867, 19191.571470, 19199.498433, 19207.425758, 19215.353443, 19223.281488, 19231.209894, - 19239.138661, 19247.067787, 19254.997274, 19262.927120, 19270.857326, 19278.787892, 19286.718817, 19294.650102, - 19302.581746, 19310.513749, 19318.446112, 19326.378833, 19334.311912, 19342.245351, 19350.179148, 19358.113303, - 19366.047816, 19373.982688, 19381.917917, 19389.853505, 19397.789450, 19405.725753, 19413.662413, 19421.599430, - 19429.536805, 19437.474537, 19445.412625, 19453.351071, 19461.289873, 19469.229032, 19477.168547, 19485.108419, - 19493.048647, 19500.989230, 19508.930170, 19516.871466, 19524.813117, 19532.755124, 19540.697486, 19548.640204, - 19556.583276, 19564.526704, 19572.470487, 19580.414624, 19588.359116, 19596.303963, 19604.249164, 19612.194720, - 19620.140629, 19628.086893, 19636.033511, 19643.980482, 19651.927807, 19659.875485, 19667.823517, 19675.771903, - 19683.720641, 19691.669733, 19699.619177, 19707.568974, 19715.519124, 19723.469627, 19731.420482, 19739.371689, - 19747.323248, 19755.275159, 19763.227423, 19771.180038, 19779.133005, 19787.086323, 19795.039993, 19802.994014, - 19810.948386, 19818.903109, 19826.858184, 19834.813609, 19842.769385, 19850.725511, 19858.681988, 19866.638815, - 19874.595992, 19882.553520, 19890.511397, 19898.469624, 19906.428201, 19914.387128, 19922.346403, 19930.306029, - 19938.266003, 19946.226327, 19954.187000, 19962.148021, 19970.109391, 19978.071110, 19986.033177, 19993.995593, - 20001.958357, 20009.921469, 20017.884929, 20025.848737, 20033.812893, 20041.777396, 20049.742247, 20057.707445, - 20065.672991, 20073.638884, 20081.605123, 20089.571710, 20097.538644, 20105.505924, 20113.473550, 20121.441524, - 20129.409843, 20137.378509, 20145.347521, 20153.316878, 20161.286582, 20169.256631, 20177.227026, 20185.197767, - 20193.168852, 20201.140283, 20209.112059, 20217.084181, 20225.056647, 20233.029457, 20241.002613, 20248.976113, - 20256.949957, 20264.924146, 20272.898679, 20280.873556, 20288.848776, 20296.824341, 20304.800249, 20312.776501, - 20320.753097, 20328.730036, 20336.707318, 20344.684943, 20352.662911, 20360.641222, 20368.619875, 20376.598872, - 20384.578211, 20392.557892, 20400.537916, 20408.518281, 20416.498989, 20424.480039, 20432.461431, 20440.443164, - 20448.425239, 20456.407655, 20464.390413, 20472.373512, 20480.356952, 20488.340733, 20496.324855, 20504.309317, - 20512.294121, 20520.279265, 20528.264749, 20536.250574, 20544.236739, 20552.223244, 20560.210089, 20568.197273, - 20576.184798, 20584.172662, 20592.160865, 20600.149408, 20608.138291, 20616.127512, 20624.117073, 20632.106972, - 20640.097210, 20648.087787, 20656.078702, 20664.069956, 20672.061549, 20680.053479, 20688.045748, 20696.038354, - 20704.031299, 20712.024581, 20720.018201, 20728.012159, 20736.006454, 20744.001086, 20751.996056, 20759.991362, - 20767.987006, 20775.982986, 20783.979304, 20791.975958, 20799.972948, 20807.970275, 20815.967938, 20823.965937, - 20831.964273, 20839.962944, 20847.961951, 20855.961294, 20863.960973, 20871.960987, 20879.961336, 20887.962021, - 20895.963041, 20903.964396, 20911.966086, 20919.968111, 20927.970470, 20935.973165, 20943.976193, 20951.979556, - 20959.983254, 20967.987285, 20975.991651, 20983.996350, 20992.001384, 21000.006751, 21008.012451, 21016.018485, - 21024.024853, 21032.031554, 21040.038588, 21048.045955, 21056.053655, 21064.061688, 21072.070053, 21080.078752, - 21088.087782, 21096.097145, 21104.106841, 21112.116868, 21120.127228, 21128.137919, 21136.148943, 21144.160298, - 21152.171985, 21160.184003, 21168.196352, 21176.209033, 21184.222045, 21192.235389, 21200.249063, 21208.263068, - 21216.277404, 21224.292070, 21232.307067, 21240.322394, 21248.338052, 21256.354040, 21264.370357, 21272.387005, - 21280.403983, 21288.421291, 21296.438928, 21304.456894, 21312.475191, 21320.493816, 21328.512771, 21336.532055, - 21344.551667, 21352.571609, 21360.591879, 21368.612479, 21376.633406, 21384.654663, 21392.676247, 21400.698160, - 21408.720401, 21416.742970, 21424.765867, 21432.789091, 21440.812644, 21448.836524, 21456.860731, 21464.885266, - 21472.910128, 21480.935317, 21488.960834, 21496.986677, 21505.012847, 21513.039344, 21521.066168, 21529.093318, - 21537.120795, 21545.148597, 21553.176726, 21561.205182, 21569.233963, 21577.263070, 21585.292503, 21593.322261, - 21601.352345, 21609.382755, 21617.413490, 21625.444550, 21633.475935, 21641.507646, 21649.539681, 21657.572041, - 21665.604726, 21673.637736, 21681.671070, 21689.704728, 21697.738711, 21705.773018, 21713.807649, 21721.842604, - 21729.877883, 21737.913485, 21745.949412, 21753.985662, 21762.022235, 21770.059132, 21778.096352, 21786.133895, - 21794.171761, 21802.209950, 21810.248462, 21818.287297, 21826.326455, 21834.365934, 21842.405737, 21850.445862, - 21858.486308, 21866.527077, 21874.568168, 21882.609581, 21890.651316, 21898.693372, 21906.735750, 21914.778450, - 21922.821471, 21930.864813, 21938.908476, 21946.952461, 21954.996766, 21963.041392, 21971.086339, 21979.131607, - 21987.177195, 21995.223104, 22003.269333, 22011.315883, 22019.362752, 22027.409942, 22035.457451, 22043.505281, - 22051.553430, 22059.601898, 22067.650687, 22075.699794, 22083.749222, 22091.798968, 22099.849033, 22107.899418, - 22115.950121, 22124.001143, 22132.052484, 22140.104144, 22148.156122, 22156.208418, 22164.261033, 22172.313966, - 22180.367217, 22188.420787, 22196.474674, 22204.528879, 22212.583401, 22220.638241, 22228.693399, 22236.748874, - 22244.804667, 22252.860776, 22260.917203, 22268.973947, 22277.031008, 22285.088385, 22293.146079, 22301.204090, - 22309.262417, 22317.321061, 22325.380021, 22333.439297, 22341.498890, 22349.558798, 22357.619022, 22365.679562, - 22373.740418, 22381.801589, 22389.863076, 22397.924879, 22405.986996, 22414.049429, 22422.112177, 22430.175240, - 22438.238618, 22446.302310, 22454.366318, 22462.430639, 22470.495276, 22478.560227, 22486.625492, 22494.691071, - 22502.756965, 22510.823173, 22518.889694, 22526.956529, 22535.023678, 22543.091141, 22551.158917, 22559.227007, - 22567.295410, 22575.364126, 22583.433155, 22591.502498, 22599.572153, 22607.642121, 22615.712402, 22623.782996, - 22631.853902, 22639.925120, 22647.996651, 22656.068494, 22664.140650, 22672.213117, 22680.285896, 22688.358988, - 22696.432391, 22704.506105, 22712.580131, 22720.654469, 22728.729118, 22736.804078, 22744.879350, 22752.954933, - 22761.030826, 22769.107031, 22777.183546, 22785.260372, 22793.337509, 22801.414956, 22809.492714, 22817.570781, - 22825.649160, 22833.727848, 22841.806846, 22849.886154, 22857.965772, 22866.045700, 22874.125937, 22882.206484, - 22890.287341, 22898.368507, 22906.449982, 22914.531766, 22922.613859, 22930.696261, 22938.778972, 22946.861992, - 22954.945321, 22963.028958, 22971.112904, 22979.197158, 22987.281720, 22995.366591, 23003.451770, 23011.537257, - 23019.623051, 23027.709154, 23035.795564, 23043.882282, 23051.969308, 23060.056640, 23068.144281, 23076.232228, - 23084.320483, 23092.409045, 23100.497914, 23108.587089, 23116.676572, 23124.766361, 23132.856457, 23140.946859, - 23149.037568, 23157.128583, 23165.219904, 23173.311531, 23181.403465, 23189.495704, 23197.588250, 23205.681101, - 23213.774257, 23221.867720, 23229.961487, 23238.055560, 23246.149939, 23254.244623, 23262.339611, 23270.434905, - 23278.530504, 23286.626407, 23294.722616, 23302.819129, 23310.915946, 23319.013068, 23327.110494, 23335.208225, - 23343.306260, 23351.404598, 23359.503241, 23367.602188, 23375.701439, 23383.800993, 23391.900851, 23400.001012, - 23408.101477, 23416.202245, 23424.303317, 23432.404692, 23440.506369, 23448.608350, 23456.710634, 23464.813220, - 23472.916109, 23481.019301, 23489.122795, 23497.226592, 23505.330691, 23513.435092, 23521.539796, 23529.644801, - 23537.750109, 23545.855718, 23553.961629, 23562.067842, 23570.174357, 23578.281173, 23586.388290, 23594.495709, - 23602.603429, 23610.711450, 23618.819773, 23626.928396, 23635.037320, 23643.146545, 23651.256071, 23659.365897, - 23667.476024, 23675.586451, 23683.697179, 23691.808206, 23699.919534, 23708.031163, 23716.143091, 23724.255319, - 23732.367846, 23740.480674, 23748.593801, 23756.707228, 23764.820954, 23772.934979, 23781.049304, 23789.163928, - 23797.278851, 23805.394073, 23813.509594, 23821.625413, 23829.741532, 23837.857949, 23845.974664, 23854.091678, - 23862.208991, 23870.326602, 23878.444511, 23886.562718, 23894.681223, 23902.800026, 23910.919127, 23919.038525, - 23927.158221, 23935.278215, 23943.398507, 23951.519095, 23959.639981, 23967.761165, 23975.882645, 23984.004422, - 23992.126497, 24000.248868, 24008.371536, 24016.494501, 24024.617762, 24032.741320, 24040.865174, 24048.989325, - 24057.113772, 24065.238515, 24073.363554, 24081.488889, 24089.614520, 24097.740447, 24105.866669, 24113.993187, - 24122.120001, 24130.247110, 24138.374515, 24146.502215, 24154.630210, 24162.758500, 24170.887085, 24179.015965, - 24187.145140, 24195.274610, 24203.404374, 24211.534433, 24219.664787, 24227.795435, 24235.926377, 24244.057614, - 24252.189144, 24260.320969, 24268.453088, 24276.585501, 24284.718207, 24292.851207, 24300.984501, 24309.118089, - 24317.251970, 24325.386144, 24333.520611, 24341.655372, 24349.790426, 24357.925773, 24366.061413, 24374.197346, - 24382.333571, 24390.470090, 24398.606900, 24406.744004, 24414.881400, 24423.019088, 24431.157068, 24439.295341, - 24447.433906, 24455.572762, 24463.711911, 24471.851352, 24479.991084, 24488.131108, 24496.271423, 24504.412030, - 24512.552929, 24520.694119, 24528.835600, 24536.977372, 24545.119435, 24553.261789, 24561.404435, 24569.547371, - 24577.690597, 24585.834115, 24593.977923, 24602.122021, 24610.266410, 24618.411089, 24626.556059, 24634.701318, - 24642.846868, 24650.992708, 24659.138837, 24667.285256, 24675.431965, 24683.578964, 24691.726252, 24699.873830, - 24708.021697, 24716.169854, 24724.318299, 24732.467034, 24740.616058, 24748.765371, 24756.914973, 24765.064863, - 24773.215042, 24781.365510, 24789.516267, 24797.667312, 24805.818645, 24813.970267, 24822.122177, 24830.274375, - 24838.426861, 24846.579635, 24854.732697, 24862.886046, 24871.039684, 24879.193609, 24887.347822, 24895.502322, - 24903.657110, 24911.812184, 24919.967547, 24928.123196, 24936.279132, 24944.435355, 24952.591866, 24960.748663, - 24968.905746, 24977.063117, 24985.220774, 24993.378717, 25001.536947, 25009.695464, 25017.854266, 25026.013355, - 25034.172730, 25042.332390, 25050.492337, 25058.652569, 25066.813088, 25074.973892, 25083.134981, 25091.296356, - 25099.458017, 25107.619962, 25115.782193, 25123.944710, 25132.107511, 25140.270597, 25148.433969, 25156.597625, - 25164.761566, 25172.925791, 25181.090302, 25189.255097, 25197.420176, 25205.585539, 25213.751187, 25221.917120, - 25230.083336, 25238.249836, 25246.416620, 25254.583689, 25262.751041, 25270.918676, 25279.086596, 25287.254799, - 25295.423285, 25303.592055, 25311.761108, 25319.930444, 25328.100064, 25336.269967, 25344.440152, 25352.610621, - 25360.781372, 25368.952406, 25377.123723, 25385.295323, 25393.467205, 25401.639369, 25409.811816, 25417.984545, - 25426.157556, 25434.330850, 25442.504425, 25450.678283, 25458.852422, 25467.026843, 25475.201546, 25483.376531, - 25491.551797, 25499.727344, 25507.903173, 25516.079284, 25524.255675, 25532.432348, 25540.609302, 25548.786537, - 25556.964053, 25565.141849, 25573.319927, 25581.498285, 25589.676924, 25597.855843, 25606.035043, 25614.214523, - 25622.394284, 25630.574324, 25638.754645, 25646.935246, 25655.116127, 25663.297288, 25671.478729, 25679.660449, - 25687.842449, 25696.024729, 25704.207288, 25712.390127, 25720.573245, 25728.756642, 25736.940319, 25745.124275, - 25753.308510, 25761.493023, 25769.677816, 25777.862887, 25786.048238, 25794.233867, 25802.419774, 25810.605960, - 25818.792424, 25826.979167, 25835.166188, 25843.353488, 25851.541065, 25859.728920, 25867.917054, 25876.105465, - 25884.294154, 25892.483121, 25900.672366, 25908.861888, 25917.051687, 25925.241764, 25933.432119, 25941.622750, - 25949.813659, 25958.004845, 25966.196308, 25974.388048, 25982.580065, 25990.772359, 25998.964930, 26007.157777, - 26015.350900, 26023.544301, 26031.737977, 26039.931930, 26048.126160, 26056.320665, 26064.515447, 26072.710504, - 26080.905838, 26089.101448, 26097.297333, 26105.493494, 26113.689931, 26121.886643, 26130.083631, 26138.280895, - 26146.478434, 26154.676248, 26162.874337, 26171.072701, 26179.271341, 26187.470255, 26195.669444, 26203.868909, - 26212.068648, 26220.268661, 26228.468950, 26236.669512, 26244.870350, 26253.071461, 26261.272847, 26269.474507, - 26277.676442, 26285.878650, 26294.081133, 26302.283889, 26310.486919, 26318.690223, 26326.893801, 26335.097652, - 26343.301777, 26351.506176, 26359.710848, 26367.915793, 26376.121011, 26384.326503, 26392.532267, 26400.738305, - 26408.944616, 26417.151200, 26425.358056, 26433.565185, 26441.772587, 26449.980261, 26458.188208, 26466.396428, - 26474.604919, 26482.813684, 26491.022720, 26499.232028, 26507.441609, 26515.651461, 26523.861586, 26532.071982, - 26540.282650, 26548.493590, 26556.704801, 26564.916284, 26573.128038, 26581.340064, 26589.552361, 26597.764930, - 26605.977769, 26614.190880, 26622.404262, 26630.617914, 26638.831838, 26647.046032, 26655.260498, 26663.475233, - 26671.690240, 26679.905517, 26688.121064, 26696.336882, 26704.552970, 26712.769328, 26720.985957, 26729.202855, - 26737.420024, 26745.637463, 26753.855171, 26762.073149, 26770.291397, 26778.509915, 26786.728702, 26794.947759, - 26803.167085, 26811.386680, 26819.606545, 26827.826679, 26836.047082, 26844.267754, 26852.488695, 26860.709905, - 26868.931384, 26877.153132, 26885.375148, 26893.597433, 26901.819987, 26910.042809, 26918.265900, 26926.489259, - 26934.712886, 26942.936781, 26951.160945, 26959.385376, 26967.610076, 26975.835043, 26984.060279, 26992.285782, - 27000.511553, 27008.737591, 27016.963897, 27025.190470, 27033.417311, 27041.644420, 27049.871795, 27058.099438, - 27066.327348, 27074.555525, 27082.783968, 27091.012679, 27099.241657, 27107.470901, 27115.700412, 27123.930190, - 27132.160234, 27140.390545, 27148.621123, 27156.851966, 27165.083076, 27173.314452, 27181.546094, 27189.778002, - 27198.010177, 27206.242617, 27214.475323, 27222.708295, 27230.941532, 27239.175035, 27247.408804, 27255.642838, - 27263.877138, 27272.111703, 27280.346533, 27288.581629, 27296.816989, 27305.052615, 27313.288506, 27321.524661, - 27329.761082, 27337.997767, 27346.234717, 27354.471932, 27362.709411, 27370.947155, 27379.185163, 27387.423436, - 27395.661973, 27403.900774, 27412.139839, 27420.379169, 27428.618762, 27436.858620, 27445.098741, 27453.339126, - 27461.579775, 27469.820687, 27478.061864, 27486.303303, 27494.545006, 27502.786973, 27511.029203, 27519.271696, - 27527.514452, 27535.757472, 27544.000754, 27552.244300, 27560.488108, 27568.732180, 27576.976514, 27585.221110, - 27593.465970, 27601.711092, 27609.956476, 27618.202123, 27626.448032, 27634.694204, 27642.940638, 27651.187334, - 27659.434292, 27667.681512, 27675.928994, 27684.176738, 27692.424743, 27700.673011, 27708.921540, 27717.170331, - 27725.419383, 27733.668697, 27741.918272, 27750.168108, 27758.418206, 27766.668565, 27774.919185, 27783.170066, - 27791.421208, 27799.672611, 27807.924275, 27816.176200, 27824.428385, 27832.680832, 27840.933538, 27849.186505, - 27857.439733, 27865.693221, 27873.946969, 27882.200978, 27890.455247, 27898.709776, 27906.964565, 27915.219614, - 27923.474922, 27931.730491, 27939.986319, 27948.242408, 27956.498755, 27964.755363, 27973.012230, 27981.269356, - 27989.526741, 27997.784386, 28006.042291, 28014.300454, 28022.558876, 28030.817558, 28039.076498, 28047.335698, - 28055.595156, 28063.854873, 28072.114849, 28080.375083, 28088.635576, 28096.896327, 28105.157337, 28113.418605, - 28121.680131, 28129.941916, 28138.203959, 28146.466260, 28154.728819, 28162.991636, 28171.254711, 28179.518043, - 28187.781634, 28196.045482, 28204.309588, 28212.573951, 28220.838572, 28229.103450, 28237.368586, 28245.633979, - 28253.899629, 28262.165536, 28270.431701, 28278.698122, 28286.964801, 28295.231736, 28303.498928, 28311.766377, - 28320.034083, 28328.302045, 28336.570264, 28344.838739, 28353.107471, 28361.376459, 28369.645704, 28377.915205, - 28386.184962, 28394.454975, 28402.725244, 28410.995769, 28419.266550, 28427.537587, 28435.808879, 28444.080428, - 28452.352232, 28460.624291, 28468.896606, 28477.169177, 28485.442003, 28493.715084, 28501.988421, 28510.262013, - 28518.535860, 28526.809962, 28535.084319, 28543.358931, 28551.633798, 28559.908919, 28568.184296, 28576.459927, - 28584.735812, 28593.011952, 28601.288347, 28609.564996, 28617.841900, 28626.119058, 28634.396470, 28642.674136, - 28650.952056, 28659.230230, 28667.508659, 28675.787341, 28684.066277, 28692.345466, 28700.624910, 28708.904607, - 28717.184558, 28725.464762, 28733.745220, 28742.025931, 28750.306895, 28758.588113, 28766.869584, 28775.151308, - 28783.433285, 28791.715515, 28799.997998, 28808.280734, 28816.563722, 28824.846964, 28833.130458, 28841.414205, - 28849.698204, 28857.982456, 28866.266960, 28874.551717, 28882.836726, 28891.121987, 28899.407500, 28907.693265, - 28915.979283, 28924.265552, 28932.552074, 28940.838847, 28949.125872, 28957.413149, 28965.700677, 28973.988457, - 28982.276489, 28990.564772, 28998.853306, 29007.142092, 29015.431129, 29023.720417, 29032.009957, 29040.299748, - 29048.589789, 29056.880082, 29065.170625, 29073.461420, 29081.752465, 29090.043761, 29098.335307, 29106.627104, - 29114.919152, 29123.211450, 29131.503998, 29139.796797, 29148.089846, 29156.383146, 29164.676695, 29172.970495, - 29181.264545, 29189.558844, 29197.853394, 29206.148193, 29214.443242, 29222.738541, 29231.034090, 29239.329888, - 29247.625935, 29255.922232, 29264.218779, 29272.515575, 29280.812620, 29289.109914, 29297.407458, 29305.705251, - 29314.003292, 29322.301583, 29330.600122, 29338.898911, 29347.197948, 29355.497234, 29363.796768, 29372.096552, - 29380.396583, 29388.696863, 29396.997392, 29405.298169, 29413.599194, 29421.900468, 29430.201989, 29438.503759, - 29446.805777, 29455.108043, 29463.410557, 29471.713318, 29480.016327, 29488.319585, 29496.623089, 29504.926842, - 29513.230842, 29521.535089, 29529.839584, 29538.144326, 29546.449316, 29554.754553, 29563.060037, 29571.365768, - 29579.671746, 29587.977971, 29596.284444, 29604.591163, 29612.898129, 29621.205341, 29629.512800, 29637.820506, - 29646.128459, 29654.436658, 29662.745104, 29671.053795, 29679.362734, 29687.671918, 29695.981349, 29704.291026, - 29712.600949, 29720.911118, 29729.221533, 29737.532194, 29745.843101, 29754.154253, 29762.465651, 29770.777295, - 29779.089185, 29787.401320, 29795.713701, 29804.026327, 29812.339198, 29820.652315, 29828.965677, 29837.279284, - 29845.593136, 29853.907233, 29862.221576, 29870.536163, 29878.850995, 29887.166072, 29895.481394, 29903.796960, - 29912.112772, 29920.428827, 29928.745128, 29937.061672, 29945.378461, 29953.695495, 29962.012773, 29970.330295, - 29978.648061, 29986.966071, 29995.284325, 30003.602824, 30011.921566, 30020.240552, 30028.559782, 30036.879256, - 30045.198973, 30053.518934, 30061.839139, 30070.159587, 30078.480278, 30086.801213, 30095.122392, 30103.443813, - 30111.765478, 30120.087386, 30128.409537, 30136.731931, 30145.054568, 30153.377448, 30161.700571, 30170.023937, - 30178.347545, 30186.671397, 30194.995490, 30203.319827, 30211.644406, 30219.969227, 30228.294290, 30236.619597, - 30244.945145, 30253.270935, 30261.596968, 30269.923243, 30278.249760, 30286.576518, 30294.903519, 30303.230762, - 30311.558246, 30319.885972, 30328.213940, 30336.542150, 30344.870601, 30353.199293, 30361.528227, 30369.857403, - 30378.186820, 30386.516478, 30394.846377, 30403.176517, 30411.506899, 30419.837522, 30428.168385, 30436.499490, - 30444.830835, 30453.162422, 30461.494249, 30469.826316, 30478.158625, 30486.491174, 30494.823963, 30503.156993, - 30511.490263, 30519.823774, 30528.157525, 30536.491516, 30544.825748, 30553.160219, 30561.494931, 30569.829882, - 30578.165074, 30586.500506, 30594.836177, 30603.172088, 30611.508239, 30619.844629, 30628.181259, 30636.518129, - 30644.855238, 30653.192587, 30661.530175, 30669.868002, 30678.206068, 30686.544374, 30694.882919, 30703.221703, - 30711.560726, 30719.899988, 30728.239489, 30736.579229, 30744.919207, 30753.259425, 30761.599881, 30769.940575, - 30778.281508, 30786.622680, 30794.964090, 30803.305739, 30811.647626, 30819.989751, 30828.332115, 30836.674716, - 30845.017556, 30853.360634, 30861.703950, 30870.047504, 30878.391296, 30886.735325, 30895.079592, 30903.424098, - 30911.768840, 30920.113821, 30928.459039, 30936.804494, 30945.150187, 30953.496117, 30961.842285, 30970.188690, - 30978.535332, 30986.882211, 30995.229327, 31003.576681, 31011.924271, 31020.272098, 31028.620163, 31036.968464, - 31045.317002, 31053.665776, 31062.014787, 31070.364035, 31078.713519, 31087.063240, 31095.413198, 31103.763391, - 31112.113821, 31120.464487, 31128.815390, 31137.166529, 31145.517903, 31153.869514, 31162.221361, 31170.573443, - 31178.925762, 31187.278316, 31195.631106, 31203.984132, 31212.337394, 31220.690891, 31229.044624, 31237.398592, - 31245.752795, 31254.107234, 31262.461908, 31270.816818, 31279.171963, 31287.527343, 31295.882958, 31304.238808, - 31312.594893, 31320.951213, 31329.307767, 31337.664557, 31346.021582, 31354.378841, 31362.736335, 31371.094063, - 31379.452026, 31387.810223, 31396.168655, 31404.527322, 31412.886222, 31421.245357, 31429.604726, 31437.964329, - 31446.324167, 31454.684238, 31463.044544, 31471.405083, 31479.765856, 31488.126863, 31496.488104, 31504.849579, - 31513.211287, 31521.573229, 31529.935405, 31538.297814, 31546.660456, 31555.023332, 31563.386441, 31571.749784, - 31580.113359, 31588.477168, 31596.841210, 31605.205485, 31613.569993, 31621.934734, 31630.299708, 31638.664915, - 31647.030355, 31655.396027, 31663.761932, 31672.128070, 31680.494440, 31688.861043, 31697.227878, 31705.594946, - 31713.962246, 31722.329779, 31730.697543, 31739.065540, 31747.433769, 31755.802230, 31764.170924, 31772.539849, - 31780.909006, 31789.278395, 31797.648016, 31806.017868, 31814.387953, 31822.758269, 31831.128816, 31839.499595, - 31847.870606, 31856.241848, 31864.613322, 31872.985027, 31881.356963, 31889.729130, 31898.101529, 31906.474159, - 31914.847019, 31923.220111, 31931.593434, 31939.966988, 31948.340772, 31956.714788, 31965.089034, 31973.463511, - 31981.838218, 31990.213157, 31998.588325, 32006.963725, 32015.339354, 32023.715214, 32032.091305, 32040.467625, - 32048.844176, 32057.220957, 32065.597968, 32073.975209, 32082.352681, 32090.730382, 32099.108313, 32107.486474, - 32115.864865, 32124.243485, 32132.622336, 32141.001415, 32149.380725, 32157.760264, 32166.140032, 32174.520030, - 32182.900258, 32191.280714, 32199.661400, 32208.042316, 32216.423460, 32224.804833, 32233.186436, 32241.568267, - 32249.950328, 32258.332617, 32266.715136, 32275.097883, 32283.480859, 32291.864063, 32300.247496, 32308.631158, - 32317.015049, 32325.399167, 32333.783515, 32342.168090, 32350.552894, 32358.937927, 32367.323187, 32375.708676, - 32384.094393, 32392.480338, 32400.866510, 32409.252911, 32417.639540, 32426.026397, 32434.413481, 32442.800794, - 32451.188334, 32459.576101, 32467.964097, 32476.352319, 32484.740770, 32493.129447, 32501.518353, 32509.907485, - 32518.296845, 32526.686432, 32535.076246, 32543.466288, 32551.856556, 32560.247052, 32568.637774, 32577.028724, - 32585.419900, 32593.811303, 32602.202933, 32610.594790, 32618.986873, 32627.379183, 32635.771720, 32644.164483, - 32652.557473, 32660.950689, 32669.344131, 32677.737800, 32686.131695, 32694.525816, 32702.920163, 32711.314737, - 32719.709536, 32728.104562, 32736.499813, 32744.895291, 32753.290994, 32761.686923, 32770.083078, 32778.479459, - 32786.876065, 32795.272897, 32803.669954, 32812.067237, 32820.464745, 32828.862479, 32837.260438, 32845.658623, - 32854.057032, 32862.455667, 32870.854527, 32879.253612, 32887.652922, 32896.052457, 32904.452218, 32912.852203, - 32921.252412, 32929.652847, 32938.053506, 32946.454390, 32954.855499, 32963.256832, 32971.658390, 32980.060173, - 32988.462179, 32996.864411, 33005.266866, 33013.669546, 33022.072450, 33030.475578, 33038.878931, 33047.282507, - 33055.686308, 33064.090332, 33072.494581, 33080.899053, 33089.303749, 33097.708669, 33106.113813, 33114.519180, - 33122.924771, 33131.330586, 33139.736624, 33148.142885, 33156.549370, 33164.956079, 33173.363011, 33181.770166, - 33190.177544, 33198.585146, 33206.992970, 33215.401018, 33223.809289, 33232.217783, 33240.626499, 33249.035439, - 33257.444601, 33265.853987, 33274.263595, 33282.673425, 33291.083479, 33299.493754, 33307.904253, 33316.314974, - 33324.725917, 33333.137083, 33341.548471, 33349.960082, 33358.371914, 33366.783969, 33375.196246, 33383.608745, - 33392.021466, 33400.434410, 33408.847575, 33417.260962, 33425.674571, 33434.088401, 33442.502454, 33450.916728, - 33459.331224, 33467.745941, 33476.160880, 33484.576041, 33492.991422, 33501.407026, 33509.822850, 33518.238897, - 33526.655164, 33535.071652, 33543.488362, 33551.905293, 33560.322445, 33568.739817, 33577.157411, 33585.575226, - 33593.993262, 33602.411518, 33610.829995, 33619.248693, 33627.667612, 33636.086751, 33644.506111, 33652.925691, - 33661.345492, 33669.765513, 33678.185755, 33686.606217, 33695.026899, 33703.447802, 33711.868925, 33720.290267, - 33728.711830, 33737.133613, 33745.555616, 33753.977839, 33762.400282, 33770.822945, 33779.245827, 33787.668930, - 33796.092252, 33804.515793, 33812.939555, 33821.363535, 33829.787736, 33838.212156, 33846.636795, 33855.061653, - 33863.486731, 33871.912028, 33880.337545, 33888.763280, 33897.189235, 33905.615409, 33914.041802, 33922.468414, - 33930.895244, 33939.322294, 33947.749562, 33956.177050, 33964.604756, 33973.032680, 33981.460824, 33989.889186, - 33998.317766, 34006.746565, 34015.175583, 34023.604819, 34032.034273, 34040.463946, 34048.893836, 34057.323946, - 34065.754273, 34074.184818, 34082.615582, 34091.046563, 34099.477763, 34107.909180, 34116.340815, 34124.772669, - 34133.204739, 34141.637028, 34150.069535, 34158.502259, 34166.935200, 34175.368359, 34183.801736, 34192.235330, - 34200.669142, 34209.103171, 34217.537417, 34225.971881, 34234.406561, 34242.841459, 34251.276574, 34259.711907, - 34268.147456, 34276.583222, 34285.019205, 34293.455405, 34301.891822, 34310.328456, 34318.765306, 34327.202373, - 34335.639657, 34344.077158, 34352.514874, 34360.952808, 34369.390958, 34377.829324, 34386.267907, 34394.706706, - 34403.145722, 34411.584953, 34420.024401, 34428.464065, 34436.903945, 34445.344041, 34453.784354, 34462.224882, - 34470.665626, 34479.106586, 34487.547761, 34495.989153, 34504.430760, 34512.872583, 34521.314621, 34529.756875, - 34538.199345, 34546.642030, 34555.084931, 34563.528047, 34571.971378, 34580.414925, 34588.858687, 34597.302664, - 34605.746856, 34614.191264, 34622.635886, 34631.080724, 34639.525776, 34647.971044, 34656.416526, 34664.862223, - 34673.308135, 34681.754262, 34690.200603, 34698.647159, 34707.093930, 34715.540915, 34723.988115, 34732.435530, - 34740.883158, 34749.331001, 34757.779059, 34766.227331, 34774.675817, 34783.124517, 34791.573431, 34800.022560, - 34808.471902, 34816.921459, 34825.371229, 34833.821214, 34842.271412, 34850.721824, 34859.172450, 34867.623290, - 34876.074343, 34884.525610, 34892.977091, 34901.428785, 34909.880693, 34918.332814, 34926.785149, 34935.237697, - 34943.690458, 34952.143433, 34960.596620, 34969.050021, 34977.503636, 34985.957463, 34994.411503, 35002.865757, - 35011.320223, 35019.774902, 35028.229795, 35036.684900, 35045.140217, 35053.595748, 35062.051491, 35070.507447, - 35078.963615, 35087.419997, 35095.876590, 35104.333396, 35112.790415, 35121.247645, 35129.705089, 35138.162744, - 35146.620612, 35155.078692, 35163.536984, 35171.995488, 35180.454204, 35188.913133, 35197.372273, 35205.831625, - 35214.291189, 35222.750965, 35231.210953, 35239.671152, 35248.131563, 35256.592186, 35265.053021, 35273.514067, - 35281.975324, 35290.436793, 35298.898474, 35307.360366, 35315.822469, 35324.284783, 35332.747309, 35341.210046, - 35349.672994, 35358.136154, 35366.599524, 35375.063106, 35383.526898, 35391.990901, 35400.455116, 35408.919541, - 35417.384177, 35425.849023, 35434.314081, 35442.779349, 35451.244828, 35459.710517, 35468.176417, 35476.642527, - 35485.108848, 35493.575379, 35502.042121, 35510.509073, 35518.976235, 35527.443608, 35535.911191, 35544.378983, - 35552.846986, 35561.315199, 35569.783622, 35578.252255, 35586.721098, 35595.190151, 35603.659414, 35612.128886, - 35620.598568, 35629.068460, 35637.538562, 35646.008873, 35654.479394, 35662.950124, 35671.421064, 35679.892213, - 35688.363572, 35696.835140, 35705.306917, 35713.778904, 35722.251100, 35730.723505, 35739.196119, 35747.668942, - 35756.141974, 35764.615216, 35773.088666, 35781.562325, 35790.036193, 35798.510270, 35806.984556, 35815.459050, - 35823.933753, 35832.408665, 35840.883786, 35849.359115, 35857.834652, 35866.310398, 35874.786353, 35883.262515, - 35891.738887, 35900.215466, 35908.692254, 35917.169250, 35925.646454, 35934.123866, 35942.601487, 35951.079315, - 35959.557352, 35968.035596, 35976.514049, 35984.992709, 35993.471577, 36001.950653, 36010.429936, 36018.909428, - 36027.389127, 36035.869033, 36044.349147, 36052.829469, 36061.309998, 36069.790735, 36078.271679, 36086.752831, - 36095.234189, 36103.715755, 36112.197529, 36120.679509, 36129.161697, 36137.644091, 36146.126693, 36154.609502, - 36163.092517, 36171.575740, 36180.059170, 36188.542806, 36197.026649, 36205.510699, 36213.994956, 36222.479419, - 36230.964089, 36239.448966, 36247.934049, 36256.419339, 36264.904835, 36273.390537, 36281.876446, 36290.362561, - 36298.848883, 36307.335411, 36315.822145, 36324.309085, 36332.796231, 36341.283584, 36349.771142, 36358.258906, - 36366.746877, 36375.235053, 36383.723435, 36392.212023, 36400.700817, 36409.189816, 36417.679021, 36426.168432, - 36434.658048, 36443.147870, 36451.637898, 36460.128131, 36468.618569, 36477.109213, 36485.600063, 36494.091117, - 36502.582377, 36511.073842, 36519.565512, 36528.057388, 36536.549468, 36545.041754, 36553.534244, 36562.026940, - 36570.519840, 36579.012946, 36587.506256, 36595.999771, 36604.493491, 36612.987415, 36621.481545, 36629.975878, - 36638.470417, 36646.965160, 36655.460108, 36663.955260, 36672.450616, 36680.946177, 36689.441942, 36697.937912, - 36706.434086, 36714.930464, 36723.427046, 36731.923832, 36740.420823, 36748.918017, 36757.415416, 36765.913019, - 36774.410825, 36782.908835, 36791.407050, 36799.905468, 36808.404089, 36816.902915, 36825.401944, 36833.901177, - 36842.400614, 36850.900254, 36859.400097, 36867.900144, 36876.400395, 36884.900848, 36893.401506, 36901.902366, - 36910.403430, 36918.904697, 36927.406167, 36935.907841, 36944.409717, 36952.911797, 36961.414079, 36969.916565, - 36978.419253, 36986.922145, 36995.425239, 37003.928536, 37012.432036, 37020.935739, 37029.439644, 37037.943752, - 37046.448062, 37054.952576, 37063.457291, 37071.962209, 37080.467330, 37088.972653, 37097.478178, 37105.983906, - 37114.489836, 37122.995968, 37131.502303, 37140.008839, 37148.515578, 37157.022519, 37165.529662, 37174.037007, - 37182.544554, 37191.052302, 37199.560253, 37208.068405, 37216.576760, 37225.085316, 37233.594073, 37242.103033, - 37250.612194, 37259.121556, 37267.631120, 37276.140886, 37284.650853, 37293.161022, 37301.671392, 37310.181963, - 37318.692736, 37327.203710, 37335.714885, 37344.226261, 37352.737838, 37361.249617, 37369.761597, 37378.273777, - 37386.786159, 37395.298742, 37403.811525, 37412.324509, 37420.837695, 37429.351080, 37437.864667, 37446.378455, - 37454.892443, 37463.406631, 37471.921021, 37480.435610, 37488.950401, 37497.465391, 37505.980583, 37514.495974, - 37523.011566, 37531.527358, 37540.043351, 37548.559544, 37557.075936, 37565.592529, 37574.109323, 37582.626316, - 37591.143509, 37599.660902, 37608.178495, 37616.696288, 37625.214281, 37633.732474, 37642.250866, 37650.769458, - 37659.288250, 37667.807242, 37676.326433, 37684.845824, 37693.365414, 37701.885204, 37710.405193, 37718.925382, - 37727.445770, 37735.966357, 37744.487144, 37753.008130, 37761.529315, 37770.050700, 37778.572283, 37787.094066, - 37795.616048, 37804.138228, 37812.660608, 37821.183187, 37829.705964, 37838.228941, 37846.752116, 37855.275490, - 37863.799063, 37872.322834, 37880.846805, 37889.370973, 37897.895341, 37906.419907, 37914.944671, 37923.469634, - 37931.994796, 37940.520155, 37949.045713, 37957.571470, 37966.097424, 37974.623577, 37983.149929, 37991.676478, - 38000.203225, 38008.730171, 38017.257314, 38025.784656, 38034.312195, 38042.839933, 38051.367868, 38059.896001, - 38068.424332, 38076.952861, 38085.481587, 38094.010511, 38102.539633, 38111.068952, 38119.598469, 38128.128184, - 38136.658096, 38145.188205, 38153.718512, 38162.249016, 38170.779718, 38179.310617, 38187.841713, 38196.373006, - 38204.904497, 38213.436184, 38221.968069, 38230.500151, 38239.032430, 38247.564905, 38256.097578, 38264.630448, - 38273.163514, 38281.696778, 38290.230238, 38298.763895, 38307.297748, 38315.831799, 38324.366046, 38332.900489, - 38341.435129, 38349.969966, 38358.504999, 38367.040229, 38375.575655, 38384.111277, 38392.647096, 38401.183110, - 38409.719322, 38418.255729, 38426.792333, 38435.329132, 38443.866128, 38452.403320, 38460.940708, 38469.478292, - 38478.016072, 38486.554047, 38495.092219, 38503.630586, 38512.169150, 38520.707909, 38529.246863, 38537.786014, - 38546.325360, 38554.864901, 38563.404638, 38571.944571, 38580.484699, 38589.025023, 38597.565542, 38606.106256, - 38614.647166, 38623.188271, 38631.729571, 38640.271067, 38648.812757, 38657.354643, 38665.896724, 38674.439000, - 38682.981471, 38691.524137, 38700.066998, 38708.610054, 38717.153305, 38725.696750, 38734.240391, 38742.784226, - 38751.328256, 38759.872480, 38768.416899, 38776.961513, 38785.506321, 38794.051324, 38802.596522, 38811.141913, - 38819.687500, 38828.233280, 38836.779255, 38845.325425, 38853.871788, 38862.418346, 38870.965098, 38879.512044, - 38888.059184, 38896.606519, 38905.154047, 38913.701770, 38922.249686, 38930.797796, 38939.346100, 38947.894598, - 38956.443290, 38964.992176, 38973.541255, 38982.090528, 38990.639995, 38999.189656, 39007.739510, 39016.289557, - 39024.839798, 39033.390233, 39041.940861, 39050.491682, 39059.042697, 39067.593905, 39076.145306, 39084.696901, - 39093.248689, 39101.800670, 39110.352844, 39118.905211, 39127.457771, 39136.010525, 39144.563471, 39153.116610, - 39161.669943, 39170.223468, 39178.777186, 39187.331097, 39195.885200, 39204.439496, 39212.993985, 39221.548667, - 39230.103541, 39238.658608, 39247.213867, 39255.769319, 39264.324964, 39272.880801, 39281.436830, 39289.993051, - 39298.549465, 39307.106071, 39315.662870, 39324.219861, 39332.777043, 39341.334418, 39349.891985, 39358.449745, - 39367.007696, 39375.565839, 39384.124174, 39392.682701, 39401.241420, 39409.800331, 39418.359434, 39426.918728, - 39435.478214, 39444.037892, 39452.597761, 39461.157822, 39469.718075, 39478.278519, 39486.839155, 39495.399982, - 39503.961001, 39512.522211, 39521.083612, 39529.645205, 39538.206989, 39546.768965, 39555.331131, 39563.893489, - 39572.456038, 39581.018778, 39589.581709, 39598.144831, 39606.708144, 39615.271648, 39623.835343, 39632.399229, - 39640.963306, 39649.527574, 39658.092032, 39666.656681, 39675.221521, 39683.786551, 39692.351773, 39700.917184, - 39709.482787, 39718.048580, 39726.614563, 39735.180737, 39743.747101, 39752.313656, 39760.880401, 39769.447336, - 39778.014461, 39786.581777, 39795.149283, 39803.716979, 39812.284866, 39820.852942, 39829.421209, 39837.989665, - 39846.558311, 39855.127148, 39863.696174, 39872.265390, 39880.834797, 39889.404392, 39897.974178, 39906.544153, - 39915.114319, 39923.684673, 39932.255218, 39940.825952, 39949.396875, 39957.967988, 39966.539291, 39975.110783, - 39983.682464, 39992.254335, 40000.826395, 40009.398644, 40017.971083, 40026.543711, 40035.116528, 40043.689534, - 40052.262730, 40060.836114, 40069.409688, 40077.983450, 40086.557402, 40095.131542, 40103.705871, 40112.280390, - 40120.855097, 40129.429993, 40138.005077, 40146.580351, 40155.155813, 40163.731464, 40172.307303, 40180.883331, - 40189.459548, 40198.035953, 40206.612546, 40215.189328, 40223.766298, 40232.343457, 40240.920804, 40249.498340, - 40258.076063, 40266.653975, 40275.232076, 40283.810364, 40292.388840, 40300.967505, 40309.546357, 40318.125398, - 40326.704627, 40335.284043, 40343.863648, 40352.443440, 40361.023420, 40369.603588, 40378.183944, 40386.764487, - 40395.345218, 40403.926137, 40412.507244, 40421.088538, 40429.670020, 40438.251689, 40446.833546, 40455.415590, - 40463.997821, 40472.580240, 40481.162847, 40489.745640, 40498.328621, 40506.911789, 40515.495145, 40524.078687, - 40532.662417, 40541.246334, 40549.830438, 40558.414729, 40566.999207, 40575.583872, 40584.168723, 40592.753762, - 40601.338988, 40609.924400, 40618.509999, 40627.095785, 40635.681758, 40644.267918, 40652.854264, 40661.440796, - 40670.027515, 40678.614421, 40687.201514, 40695.788792, 40704.376258, 40712.963909, 40721.551747, 40730.139772, - 40738.727982, 40747.316379, 40755.904963, 40764.493732, 40773.082687, 40781.671829, 40790.261157, 40798.850671, - 40807.440371, 40816.030257, 40824.620328, 40833.210586, 40841.801030, 40850.391659, 40858.982475, 40867.573476, - 40876.164663, 40884.756035, 40893.347594, 40901.939337, 40910.531267, 40919.123382, 40927.715683, 40936.308169, - 40944.900841, 40953.493698, 40962.086740, 40970.679968, 40979.273381, 40987.866980, 40996.460764, 41005.054733, - 41013.648887, 41022.243226, 41030.837751, 41039.432460, 41048.027355, 41056.622435, 41065.217700, 41073.813149, - 41082.408784, 41091.004603, 41099.600608, 41108.196797, 41116.793171, 41125.389730, 41133.986473, 41142.583401, - 41151.180514, 41159.777812, 41168.375294, 41176.972960, 41185.570811, 41194.168847, 41202.767067, 41211.365471, - 41219.964060, 41228.562833, 41237.161791, 41245.760933, 41254.360259, 41262.959769, 41271.559463, 41280.159342, - 41288.759405, 41297.359651, 41305.960082, 41314.560697, 41323.161496, 41331.762478, 41340.363645, 41348.964995, - 41357.566530, 41366.168248, 41374.770150, 41383.372236, 41391.974505, 41400.576958, 41409.179595, 41417.782415, - 41426.385419, 41434.988606, 41443.591977, 41452.195531, 41460.799269, 41469.403190, 41478.007295, 41486.611583, - 41495.216054, 41503.820708, 41512.425546, 41521.030567, 41529.635771, 41538.241158, 41546.846729, 41555.452482, - 41564.058418, 41572.664538, 41581.270840, 41589.877325, 41598.483994, 41607.090845, 41615.697879, 41624.305095, - 41632.912495, 41641.520077, 41650.127842, 41658.735789, 41667.343920, 41675.952232, 41684.560728, 41693.169406, - 41701.778266, 41710.387309, 41718.996534, 41727.605942, 41736.215532, 41744.825304, 41753.435259, 41762.045396, - 41770.655715, 41779.266216, 41787.876900, 41796.487766, 41805.098813, 41813.710043, 41822.321455, 41830.933049, - 41839.544825, 41848.156783, 41856.768922, 41865.381244, 41873.993747, 41882.606432, 41891.219299, 41899.832348, - 41908.445578, 41917.058990, 41925.672584, 41934.286359, 41942.900316, 41951.514455, 41960.128774, 41968.743276, - 41977.357959, 41985.972823, 41994.587868, 42003.203095, 42011.818504, 42020.434093, 42029.049864, 42037.665816, - 42046.281949, 42054.898263, 42063.514759, 42072.131435, 42080.748293, 42089.365331, 42097.982551, 42106.599951, - 42115.217532, 42123.835295, 42132.453238, 42141.071362, 42149.689666, 42158.308152, 42166.926818, 42175.545665, - 42184.164692, 42192.783900, 42201.403289, 42210.022858, 42218.642608, 42227.262539, 42235.882649, 42244.502940, - 42253.123412, 42261.744064, 42270.364896, 42278.985909, 42287.607101, 42296.228474, 42304.850028, 42313.471761, - 42322.093674, 42330.715768, 42339.338042, 42347.960495, 42356.583129, 42365.205943, 42373.828936, 42382.452110, - 42391.075463, 42399.698997, 42408.322710, 42416.946602, 42425.570675, 42434.194927, 42442.819359, 42451.443971, - 42460.068762, 42468.693733, 42477.318883, 42485.944213, 42494.569722, 42503.195411, 42511.821279, 42520.447327, - 42529.073554, 42537.699960, 42546.326546, 42554.953310, 42563.580254, 42572.207378, 42580.834680, 42589.462162, - 42598.089822, 42606.717662, 42615.345681, 42623.973879, 42632.602255, 42641.230811, 42649.859545, 42658.488459, - 42667.117551, 42675.746822, 42684.376272, 42693.005901, 42701.635708, 42710.265694, 42718.895859, 42727.526202, - 42736.156724, 42744.787424, 42753.418303, 42762.049361, 42770.680597, 42779.312011, 42787.943604, 42796.575375, - 42805.207324, 42813.839452, 42822.471758, 42831.104242, 42839.736905, 42848.369745, 42857.002764, 42865.635961, - 42874.269336, 42882.902889, 42891.536620, 42900.170529, 42908.804616, 42917.438881, 42926.073323, 42934.707944, - 42943.342743, 42951.977719, 42960.612873, 42969.248204, 42977.883714, 42986.519401, 42995.155266, 43003.791308, - 43012.427528, 43021.063925, 43029.700500, 43038.337253, 43046.974183, 43055.611290, 43064.248575, 43072.886037, - 43081.523676, 43090.161493, 43098.799486, 43107.437658, 43116.076006, 43124.714531, 43133.353234, 43141.992114, - 43150.631170, 43159.270404, 43167.909815, 43176.549403, 43185.189168, 43193.829109, 43202.469228, 43211.109523, - 43219.749995, 43228.390644, 43237.031470, 43245.672473, 43254.313652, 43262.955008, 43271.596540, 43280.238249, - 43288.880135, 43297.522197, 43306.164436, 43314.806851, 43323.449442, 43332.092210, 43340.735155, 43349.378276, - 43358.021573, 43366.665046, 43375.308696, 43383.952521, 43392.596524, 43401.240702, 43409.885056, 43418.529586, - 43427.174293, 43435.819176, 43444.464234, 43453.109469, 43461.754879, 43470.400466, 43479.046228, 43487.692166, - 43496.338280, 43504.984570, 43513.631035, 43522.277677, 43530.924493, 43539.571486, 43548.218654, 43556.865998, - 43565.513518, 43574.161213, 43582.809083, 43591.457129, 43600.105351, 43608.753748, 43617.402320, 43626.051067, - 43634.699990, 43643.349089, 43651.998362, 43660.647811, 43669.297435, 43677.947234, 43686.597208, 43695.247358, - 43703.897682, 43712.548182, 43721.198856, 43729.849706, 43738.500731, 43747.151930, 43755.803304, 43764.454854, - 43773.106578, 43781.758477, 43790.410550, 43799.062799, 43807.715222, 43816.367820, 43825.020592, 43833.673539, - 43842.326661, 43850.979957, 43859.633428, 43868.287073, 43876.940893, 43885.594887, 43894.249056, 43902.903399, - 43911.557917, 43920.212608, 43928.867474, 43937.522514, 43946.177729, 43954.833118, 43963.488681, 43972.144418, - 43980.800329, 43989.456414, 43998.112673, 44006.769106, 44015.425714, 44024.082495, 44032.739450, 44041.396579, - 44050.053882, 44058.711359, 44067.369009, 44076.026833, 44084.684831, 44093.343003, 44102.001349, 44110.659868, - 44119.318561, 44127.977427, 44136.636467, 44145.295680, 44153.955067, 44162.614628, 44171.274362, 44179.934269, - 44188.594350, 44197.254604, 44205.915031, 44214.575632, 44223.236406, 44231.897353, 44240.558473, 44249.219767, - 44257.881233, 44266.542873, 44275.204686, 44283.866672, 44292.528831, 44301.191163, 44309.853668, 44318.516346, - 44327.179196, 44335.842220, 44344.505416, 44353.168786, 44361.832328, 44370.496043, 44379.159930, 44387.823991, - 44396.488223, 44405.152629, 44413.817207, 44422.481958, 44431.146881, 44439.811977, 44448.477245, 44457.142686, - 44465.808299, 44474.474085, 44483.140043, 44491.806173, 44500.472476, 44509.138951, 44517.805598, 44526.472417, - 44535.139409, 44543.806573, 44552.473908, 44561.141416, 44569.809096, 44578.476948, 44587.144973, 44595.813169, - 44604.481537, 44613.150077, 44621.818788, 44630.487672, 44639.156728, 44647.825955, 44656.495354, 44665.164925, - 44673.834668, 44682.504582, 44691.174668, 44699.844925, 44708.515355, 44717.185955, 44725.856728, 44734.527671, - 44743.198787, 44751.870073, 44760.541531, 44769.213161, 44777.884962, 44786.556934, 44795.229078, 44803.901393, - 44812.573879, 44821.246536, 44829.919364, 44838.592364, 44847.265535, 44855.938877, 44864.612390, 44873.286074, - 44881.959929, 44890.633955, 44899.308152, 44907.982519, 44916.657058, 44925.331768, 44934.006648, 44942.681700, - 44951.356922, 44960.032314, 44968.707878, 44977.383612, 44986.059517, 44994.735593, 45003.411839, 45012.088255, - 45020.764843, 45029.441600, 45038.118529, 45046.795627, 45055.472896, 45064.150336, 45072.827946, 45081.505726, - 45090.183677, 45098.861798, 45107.540089, 45116.218550, 45124.897182, 45133.575983, 45142.254955, 45150.934097, - 45159.613409, 45168.292891, 45176.972543, 45185.652366, 45194.332358, 45203.012520, 45211.692852, 45220.373353, - 45229.054025, 45237.734866, 45246.415878, 45255.097059, 45263.778410, 45272.459930, 45281.141620, 45289.823480, - 45298.505509, 45307.187709, 45315.870077, 45324.552615, 45333.235323, 45341.918200, 45350.601247, 45359.284462, - 45367.967848, 45376.651403, 45385.335127, 45394.019020, 45402.703083, 45411.387315, 45420.071716, 45428.756286, - 45437.441025, 45446.125934, 45454.811012, 45463.496258, 45472.181674, 45480.867259, 45489.553013, 45498.238936, - 45506.925028, 45515.611288, 45524.297718, 45532.984316, 45541.671083, 45550.358019, 45559.045124, 45567.732397, - 45576.419840, 45585.107450, 45593.795230, 45602.483178, 45611.171295, 45619.859580, 45628.548034, 45637.236656, - 45645.925447, 45654.614406, 45663.303534, 45671.992830, 45680.682294, 45689.371927, 45698.061728, 45706.751697, - 45715.441835, 45724.132141, 45732.822615, 45741.513257, 45750.204067, 45758.895046, 45767.586192, 45776.277507, - 45784.968989, 45793.660640, 45802.352458, 45811.044445, 45819.736599, 45828.428921, 45837.121412, 45845.814070, - 45854.506895, 45863.199889, 45871.893050, 45880.586379, 45889.279876, 45897.973540, 45906.667372, 45915.361372, - 45924.055539, 45932.749874, 45941.444376, 45950.139045, 45958.833883, 45967.528887, 45976.224059, 45984.919399, - 45993.614905, 46002.310579, 46011.006421, 46019.702429, 46028.398605, 46037.094948, 46045.791458, 46054.488136, - 46063.184980, 46071.881992, 46080.579171, 46089.276516, 46097.974029, 46106.671709, 46115.369556, 46124.067569, - 46132.765750, 46141.464097, 46150.162611, 46158.861292, 46167.560140, 46176.259155, 46184.958336, 46193.657684, - 46202.357199, 46211.056880, 46219.756728, 46228.456743, 46237.156924, 46245.857272, 46254.557786, 46263.258467, - 46271.959314, 46280.660328, 46289.361508, 46298.062854, 46306.764367, 46315.466046, 46324.167891, 46332.869903, - 46341.572081, 46350.274425, 46358.976935, 46367.679612, 46376.382454, 46385.085463, 46393.788638, 46402.491978, - 46411.195485, 46419.899158, 46428.602997, 46437.307001, 46446.011172, 46454.715508, 46463.420011, 46472.124679, - 46480.829513, 46489.534512, 46498.239678, 46506.945009, 46515.650506, 46524.356168, 46533.061996, 46541.767990, - 46550.474149, 46559.180474, 46567.886964, 46576.593620, 46585.300442, 46594.007428, 46602.714581, 46611.421898, - 46620.129381, 46628.837029, 46637.544843, 46646.252822, 46654.960966, 46663.669275, 46672.377749, 46681.086389, - 46689.795194, 46698.504164, 46707.213299, 46715.922599, 46724.632064, 46733.341694, 46742.051489, 46750.761449, - 46759.471574, 46768.181864, 46776.892319, 46785.602938, 46794.313722, 46803.024672, 46811.735785, 46820.447064, - 46829.158507, 46837.870115, 46846.581888, 46855.293825, 46864.005927, 46872.718194, 46881.430625, 46890.143220, - 46898.855980, 46907.568904, 46916.281993, 46924.995247, 46933.708664, 46942.422246, 46951.135993, 46959.849903, - 46968.563978, 46977.278217, 46985.992621, 46994.707188, 47003.421920, 47012.136816, 47020.851876, 47029.567100, - 47038.282488, 47046.998040, 47055.713756, 47064.429636, 47073.145680, 47081.861888, 47090.578260, 47099.294796, - 47108.011495, 47116.728359, 47125.445386, 47134.162577, 47142.879932, 47151.597450, 47160.315132, 47169.032978, - 47177.750987, 47186.469160, 47195.187496, 47203.905996, 47212.624660, 47221.343487, 47230.062478, 47238.781632, - 47247.500949, 47256.220430, 47264.940074, 47273.659881, 47282.379852, 47291.099986, 47299.820283, 47308.540744, - 47317.261368, 47325.982154, 47334.703104, 47343.424218, 47352.145494, 47360.866933, 47369.588536, 47378.310301, - 47387.032229, 47395.754321, 47404.476575, 47413.198992, 47421.921572, 47430.644315, 47439.367220, 47448.090289, - 47456.813520, 47465.536914, 47474.260471, 47482.984190, 47491.708073, 47500.432117, 47509.156325, 47517.880695, - 47526.605227, 47535.329922, 47544.054780, 47552.779800, 47561.504982, 47570.230327, 47578.955835, 47587.681504, - 47596.407336, 47605.133331, 47613.859487, 47622.585806, 47631.312288, 47640.038931, 47648.765737, 47657.492704, - 47666.219834, 47674.947126, 47683.674580, 47692.402197, 47701.129975, 47709.857915, 47718.586017, 47727.314281, - 47736.042707, 47744.771295, 47753.500045, 47762.228957, 47770.958031, 47779.687266, 47788.416663, 47797.146222, - 47805.875943, 47814.605825, 47823.335869, 47832.066074, 47840.796442, 47849.526970, 47858.257661, 47866.988513, - 47875.719526, 47884.450701, 47893.182037, 47901.913535, 47910.645194, 47919.377015, 47928.108997, 47936.841140, - 47945.573445, 47954.305911, 47963.038538, 47971.771326, 47980.504275, 47989.237386, 47997.970658, 48006.704091, - 48015.437685, 48024.171440, 48032.905356, 48041.639434, 48050.373672, 48059.108071, 48067.842631, 48076.577352, - 48085.312234, 48094.047277, 48102.782480, 48111.517845, 48120.253370, 48128.989056, 48137.724902, 48146.460910, - 48155.197078, 48163.933407, 48172.669896, 48181.406546, 48190.143356, 48198.880328, 48207.617459, 48216.354751, - 48225.092204, 48233.829817, 48242.567590, 48251.305524, 48260.043618, 48268.781873, 48277.520288, 48286.258863, - 48294.997599, 48303.736494, 48312.475550, 48321.214766, 48329.954143, 48338.693679, 48347.433376, 48356.173232, - 48364.913249, 48373.653426, 48382.393762, 48391.134259, 48399.874916, 48408.615732, 48417.356709, 48426.097845, - 48434.839142, 48443.580598, 48452.322214, 48461.063989, 48469.805925, 48478.548020, 48487.290275, 48496.032689, - 48504.775264, 48513.517998, 48522.260891, 48531.003944, 48539.747157, 48548.490529, 48557.234060, 48565.977752, - 48574.721602, 48583.465612, 48592.209782, 48600.954110, 48609.698598, 48618.443246, 48627.188053, 48635.933019, - 48644.678144, 48653.423428, 48662.168872, 48670.914475, 48679.660237, 48688.406158, 48697.152238, 48705.898477, - 48714.644876, 48723.391433, 48732.138150, 48740.885025, 48749.632059, 48758.379252, 48767.126604, 48775.874115, - 48784.621785, 48793.369614, 48802.117601, 48810.865747, 48819.614052, 48828.362516, 48837.111138, 48845.859919, - 48854.608859, 48863.357957, 48872.107214, 48880.856629, 48889.606203, 48898.355936, 48907.105827, 48915.855876, - 48924.606084, 48933.356450, 48942.106975, 48950.857658, 48959.608499, 48968.359499, 48977.110657, 48985.861973, - 48994.613448, 49003.365080, 49012.116871, 49020.868820, 49029.620928, 49038.373193, 49047.125616, 49055.878198, - 49064.630937, 49073.383835, 49082.136890, 49090.890104, 49099.643475, 49108.397005, 49117.150692, 49125.904537, - 49134.658540, 49143.412701, 49152.167019, 49160.921495, 49169.676129, 49178.430921, 49187.185871, 49195.940978, - 49204.696243, 49213.451665, 49222.207245, 49230.962982, 49239.718877, 49248.474930, 49257.231140, 49265.987508, - 49274.744033, 49283.500715, 49292.257555, 49301.014552, 49309.771707, 49318.529019, 49327.286488, 49336.044114, - 49344.801898, 49353.559839, 49362.317937, 49371.076192, 49379.834604, 49388.593174, 49397.351900, 49406.110784, - 49414.869825, 49423.629023, 49432.388377, 49441.147889, 49449.907558, 49458.667383, 49467.427366, 49476.187505, - 49484.947801, 49493.708254, 49502.468864, 49511.229631, 49519.990554, 49528.751634, 49537.512871, 49546.274265, - 49555.035815, 49563.797522, 49572.559385, 49581.321405, 49590.083581, 49598.845915, 49607.608404, 49616.371050, - 49625.133853, 49633.896811, 49642.659927, 49651.423199, 49660.186627, 49668.950211, 49677.713952, 49686.477849, - 49695.241902, 49704.006112, 49712.770477, 49721.534999, 49730.299677, 49739.064511, 49747.829502, 49756.594648, - 49765.359951, 49774.125409, 49782.891024, 49791.656794, 49800.422721, 49809.188803, 49817.955042, 49826.721436, - 49835.487986, 49844.254692, 49853.021554, 49861.788572, 49870.555745, 49879.323074, 49888.090559, 49896.858200, - 49905.625996, 49914.393948, 49923.162055, 49931.930318, 49940.698737, 49949.467311, 49958.236041, 49967.004927, - 49975.773967, 49984.543164, 49993.312515, 50002.082022, 50010.851685, 50019.621503, 50028.391476, 50037.161605, - 50045.931888, 50054.702327, 50063.472922, 50072.243671, 50081.014576, 50089.785636, 50098.556851, 50107.328221, - 50116.099747, 50124.871427, 50133.643262, 50142.415253, 50151.187398, 50159.959699, 50168.732154, 50177.504764, - 50186.277529, 50195.050450, 50203.823525, 50212.596754, 50221.370139, 50230.143678, 50238.917372, 50247.691221, - 50256.465225, 50265.239383, 50274.013696, 50282.788164, 50291.562786, 50300.337563, 50309.112494, 50317.887580, - 50326.662821, 50335.438216, 50344.213765, 50352.989469, 50361.765327, 50370.541340, 50379.317507, 50388.093828, - 50396.870304, 50405.646934, 50414.423719, 50423.200657, 50431.977750, 50440.754997, 50449.532399, 50458.309954, - 50467.087664, 50475.865527, 50484.643545, 50493.421717, 50502.200043, 50510.978523, 50519.757157, 50528.535945, - 50537.314887, 50546.093983, 50554.873232, 50563.652636, 50572.432193, 50581.211905, 50589.991770, 50598.771789, - 50607.551961, 50616.332288, 50625.112768, 50633.893402, 50642.674189, 50651.455130, 50660.236225, 50669.017473, - 50677.798875, 50686.580431, 50695.362140, 50704.144002, 50712.926018, 50721.708187, 50730.490510, 50739.272987, - 50748.055616, 50756.838399, 50765.621336, 50774.404425, 50783.187668, 50791.971064, 50800.754614, 50809.538317, - 50818.322173, 50827.106182, 50835.890344, 50844.674659, 50853.459128, 50862.243749, 50871.028524, 50879.813451, - 50888.598532, 50897.383766, 50906.169152, 50914.954692, 50923.740384, 50932.526230, 50941.312228, 50950.098379, - 50958.884683, 50967.671139, 50976.457749, 50985.244511, 50994.031426, 51002.818494, 51011.605714, 51020.393087, - 51029.180613, 51037.968291, 51046.756122, 51055.544105, 51064.332241, 51073.120529, 51081.908970, 51090.697564, - 51099.486310, 51108.275208, 51117.064259, 51125.853462, 51134.642817, 51143.432325, 51152.221985, 51161.011798, - 51169.801762, 51178.591879, 51187.382148, 51196.172569, 51204.963143, 51213.753869, 51222.544746, 51231.335776, - 51240.126958, 51248.918292, 51257.709778, 51266.501416, 51275.293206, 51284.085148, 51292.877242, 51301.669488, - 51310.461886, 51319.254435, 51328.047137, 51336.839990, 51345.632995, 51354.426152, 51363.219461, 51372.012921, - 51380.806533, 51389.600297, 51398.394212, 51407.188279, 51415.982498, 51424.776868, 51433.571390, 51442.366064, - 51451.160889, 51459.955865, 51468.750993, 51477.546272, 51486.341703, 51495.137285, 51503.933019, 51512.728904, - 51521.524940, 51530.321128, 51539.117467, 51547.913957, 51556.710598, 51565.507391, 51574.304335, 51583.101430, - 51591.898676, 51600.696074, 51609.493622, 51618.291322, 51627.089172, 51635.887174, 51644.685327, 51653.483631, - 51662.282085, 51671.080691, 51679.879447, 51688.678355, 51697.477413, 51706.276623, 51715.075983, 51723.875494, - 51732.675155, 51741.474968, 51750.274931, 51759.075045, 51767.875310, 51776.675725, 51785.476291, 51794.277007, - 51803.077875, 51811.878893, 51820.680061, 51829.481380, 51838.282849, 51847.084469, 51855.886240, 51864.688161, - 51873.490232, 51882.292454, 51891.094826, 51899.897348, 51908.700021, 51917.502844, 51926.305818, 51935.108942, - 51943.912216, 51952.715640, 51961.519214, 51970.322939, 51979.126814, 51987.930838, 51996.735013, 52005.539339, - 52014.343814, 52023.148439, 52031.953214, 52040.758140, 52049.563215, 52058.368440, 52067.173815, 52075.979340, - 52084.785015, 52093.590840, 52102.396815, 52111.202939, 52120.009213, 52128.815637, 52137.622211, 52146.428935, - 52155.235808, 52164.042831, 52172.850004, 52181.657326, 52190.464798, 52199.272419, 52208.080190, 52216.888111, - 52225.696181, 52234.504401, 52243.312770, 52252.121289, 52260.929957, 52269.738774, 52278.547741, 52287.356857, - 52296.166123, 52304.975538, 52313.785102, 52322.594816, 52331.404678, 52340.214690, 52349.024852, 52357.835162, - 52366.645622, 52375.456231, 52384.266989, 52393.077896, 52401.888952, 52410.700157, 52419.511511, 52428.323014, - 52437.134667, 52445.946468, 52454.758418, 52463.570517, 52472.382765, 52481.195162, 52490.007708, 52498.820402, - 52507.633246, 52516.446238, 52525.259379, 52534.072669, 52542.886107, 52551.699695, 52560.513430, 52569.327315, - 52578.141348, 52586.955530, 52595.769860, 52604.584339, 52613.398967, 52622.213743, 52631.028668, 52639.843741, - 52648.658962, 52657.474332, 52666.289851, 52675.105518, 52683.921333, 52692.737296, 52701.553408, 52710.369668, - 52719.186077, 52728.002634, 52736.819339, 52745.636192, 52754.453193, 52763.270343, 52772.087641, 52780.905087, - 52789.722681, 52798.540423, 52807.358313, 52816.176351, 52824.994538, 52833.812872, 52842.631354, 52851.449984, - 52860.268763, 52869.087689, 52877.906763, 52886.725985, 52895.545354, 52904.364872, 52913.184537, 52922.004350, - 52930.824311, 52939.644420, 52948.464676, 52957.285080, 52966.105632, 52974.926331, 52983.747178, 52992.568173, - 53001.389315, 53010.210605, 53019.032042, 53027.853627, 53036.675360, 53045.497240, 53054.319267, 53063.141442, - 53071.963764, 53080.786233, 53089.608850, 53098.431615, 53107.254526, 53116.077585, 53124.900791, 53133.724145, - 53142.547646, 53151.371294, 53160.195089, 53169.019031, 53177.843121, 53186.667357, 53195.491741, 53204.316272, - 53213.140950, 53221.965775, 53230.790747, 53239.615866, 53248.441131, 53257.266544, 53266.092104, 53274.917811, - 53283.743665, 53292.569665, 53301.395813, 53310.222107, 53319.048548, 53327.875136, 53336.701870, 53345.528752, - 53354.355780, 53363.182955, 53372.010276, 53380.837744, 53389.665359, 53398.493120, 53407.321028, 53416.149083, - 53424.977284, 53433.805631, 53442.634126, 53451.462766, 53460.291553, 53469.120487, 53477.949567, 53486.778793, - 53495.608166, 53504.437685, 53513.267350, 53522.097162, 53530.927120, 53539.757224, 53548.587475, 53557.417872, - 53566.248415, 53575.079104, 53583.909939, 53592.740921, 53601.572049, 53610.403322, 53619.234742, 53628.066308, - 53636.898020, 53645.729878, 53654.561882, 53663.394032, 53672.226328, 53681.058769, 53689.891357, 53698.724091, - 53707.556970, 53716.389995, 53725.223167, 53734.056483, 53742.889946, 53751.723555, 53760.557309, 53769.391209, - 53778.225254, 53787.059446, 53795.893783, 53804.728265, 53813.562894, 53822.397667, 53831.232587, 53840.067652, - 53848.902862, 53857.738218, 53866.573720, 53875.409367, 53884.245159, 53893.081097, 53901.917180, 53910.753408, - 53919.589782, 53928.426302, 53937.262966, 53946.099776, 53954.936731, 53963.773832, 53972.611077, 53981.448468, - 53990.286004, 53999.123685, 54007.961512, 54016.799483, 54025.637600, 54034.475862, 54043.314268, 54052.152820, - 54060.991517, 54069.830359, 54078.669346, 54087.508477, 54096.347754, 54105.187176, 54114.026742, 54122.866453, - 54131.706310, 54140.546311, 54149.386457, 54158.226747, 54167.067183, 54175.907763, 54184.748488, 54193.589357, - 54202.430372, 54211.271531, 54220.112834, 54228.954283, 54237.795875, 54246.637613, 54255.479495, 54264.321521, - 54273.163692, 54282.006008, 54290.848468, 54299.691073, 54308.533821, 54317.376715, 54326.219753, 54335.062935, - 54343.906261, 54352.749732, 54361.593347, 54370.437106, 54379.281010, 54388.125058, 54396.969250, 54405.813586, - 54414.658067, 54423.502692, 54432.347460, 54441.192373, 54450.037430, 54458.882631, 54467.727977, 54476.573466, - 54485.419099, 54494.264876, 54503.110798, 54511.956863, 54520.803072, 54529.649425, 54538.495922, 54547.342563, - 54556.189347, 54565.036276, 54573.883348, 54582.730564, 54591.577924, 54600.425428, 54609.273075, 54618.120866, - 54626.968801, 54635.816879, 54644.665102, 54653.513467, 54662.361977, 54671.210629, 54680.059426, 54688.908366, - 54697.757449, 54706.606676, 54715.456047, 54724.305561, 54733.155218, 54742.005019, 54750.854963, 54759.705051, - 54768.555282, 54777.405656, 54786.256174, 54795.106835, 54803.957639, 54812.808586, 54821.659677, 54830.510911, - 54839.362288, 54848.213808, 54857.065472, 54865.917278, 54874.769228, 54883.621321, 54892.473557, 54901.325936, - 54910.178457, 54919.031122, 54927.883930, 54936.736881, 54945.589975, 54954.443212, 54963.296591, 54972.150114, - 54981.003779, 54989.857588, 54998.711539, 55007.565633, 55016.419869, 55025.274249, 55034.128771, 55042.983436, - 55051.838244, 55060.693194, 55069.548287, 55078.403523, 55087.258901, 55096.114422, 55104.970085, 55113.825891, - 55122.681840, 55131.537931, 55140.394164, 55149.250540, 55158.107059, 55166.963720, 55175.820523, 55184.677469, - 55193.534557, 55202.391787, 55211.249160, 55220.106675, 55228.964333, 55237.822133, 55246.680075, 55255.538159, - 55264.396385, 55273.254754, 55282.113265, 55290.971918, 55299.830713, 55308.689650, 55317.548729, 55326.407951, - 55335.267314, 55344.126820, 55352.986467, 55361.846257, 55370.706188, 55379.566261, 55388.426477, 55397.286834, - 55406.147333, 55415.007974, 55423.868757, 55432.729682, 55441.590749, 55450.451957, 55459.313307, 55468.174799, - 55477.036432, 55485.898208, 55494.760125, 55503.622183, 55512.484384, 55521.346726, 55530.209209, 55539.071834, - 55547.934601, 55556.797509, 55565.660559, 55574.523751, 55583.387083, 55592.250558, 55601.114174, 55609.977931, - 55618.841829, 55627.705869, 55636.570051, 55645.434373, 55654.298837, 55663.163443, 55672.028190, 55680.893077, - 55689.758107, 55698.623277, 55707.488589, 55716.354042, 55725.219636, 55734.085371, 55742.951247, 55751.817264, - 55760.683423, 55769.549722, 55778.416163, 55787.282745, 55796.149467, 55805.016331, 55813.883336, 55822.750481, - 55831.617768, 55840.485195, 55849.352764, 55858.220473, 55867.088323, 55875.956314, 55884.824445, 55893.692718, - 55902.561131, 55911.429685, 55920.298380, 55929.167216, 55938.036192, 55946.905309, 55955.774566, 55964.643964, - 55973.513503, 55982.383182, 55991.253002, 56000.122963, 56008.993064, 56017.863305, 56026.733688, 56035.604210, - 56044.474873, 56053.345677, 56062.216620, 56071.087705, 56079.958929, 56088.830294, 56097.701800, 56106.573445, - 56115.445231, 56124.317158, 56133.189224, 56142.061431, 56150.933778, 56159.806265, 56168.678892, 56177.551660, - 56186.424568, 56195.297615, 56204.170803, 56213.044131, 56221.917599, 56230.791207, 56239.664956, 56248.538844, - 56257.412872, 56266.287040, 56275.161348, 56284.035796, 56292.910384, 56301.785112, 56310.659979, 56319.534987, - 56328.410134, 56337.285421, 56346.160848, 56355.036415, 56363.912121, 56372.787967, 56381.663953, 56390.540079, - 56399.416344, 56408.292749, 56417.169294, 56426.045978, 56434.922801, 56443.799765, 56452.676868, 56461.554110, - 56470.431492, 56479.309014, 56488.186674, 56497.064475, 56505.942415, 56514.820494, 56523.698713, 56532.577071, - 56541.455568, 56550.334205, 56559.212981, 56568.091896, 56576.970951, 56585.850145, 56594.729478, 56603.608950, - 56612.488562, 56621.368313, 56630.248203, 56639.128232, 56648.008400, 56656.888708, 56665.769154, 56674.649740, - 56683.530464, 56692.411328, 56701.292330, 56710.173472, 56719.054753, 56727.936172, 56736.817731, 56745.699428, - 56754.581264, 56763.463239, 56772.345354, 56781.227606, 56790.109998, 56798.992529, 56807.875198, 56816.758006, - 56825.640953, 56834.524038, 56843.407263, 56852.290625, 56861.174127, 56870.057767, 56878.941546, 56887.825464, - 56896.709520, 56905.593714, 56914.478047, 56923.362519, 56932.247129, 56941.131878, 56950.016765, 56958.901791, - 56967.786955, 56976.672258, 56985.557699, 56994.443278, 57003.328995, 57012.214851, 57021.100846, 57029.986978, - 57038.873249, 57047.759658, 57056.646206, 57065.532892, 57074.419715, 57083.306677, 57092.193778, 57101.081016, - 57109.968392, 57118.855907, 57127.743560, 57136.631350, 57145.519279, 57154.407346, 57163.295551, 57172.183894, - 57181.072375, 57189.960994, 57198.849750, 57207.738645, 57216.627678, 57225.516848, 57234.406156, 57243.295602, - 57252.185186, 57261.074908, 57269.964768, 57278.854765, 57287.744900, 57296.635173, 57305.525584, 57314.416132, - 57323.306818, 57332.197641, 57341.088603, 57349.979702, 57358.870938, 57367.762312, 57376.653824, 57385.545473, - 57394.437259, 57403.329183, 57412.221245, 57421.113444, 57430.005781, 57438.898255, 57447.790866, 57456.683615, - 57465.576501, 57474.469524, 57483.362685, 57492.255983, 57501.149419, 57510.042992, 57518.936702, 57527.830549, - 57536.724533, 57545.618655, 57554.512914, 57563.407310, 57572.301843, 57581.196513, 57590.091320, 57598.986265, - 57607.881346, 57616.776565, 57625.671921, 57634.567413, 57643.463043, 57652.358809, 57661.254713, 57670.150754, - 57679.046931, 57687.943245, 57696.839696, 57705.736285, 57714.633009, 57723.529871, 57732.426870, 57741.324005, - 57750.221277, 57759.118686, 57768.016232, 57776.913914, 57785.811733, 57794.709689, 57803.607781, 57812.506010, - 57821.404376, 57830.302878, 57839.201517, 57848.100292, 57856.999204, 57865.898252, 57874.797437, 57883.696759, - 57892.596217, 57901.495811, 57910.395542, 57919.295409, 57928.195413, 57937.095553, 57945.995829, 57954.896242, - 57963.796791, 57972.697476, 57981.598298, 57990.499255, 57999.400350, 58008.301580, 58017.202946, 58026.104449, - 58035.006088, 58043.907863, 58052.809774, 58061.711822, 58070.614005, 58079.516325, 58088.418780, 58097.321372, - 58106.224100, 58115.126963, 58124.029963, 58132.933099, 58141.836370, 58150.739778, 58159.643321, 58168.547001, - 58177.450816, 58186.354767, 58195.258854, 58204.163076, 58213.067435, 58221.971929, 58230.876559, 58239.781325, - 58248.686227, 58257.591264, 58266.496437, 58275.401746, 58284.307190, 58293.212770, 58302.118486, 58311.024337, - 58319.930324, 58328.836446, 58337.742704, 58346.649097, 58355.555626, 58364.462291, 58373.369090, 58382.276026, - 58391.183097, 58400.090303, 58408.997644, 58417.905121, 58426.812734, 58435.720481, 58444.628364, 58453.536383, - 58462.444536, 58471.352825, 58480.261249, 58489.169809, 58498.078503, 58506.987333, 58515.896298, 58524.805398, - 58533.714633, 58542.624004, 58551.533509, 58560.443150, 58569.352926, 58578.262836, 58587.172882, 58596.083063, - 58604.993379, 58613.903829, 58622.814415, 58631.725136, 58640.635991, 58649.546982, 58658.458107, 58667.369368, - 58676.280763, 58685.192293, 58694.103957, 58703.015757, 58711.927691, 58720.839760, 58729.751964, 58738.664303, - 58747.576776, 58756.489384, 58765.402127, 58774.315004, 58783.228016, 58792.141162, 58801.054444, 58809.967859, - 58818.881410, 58827.795094, 58836.708914, 58845.622868, 58854.536956, 58863.451179, 58872.365536, 58881.280028, - 58890.194654, 58899.109414, 58908.024309, 58916.939339, 58925.854502, 58934.769800, 58943.685232, 58952.600799, - 58961.516500, 58970.432335, 58979.348304, 58988.264408, 58997.180645, 59006.097017, 59015.013523, 59023.930164, - 59032.846938, 59041.763846, 59050.680889, 59059.598066, 59068.515376, 59077.432821, 59086.350400, 59095.268113, - 59104.185959, 59113.103940, 59122.022055, 59130.940303, 59139.858686, 59148.777202, 59157.695852, 59166.614637, - 59175.533555, 59184.452606, 59193.371792, 59202.291111, 59211.210565, 59220.130151, 59229.049872, 59237.969726, - 59246.889715, 59255.809836, 59264.730092, 59273.650481, 59282.571003, 59291.491660, 59300.412450, 59309.333373, - 59318.254430, 59327.175621, 59336.096945, 59345.018402, 59353.939993, 59362.861718, 59371.783576, 59380.705567, - 59389.627692, 59398.549950, 59407.472342, 59416.394867, 59425.317525, 59434.240317, 59443.163242, 59452.086300, - 59461.009491, 59469.932816, 59478.856274, 59487.779865, 59496.703590, 59505.627447, 59514.551438, 59523.475562, - 59532.399819, 59541.324209, 59550.248732, 59559.173389, 59568.098178, 59577.023100, 59585.948156, 59594.873344, - 59603.798666, 59612.724120, 59621.649707, 59630.575428, 59639.501281, 59648.427267, 59657.353386, 59666.279638, - 59675.206023, 59684.132540, 59693.059190, 59701.985973, 59710.912889, 59719.839938, 59728.767119, 59737.694433, - 59746.621880, 59755.549460, 59764.477172, 59773.405017, 59782.332994, 59791.261104, 59800.189347, 59809.117722, - 59818.046230, 59826.974870, 59835.903643, 59844.832549, 59853.761587, 59862.690757, 59871.620060, 59880.549495, - 59889.479063, 59898.408763, 59907.338596, 59916.268560, 59925.198658, 59934.128887, 59943.059249, 59951.989743, - 59960.920370, 59969.851128, 59978.782019, 59987.713043, 59996.644198, 60005.575486, 60014.506906, 60023.438458, - 60032.370142, 60041.301958, 60050.233906, 60059.165987, 60068.098199, 60077.030544, 60085.963020, 60094.895629, - 60103.828370, 60112.761242, 60121.694247, 60130.627383, 60139.560652, 60148.494052, 60157.427585, 60166.361249, - 60175.295045, 60184.228973, 60193.163032, 60202.097224, 60211.031547, 60219.966002, 60228.900589, 60237.835308, - 60246.770158, 60255.705140, 60264.640254, 60273.575499, 60282.510876, 60291.446385, 60300.382025, 60309.317797, - 60318.253701, 60327.189736, 60336.125903, 60345.062201, 60353.998631, 60362.935192, 60371.871884, 60380.808709, - 60389.745664, 60398.682751, 60407.619970, 60416.557320, 60425.494801, 60434.432413, 60443.370157, 60452.308033, - 60461.246039, 60470.184177, 60479.122446, 60488.060847, 60496.999378, 60505.938041, 60514.876835, 60523.815760, - 60532.754817, 60541.694005, 60550.633323, 60559.572773, 60568.512354, 60577.452066, 60586.391909, 60595.331883, - 60604.271989, 60613.212225, 60622.152592, 60631.093090, 60640.033720, 60648.974480, 60657.915371, 60666.856393, - 60675.797546, 60684.738829, 60693.680244, 60702.621789, 60711.563466, 60720.505273, 60729.447211, 60738.389279, - 60747.331479, 60756.273809, 60765.216270, 60774.158862, 60783.101584, 60792.044437, 60800.987421, 60809.930535, - 60818.873780, 60827.817155, 60836.760662, 60845.704298, 60854.648066, 60863.591963, 60872.535992, 60881.480151, - 60890.424440, 60899.368860, 60908.313410, 60917.258091, 60926.202902, 60935.147843, 60944.092915, 60953.038117, - 60961.983450, 60970.928913, 60979.874506, 60988.820230, 60997.766084, 61006.712068, 61015.658182, 61024.604427, - 61033.550802, 61042.497307, 61051.443942, 61060.390707, 61069.337603, 61078.284628, 61087.231784, 61096.179070, - 61105.126486, 61114.074032, 61123.021708, 61131.969514, 61140.917450, 61149.865516, 61158.813712, 61167.762038, - 61176.710494, 61185.659080, 61194.607796, 61203.556642, 61212.505618, 61221.454723, 61230.403958, 61239.353323, - 61248.302818, 61257.252443, 61266.202198, 61275.152082, 61284.102096, 61293.052240, 61302.002513, 61310.952916, - 61319.903449, 61328.854112, 61337.804904, 61346.755826, 61355.706877, 61364.658058, 61373.609369, 61382.560809, - 61391.512378, 61400.464077, 61409.415906, 61418.367864, 61427.319952, 61436.272169, 61445.224516, 61454.176992, - 61463.129597, 61472.082332, 61481.035196, 61489.988189, 61498.941312, 61507.894564, 61516.847946, 61525.801457, - 61534.755097, 61543.708866, 61552.662764, 61561.616792, 61570.570949, 61579.525235, 61588.479651, 61597.434195, - 61606.388869, 61615.343672, 61624.298603, 61633.253664, 61642.208854, 61651.164173, 61660.119622, 61669.075199, - 61678.030905, 61686.986740, 61695.942704, 61704.898797, 61713.855019, 61722.811370, 61731.767850, 61740.724459, - 61749.681196, 61758.638063, 61767.595058, 61776.552182, 61785.509435, 61794.466817, 61803.424327, 61812.381967, - 61821.339735, 61830.297631, 61839.255657, 61848.213811, 61857.172094, 61866.130505, 61875.089045, 61884.047714, - 61893.006512, 61901.965437, 61910.924492, 61919.883675, 61928.842987, 61937.802427, 61946.761995, 61955.721693, - 61964.681518, 61973.641472, 61982.601555, 61991.561766, 62000.522105, 62009.482573, 62018.443169, 62027.403894, - 62036.364746, 62045.325728, 62054.286837, 62063.248075, 62072.209441, 62081.170935, 62090.132558, 62099.094309, - 62108.056188, 62117.018195, 62125.980330, 62134.942594, 62143.904985, 62152.867505, 62161.830153, 62170.792929, - 62179.755833, 62188.718866, 62197.682026, 62206.645314, 62215.608730, 62224.572275, 62233.535947, 62242.499747, - 62251.463675, 62260.427732, 62269.391916, 62278.356228, 62287.320667, 62296.285235, 62305.249931, 62314.214754, - 62323.179705, 62332.144784, 62341.109991, 62350.075326, 62359.040788, 62368.006378, 62376.972096, 62385.937941, - 62394.903915, 62403.870015, 62412.836244, 62421.802600, 62430.769084, 62439.735695, 62448.702434, 62457.669301, - 62466.636295, 62475.603416, 62484.570666, 62493.538042, 62502.505547, 62511.473178, 62520.440937, 62529.408824, - 62538.376838, 62547.344979, 62556.313248, 62565.281644, 62574.250168, 62583.218819, 62592.187597, 62601.156503, - 62610.125535, 62619.094696, 62628.063983, 62637.033398, 62646.002940, 62654.972609, 62663.942405, 62672.912328, - 62681.882379, 62690.852557, 62699.822862, 62708.793294, 62717.763853, 62726.734539, 62735.705353, 62744.676293, - 62753.647361, 62762.618555, 62771.589876, 62780.561325, 62789.532900, 62798.504603, 62807.476432, 62816.448388, - 62825.420472, 62834.392682, 62843.365019, 62852.337482, 62861.310073, 62870.282791, 62879.255635, 62888.228606, - 62897.201704, 62906.174929, 62915.148280, 62924.121758, 62933.095363, 62942.069095, 62951.042953, 62960.016938, - 62968.991049, 62977.965288, 62986.939652, 62995.914144, 63004.888762, 63013.863507, 63022.838378, 63031.813375, - 63040.788500, 63049.763750, 63058.739128, 63067.714631, 63076.690262, 63085.666018, 63094.641901, 63103.617911, - 63112.594047, 63121.570309, 63130.546697, 63139.523212, 63148.499854, 63157.476621, 63166.453515, 63175.430535, - 63184.407682, 63193.384955, 63202.362354, 63211.339879, 63220.317530, 63229.295308, 63238.273212, 63247.251242, - 63256.229398, 63265.207680, 63274.186088, 63283.164623, 63292.143283, 63301.122070, 63310.100982, 63319.080021, - 63328.059186, 63337.038476, 63346.017893, 63354.997435, 63363.977104, 63372.956898, 63381.936819, 63390.916865, - 63399.897037, 63408.877335, 63417.857759, 63426.838309, 63435.818985, 63444.799786, 63453.780713, 63462.761766, - 63471.742945, 63480.724250, 63489.705680, 63498.687236, 63507.668917, 63516.650725, 63525.632658, 63534.614716, - 63543.596901, 63552.579211, 63561.561646, 63570.544207, 63579.526894, 63588.509706, 63597.492644, 63606.475707, - 63615.458896, 63624.442210, 63633.425650, 63642.409215, 63651.392906, 63660.376722, 63669.360664, 63678.344730, - 63687.328923, 63696.313240, 63705.297684, 63714.282252, 63723.266946, 63732.251765, 63741.236709, 63750.221778, - 63759.206973, 63768.192293, 63777.177739, 63786.163309, 63795.149005, 63804.134826, 63813.120772, 63822.106843, - 63831.093039, 63840.079361, 63849.065807, 63858.052379, 63867.039075, 63876.025897, 63885.012844, 63893.999916, - 63902.987113, 63911.974434, 63920.961881, 63929.949453, 63938.937150, 63947.924971, 63956.912918, 63965.900989, - 63974.889186, 63983.877507, 63992.865953, 64001.854524, 64010.843219, 64019.832040, 64028.820985, 64037.810055, - 64046.799250, 64055.788570, 64064.778014, 64073.767583, 64082.757277, 64091.747095, 64100.737038, 64109.727106, - 64118.717298, 64127.707615, 64136.698057, 64145.688623, 64154.679313, 64163.670129, 64172.661069, 64181.652133, - 64190.643322, 64199.634635, 64208.626073, 64217.617635, 64226.609322, 64235.601133, 64244.593069, 64253.585129, - 64262.577313, 64271.569622, 64280.562055, 64289.554612, 64298.547294, 64307.540100, 64316.533030, 64325.526085, - 64334.519264, 64343.512567, 64352.505994, 64361.499546, 64370.493222, 64379.487022, 64388.480946, 64397.474994, - 64406.469167, 64415.463463, 64424.457884, 64433.452429, 64442.447097, 64451.441890, 64460.436807, 64469.431848, - 64478.427013, 64487.422302, 64496.417715, 64505.413252, 64514.408913, 64523.404698, 64532.400607, 64541.396639, - 64550.392796, 64559.389076, 64568.385481, 64577.382009, 64586.378661, 64595.375437, 64604.372336, 64613.369360, - 64622.366507, 64631.363778, 64640.361172, 64649.358691, 64658.356333, 64667.354098, 64676.351988, 64685.350001, - 64694.348138, 64703.346398, 64712.344782, 64721.343290, 64730.341921, 64739.340676, 64748.339554, 64757.338556, - 64766.337681, 64775.336930, 64784.336303, 64793.335799, 64802.335418, 64811.335161, 64820.335027, 64829.335016, - 64838.335130, 64847.335366, 64856.335726, 64865.336209, 64874.336815, 64883.337545, 64892.338398, 64901.339375, - 64910.340475, 64919.341698, 64928.343044, 64937.344513, 64946.346106, 64955.347822, 64964.349661, 64973.351623, - 64982.353709, 64991.355917, 65000.358249, 65009.360704, 65018.363282, 65027.365983, 65036.368807, 65045.371754, - 65054.374824, 65063.378017, 65072.381334, 65081.384773, 65090.388335, 65099.392020, 65108.395828, 65117.399759, - 65126.403813, 65135.407990, 65144.412290, 65153.416712, 65162.421258, 65171.425926, 65180.430717, 65189.435631, - 65198.440668, 65207.445827, 65216.451110, 65225.456515, 65234.462042, 65243.467693, 65252.473466, 65261.479362, - 65270.485381, 65279.491522, 65288.497786, 65297.504172, 65306.510681, 65315.517313, 65324.524067, 65333.530944, - 65342.537944, 65351.545066, 65360.552310, 65369.559677, 65378.567167, 65387.574779, 65396.582513, 65405.590370, - 65414.598350, 65423.606451, 65432.614676, 65441.623022, 65450.631491, 65459.640082, 65468.648796, 65477.657632, - 65486.666590, 65495.675671, 65504.684874, 65513.694199, 65522.703647, 65531.713216, 65540.722908, 65549.732722, - 65558.742659, 65567.752717, 65576.762898, 65585.773200, 65594.783625, 65603.794172, 65612.804842, 65621.815633, - 65630.826546, 65639.837582, 65648.848739, 65657.860019, 65666.871420, 65675.882944, 65684.894589, 65693.906357, - 65702.918246, 65711.930257, 65720.942391, 65729.954646, 65738.967023, 65747.979522, 65756.992143, 65766.004886, - 65775.017750, 65784.030737, 65793.043845, 65802.057075, 65811.070427, 65820.083900, 65829.097495, 65838.111213, - 65847.125051, 65856.139012, 65865.153094, 65874.167298, 65883.181623, 65892.196070, 65901.210639, 65910.225329, - 65919.240141, 65928.255075, 65937.270130, 65946.285307, 65955.300605, 65964.316025, 65973.331566, 65982.347229, - 65991.363013, 66000.378919, 66009.394946, 66018.411095, 66027.427365, 66036.443756, 66045.460269, 66054.476904, - 66063.493659, 66072.510536, 66081.527534, 66090.544654, 66099.561895, 66108.579257, 66117.596741, 66126.614346, - 66135.632072, 66144.649919, 66153.667887, 66162.685977, 66171.704188, 66180.722520, 66189.740973, 66198.759548, - 66207.778243, 66216.797060, 66225.815997, 66234.835056, 66243.854236, 66252.873537, 66261.892959, 66270.912502, - 66279.932166, 66288.951951, 66297.971857, 66306.991884, 66316.012032, 66325.032301, 66334.052690, 66343.073201, - 66352.093833, 66361.114585, 66370.135459, 66379.156453, 66388.177568, 66397.198804, 66406.220160, 66415.241638, - 66424.263236, 66433.284955, 66442.306795, 66451.328755, 66460.350837, 66469.373038, 66478.395361, 66487.417804, - 66496.440368, 66505.463053, 66514.485858, 66523.508784, 66532.531831, 66541.554998, 66550.578285, 66559.601693, - 66568.625222, 66577.648871, 66586.672641, 66595.696532, 66604.720542, 66613.744674, 66622.768925, 66631.793298, - 66640.817790, 66649.842403, 66658.867137, 66667.891990, 66676.916965, 66685.942059, 66694.967274, 66703.992609, - 66713.018065, 66722.043641, 66731.069337, 66740.095153, 66749.121090, 66758.147147, 66767.173324, 66776.199621, - 66785.226039, 66794.252576, 66803.279234, 66812.306012, 66821.332911, 66830.359929, 66839.387067, 66848.414326, - 66857.441704, 66866.469203, 66875.496822, 66884.524561, 66893.552419, 66902.580398, 66911.608497, 66920.636716, - 66929.665055, 66938.693513, 66947.722092, 66956.750791, 66965.779609, 66974.808547, 66983.837606, 66992.866784, - 67001.896082, 67010.925500, 67019.955037, 67028.984695, 67038.014472, 67047.044369, 67056.074386, 67065.104522, - 67074.134779, 67083.165155, 67092.195651, 67101.226266, 67110.257001, 67119.287856, 67128.318830, 67137.349924, - 67146.381138, 67155.412471, 67164.443924, 67173.475497, 67182.507189, 67191.539001, 67200.570932, 67209.602982, - 67218.635153, 67227.667442, 67236.699851, 67245.732380, 67254.765028, 67263.797796, 67272.830683, 67281.863689, - 67290.896815, 67299.930060, 67308.963424, 67317.996908, 67327.030511, 67336.064234, 67345.098076, 67354.132037, - 67363.166117, 67372.200317, 67381.234636, 67390.269074, 67399.303631, 67408.338308, 67417.373104, 67426.408019, - 67435.443053, 67444.478206, 67453.513479, 67462.548870, 67471.584381, 67480.620011, 67489.655760, 67498.691628, - 67507.727615, 67516.763721, 67525.799946, 67534.836290, 67543.872753, 67552.909335, 67561.946036, 67570.982856, - 67580.019795, 67589.056853, 67598.094029, 67607.131325, 67616.168739, 67625.206273, 67634.243925, 67643.281696, - 67652.319586, 67661.357595, 67670.395722, 67679.433969, 67688.472334, 67697.510818, 67706.549420, 67715.588142, - 67724.626982, 67733.665941, 67742.705018, 67751.744214, 67760.783529, 67769.822962, 67778.862514, 67787.902185, - 67796.941974, 67805.981882, 67815.021909, 67824.062054, 67833.102317, 67842.142699, 67851.183200, 67860.223819, - 67869.264556, 67878.305413, 67887.346387, 67896.387480, 67905.428691, 67914.470021, 67923.511469, 67932.553036, - 67941.594721, 67950.636525, 67959.678446, 67968.720486, 67977.762645, 67986.804921, 67995.847316, 68004.889830, - 68013.932461, 68022.975211, 68032.018079, 68041.061065, 68050.104170, 68059.147392, 68068.190733, 68077.234192, - 68086.277769, 68095.321465, 68104.365278, 68113.409209, 68122.453259, 68131.497427, 68140.541713, 68149.586116, - 68158.630638, 68167.675278, 68176.720036, 68185.764912, 68194.809906, 68203.855018, 68212.900248, 68221.945596, - 68230.991061, 68240.036645, 68249.082347, 68258.128166, 68267.174103, 68276.220158, 68285.266331, 68294.312622, - 68303.359031, 68312.405558, 68321.452202, 68330.498964, 68339.545844, 68348.592841, 68357.639957, 68366.687190, - 68375.734540, 68384.782009, 68393.829595, 68402.877299, 68411.925120, 68420.973059, 68430.021116, 68439.069290, - 68448.117582, 68457.165992, 68466.214519, 68475.263163, 68484.311926, 68493.360805, 68502.409802, 68511.458917, - 68520.508149, 68529.557499, 68538.606966, 68547.656551, 68556.706253, 68565.756072, 68574.806009, 68583.856063, - 68592.906235, 68601.956524, 68611.006930, 68620.057454, 68629.108095, 68638.158853, 68647.209729, 68656.260722, - 68665.311832, 68674.363059, 68683.414404, 68692.465866, 68701.517445, 68710.569141, 68719.620955, 68728.672885, - 68737.724933, 68746.777098, 68755.829380, 68764.881779, 68773.934296, 68782.986929, 68792.039679, 68801.092547, - 68810.145531, 68819.198633, 68828.251852, 68837.305187, 68846.358640, 68855.412210, 68864.465896, 68873.519700, - 68882.573620, 68891.627657, 68900.681812, 68909.736083, 68918.790471, 68927.844976, 68936.899598, 68945.954336, - 68955.009192, 68964.064164, 68973.119253, 68982.174459, 68991.229782, 69000.285221, 69009.340777, 69018.396450, - 69027.452240, 69036.508146, 69045.564169, 69054.620309, 69063.676565, 69072.732938, 69081.789428, 69090.846034, - 69099.902757, 69108.959596, 69118.016553, 69127.073625, 69136.130814, 69145.188120, 69154.245542, 69163.303081, - 69172.360736, 69181.418508, 69190.476396, 69199.534401, 69208.592522, 69217.650760, 69226.709114, 69235.767584, - 69244.826171, 69253.884874, 69262.943694, 69272.002630, 69281.061682, 69290.120851, 69299.180136, 69308.239537, - 69317.299054, 69326.358688, 69335.418438, 69344.478304, 69353.538287, 69362.598385, 69371.658600, 69380.718931, - 69389.779379, 69398.839942, 69407.900622, 69416.961418, 69426.022329, 69435.083357, 69444.144501, 69453.205762, - 69462.267138, 69471.328630, 69480.390238, 69489.451963, 69498.513803, 69507.575759, 69516.637832, 69525.700020, - 69534.762324, 69543.824745, 69552.887281, 69561.949933, 69571.012701, 69580.075585, 69589.138585, 69598.201700, - 69607.264932, 69616.328279, 69625.391742, 69634.455321, 69643.519016, 69652.582827, 69661.646753, 69670.710795, - 69679.774953, 69688.839227, 69697.903616, 69706.968121, 69716.032742, 69725.097478, 69734.162330, 69743.227298, - 69752.292381, 69761.357580, 69770.422895, 69779.488325, 69788.553871, 69797.619532, 69806.685309, 69815.751202, - 69824.817210, 69833.883333, 69842.949572, 69852.015927, 69861.082397, 69870.148982, 69879.215683, 69888.282499, - 69897.349431, 69906.416478, 69915.483641, 69924.550919, 69933.618312, 69942.685821, 69951.753445, 69960.821185, - 69969.889039, 69978.957009, 69988.025095, 69997.093295, 70006.161611, 70015.230042, 70024.298589, 70033.367250, - 70042.436027, 70051.504919, 70060.573926, 70069.643049, 70078.712286, 70087.781639, 70096.851107, 70105.920690, - 70114.990388, 70124.060201, 70133.130129, 70142.200172, 70151.270331, 70160.340604, 70169.410992, 70178.481496, - 70187.552114, 70196.622848, 70205.693696, 70214.764659, 70223.835738, 70232.906931, 70241.978239, 70251.049662, - 70260.121200, 70269.192853, 70278.264621, 70287.336503, 70296.408501, 70305.480613, 70314.552840, 70323.625182, - 70332.697639, 70341.770210, 70350.842896, 70359.915697, 70368.988613, 70378.061643, 70387.134788, 70396.208048, - 70405.281423, 70414.354912, 70423.428516, 70432.502234, 70441.576067, 70450.650015, 70459.724078, 70468.798254, - 70477.872546, 70486.946952, 70496.021473, 70505.096108, 70514.170858, 70523.245722, 70532.320701, 70541.395794, - 70550.471002, 70559.546324, 70568.621760, 70577.697311, 70586.772977, 70595.848757, 70604.924651, 70614.000660, - 70623.076783, 70632.153020, 70641.229372, 70650.305838, 70659.382418, 70668.459113, 70677.535922, 70686.612845, - 70695.689883, 70704.767034, 70713.844300, 70722.921681, 70731.999175, 70741.076784, 70750.154507, 70759.232344, - 70768.310295, 70777.388360, 70786.466540, 70795.544833, 70804.623241, 70813.701763, 70822.780399, 70831.859149, - 70840.938013, 70850.016991, 70859.096083, 70868.175289, 70877.254609, 70886.334043, 70895.413591, 70904.493253, - 70913.573029, 70922.652919, 70931.732923, 70940.813041, 70949.893272, 70958.973618, 70968.054077, 70977.134651, - 70986.215338, 70995.296139, 71004.377054, 71013.458082, 71022.539225, 71031.620481, 71040.701851, 71049.783335, - 71058.864932, 71067.946644, 71077.028469, 71086.110407, 71095.192460, 71104.274626, 71113.356905, 71122.439299, - 71131.521806, 71140.604426, 71149.687160, 71158.770008, 71167.852970, 71176.936045, 71186.019233, 71195.102536, - 71204.185951, 71213.269480, 71222.353123, 71231.436879, 71240.520749, 71249.604732, 71258.688829, 71267.773039, - 71276.857363, 71285.941799, 71295.026350, 71304.111014, 71313.195791, 71322.280681, 71331.365685, 71340.450802, - 71349.536033, 71358.621377, 71367.706834, 71376.792404, 71385.878088, 71394.963885, 71404.049796, 71413.135819, - 71422.221956, 71431.308206, 71440.394569, 71449.481045, 71458.567635, 71467.654338, 71476.741154, 71485.828083, - 71494.915125, 71504.002280, 71513.089548, 71522.176930, 71531.264424, 71540.352032, 71549.439753, 71558.527586, - 71567.615533, 71576.703593, 71585.791766, 71594.880051, 71603.968450, 71613.056962, 71622.145586, 71631.234324, - 71640.323174, 71649.412138, 71658.501214, 71667.590403, 71676.679705, 71685.769120, 71694.858648, 71703.948288, - 71713.038042, 71722.127908, 71731.217887, 71740.307979, 71749.398184, 71758.488501, 71767.578931, 71776.669474, - 71785.760129, 71794.850897, 71803.941778, 71813.032772, 71822.123878, 71831.215097, 71840.306429, 71849.397873, - 71858.489430, 71867.581099, 71876.672881, 71885.764776, 71894.856783, 71903.948903, 71913.041135, 71922.133480, - 71931.225937, 71940.318507, 71949.411190, 71958.503984, 71967.596892, 71976.689911, 71985.783043, 71994.876288, - 72003.969645, 72013.063115, 72022.156696, 72031.250391, 72040.344197, 72049.438116, 72058.532147, 72067.626291, - 72076.720547, 72085.814915, 72094.909395, 72104.003988, 72113.098693, 72122.193510, 72131.288440, 72140.383482, - 72149.478636, 72158.573902, 72167.669280, 72176.764771, 72185.860373, 72194.956088, 72204.051915, 72213.147854, - 72222.243906, 72231.340069, 72240.436344, 72249.532732, 72258.629231, 72267.725843, 72276.822567, 72285.919402, - 72295.016350, 72304.113410, 72313.210581, 72322.307865, 72331.405261, 72340.502768, 72349.600388, 72358.698119, - 72367.795962, 72376.893918, 72385.991985, 72395.090164, 72404.188455, 72413.286857, 72422.385372, 72431.483998, - 72440.582737, 72449.681587, 72458.780548, 72467.879622, 72476.978807, 72486.078104, 72495.177513, 72504.277034, - 72513.376666, 72522.476410, 72531.576265, 72540.676233, 72549.776312, 72558.876502, 72567.976805, 72577.077219, - 72586.177744, 72595.278381, 72604.379130, 72613.479990, 72622.580962, 72631.682045, 72640.783240, 72649.884547, - 72658.985965, 72668.087494, 72677.189135, 72686.290888, 72695.392751, 72704.494727, 72713.596814, 72722.699012, - 72731.801321, 72740.903742, 72750.006275, 72759.108919, 72768.211674, 72777.314540, 72786.417518, 72795.520607, - 72804.623808, 72813.727120, 72822.830543, 72831.934077, 72841.037723, 72850.141480, 72859.245348, 72868.349327, - 72877.453418, 72886.557619, 72895.661932, 72904.766357, 72913.870892, 72922.975538, 72932.080296, 72941.185165, - 72950.290145, 72959.395236, 72968.500438, 72977.605751, 72986.711175, 72995.816710, 73004.922356, 73014.028114, - 73023.133982, 73032.239962, 73041.346052, 73050.452253, 73059.558566, 73068.664989, 73077.771523, 73086.878168, - 73095.984924, 73105.091791, 73114.198769, 73123.305858, 73132.413057, 73141.520368, 73150.627789, 73159.735321, - 73168.842964, 73177.950718, 73187.058583, 73196.166558, 73205.274644, 73214.382841, 73223.491149, 73232.599567, - 73241.708096, 73250.816736, 73259.925486, 73269.034348, 73278.143320, 73287.252402, 73296.361595, 73305.470899, - 73314.580314, 73323.689839, 73332.799474, 73341.909221, 73351.019077, 73360.129045, 73369.239123, 73378.349311, - 73387.459610, 73396.570020, 73405.680540, 73414.791170, 73423.901911, 73433.012763, 73442.123725, 73451.234797, - 73460.345980, 73469.457273, 73478.568677, 73487.680191, 73496.791815, 73505.903550, 73515.015395, 73524.127351, - 73533.239416, 73542.351592, 73551.463879, 73560.576276, 73569.688783, 73578.801400, 73587.914127, 73597.026965, - 73606.139913, 73615.252972, 73624.366140, 73633.479419, 73642.592808, 73651.706307, 73660.819916, 73669.933635, - 73679.047465, 73688.161404, 73697.275454, 73706.389614, 73715.503884, 73724.618264, 73733.732754, 73742.847354, - 73751.962064, 73761.076884, 73770.191814, 73779.306854, 73788.422005, 73797.537265, 73806.652635, 73815.768115, - 73824.883705, 73833.999405, 73843.115215, 73852.231135, 73861.347164, 73870.463304, 73879.579553, 73888.695913, - 73897.812382, 73906.928961, 73916.045650, 73925.162448, 73934.279357, 73943.396375, 73952.513503, 73961.630741, - 73970.748088, 73979.865545, 73988.983112, 73998.100789, 74007.218575, 74016.336472, 74025.454477, 74034.572593, - 74043.690818, 74052.809153, 74061.927597, 74071.046151, 74080.164814, 74089.283588, 74098.402470, 74107.521463, - 74116.640565, 74125.759776, 74134.879097, 74143.998528, 74153.118068, 74162.237717, 74171.357476, 74180.477344, - 74189.597322, 74198.717410, 74207.837607, 74216.957913, 74226.078329, 74235.198854, 74244.319488, 74253.440232, - 74262.561085, 74271.682048, 74280.803120, 74289.924301, 74299.045591, 74308.166991, 74317.288500, 74326.410119, - 74335.531847, 74344.653684, 74353.775630, 74362.897685, 74372.019850, 74381.142124, 74390.264507, 74399.386999, - 74408.509601, 74417.632311, 74426.755131, 74435.878060, 74445.001098, 74454.124245, 74463.247501, 74472.370867, - 74481.494341, 74490.617925, 74499.741617, 74508.865419, 74517.989330, 74527.113349, 74536.237478, 74545.361716, - 74554.486062, 74563.610518, 74572.735082, 74581.859756, 74590.984538, 74600.109430, 74609.234430, 74618.359539, - 74627.484758, 74636.610085, 74645.735520, 74654.861065, 74663.986719, 74673.112481, 74682.238352, 74691.364332, - 74700.490421, 74709.616619, 74718.742925, 74727.869340, 74736.995864, 74746.122497, 74755.249238, 74764.376088, - 74773.503047, 74782.630114, 74791.757290, 74800.884575, 74810.011969, 74819.139471, 74828.267082, 74837.394801, - 74846.522629, 74855.650565, 74864.778611, 74873.906764, 74883.035026, 74892.163397, 74901.291877, 74910.420465, - 74919.549161, 74928.677966, 74937.806879, 74946.935901, 74956.065031, 74965.194270, 74974.323617, 74983.453073, - 74992.582637, 75001.712309, 75010.842090, 75019.971980, 75029.101977, 75038.232083, 75047.362298, 75056.492620, - 75065.623051, 75074.753590, 75083.884238, 75093.014994, 75102.145858, 75111.276831, 75120.407911, 75129.539100, - 75138.670397, 75147.801803, 75156.933316, 75166.064938, 75175.196668, 75184.328506, 75193.460453, 75202.592507, - 75211.724670, 75220.856940, 75229.989319, 75239.121806, 75248.254401, 75257.387104, 75266.519915, 75275.652835, - 75284.785862, 75293.918997, 75303.052240, 75312.185592, 75321.319051, 75330.452618, 75339.586294, 75348.720077, - 75357.853968, 75366.987967, 75376.122074, 75385.256289, 75394.390612, 75403.525043, 75412.659582, 75421.794228, - 75430.928983, 75440.063845, 75449.198815, 75458.333893, 75467.469078, 75476.604372, 75485.739773, 75494.875282, - 75504.010899, 75513.146624, 75522.282456, 75531.418396, 75540.554444, 75549.690599, 75558.826863, 75567.963233, - 75577.099712, 75586.236298, 75595.372992, 75604.509793, 75613.646702, 75622.783719, 75631.920843, 75641.058075, - 75650.195415, 75659.332862, 75668.470417, 75677.608079, 75686.745848, 75695.883726, 75705.021710, 75714.159802, - 75723.298002, 75732.436309, 75741.574724, 75750.713246, 75759.851876, 75768.990613, 75778.129457, 75787.268409, - 75796.407468, 75805.546634, 75814.685908, 75823.825290, 75832.964778, 75842.104374, 75851.244077, 75860.383888, - 75869.523806, 75878.663831, 75887.803964, 75896.944203, 75906.084550, 75915.225005, 75924.365566, 75933.506235, - 75942.647011, 75951.787894, 75960.928884, 75970.069982, 75979.211186, 75988.352498, 75997.493917, 76006.635443, - 76015.777076, 76024.918816, 76034.060664, 76043.202618, 76052.344680, 76061.486848, 76070.629124, 76079.771507, - 76088.913996, 76098.056593, 76107.199297, 76116.342108, 76125.485025, 76134.628050, 76143.771182, 76152.914420, - 76162.057766, 76171.201218, 76180.344777, 76189.488444, 76198.632217, 76207.776097, 76216.920084, 76226.064177, - 76235.208378, 76244.352685, 76253.497100, 76262.641621, 76271.786248, 76280.930983, 76290.075824, 76299.220773, - 76308.365828, 76317.510989, 76326.656258, 76335.801633, 76344.947114, 76354.092703, 76363.238398, 76372.384200, - 76381.530108, 76390.676124, 76399.822245, 76408.968474, 76418.114809, 76427.261251, 76436.407799, 76445.554454, - 76454.701215, 76463.848083, 76472.995057, 76482.142138, 76491.289326, 76500.436620, 76509.584021, 76518.731528, - 76527.879141, 76537.026861, 76546.174688, 76555.322621, 76564.470660, 76573.618806, 76582.767058, 76591.915417, - 76601.063882, 76610.212453, 76619.361131, 76628.509915, 76637.658805, 76646.807802, 76655.956905, 76665.106114, - 76674.255430, 76683.404852, 76692.554380, 76701.704015, 76710.853755, 76720.003602, 76729.153556, 76738.303615, - 76747.453781, 76756.604052, 76765.754431, 76774.904915, 76784.055505, 76793.206202, 76802.357004, 76811.507913, - 76820.658928, 76829.810049, 76838.961276, 76848.112609, 76857.264049, 76866.415594, 76875.567245, 76884.719003, - 76893.870866, 76903.022836, 76912.174911, 76921.327092, 76930.479380, 76939.631773, 76948.784273, 76957.936878, - 76967.089589, 76976.242406, 76985.395330, 76994.548359, 77003.701493, 77012.854734, 77022.008081, 77031.161533, - 77040.315092, 77049.468756, 77058.622526, 77067.776402, 77076.930383, 77086.084471, 77095.238664, 77104.392963, - 77113.547368, 77122.701878, 77131.856495, 77141.011216, 77150.166044, 77159.320977, 77168.476017, 77177.631161, - 77186.786412, 77195.941768, 77205.097229, 77214.252797, 77223.408470, 77232.564248, 77241.720133, 77250.876122, - 77260.032218, 77269.188419, 77278.344725, 77287.501137, 77296.657655, 77305.814278, 77314.971006, 77324.127840, - 77333.284780, 77342.441825, 77351.598976, 77360.756232, 77369.913593, 77379.071060, 77388.228632, 77397.386310, - 77406.544093, 77415.701982, 77424.859976, 77434.018075, 77443.176279, 77452.334589, 77461.493005, 77470.651525, - 77479.810151, 77488.968883, 77498.127719, 77507.286661, 77516.445708, 77525.604860, 77534.764118, 77543.923481, - 77553.082949, 77562.242522, 77571.402200, 77580.561984, 77589.721873, 77598.881867, 77608.041966, 77617.202170, - 77626.362480, 77635.522894, 77644.683414, 77653.844039, 77663.004769, 77672.165604, 77681.326544, 77690.487589, - 77699.648739, 77708.809994, 77717.971354, 77727.132819, 77736.294390, 77745.456065, 77754.617845, 77763.779730, - 77772.941720, 77782.103815, 77791.266015, 77800.428320, 77809.590730, 77818.753245, 77827.915864, 77837.078589, - 77846.241418, 77855.404353, 77864.567392, 77873.730536, 77882.893784, 77892.057138, 77901.220596, 77910.384160, - 77919.547828, 77928.711600, 77937.875478, 77947.039460, 77956.203547, 77965.367739, 77974.532035, 77983.696436, - 77992.860942, 78002.025553, 78011.190268, 78020.355088, 78029.520012, 78038.685041, 78047.850175, 78057.015414, - 78066.180757, 78075.346204, 78084.511756, 78093.677413, 78102.843174, 78112.009040, 78121.175011, 78130.341086, - 78139.507265, 78148.673549, 78157.839938, 78167.006431, 78176.173028, 78185.339730, 78194.506536, 78203.673447, - 78212.840462, 78222.007582, 78231.174806, 78240.342135, 78249.509568, 78258.677105, 78267.844746, 78277.012492, - 78286.180343, 78295.348297, 78304.516356, 78313.684520, 78322.852787, 78332.021159, 78341.189635, 78350.358216, - 78359.526900, 78368.695689, 78377.864583, 78387.033580, 78396.202682, 78405.371887, 78414.541197, 78423.710612, - 78432.880130, 78442.049753, 78451.219479, 78460.389310, 78469.559245, 78478.729284, 78487.899427, 78497.069675, - 78506.240026, 78515.410481, 78524.581041, 78533.751704, 78542.922472, 78552.093344, 78561.264319, 78570.435399, - 78579.606583, 78588.777870, 78597.949262, 78607.120757, 78616.292357, 78625.464060, 78634.635868, 78643.807779, - 78652.979794, 78662.151914, 78671.324137, 78680.496464, 78689.668894, 78698.841429, 78708.014068, 78717.186810, - 78726.359656, 78735.532606, 78744.705660, 78753.878817, 78763.052079, 78772.225444, 78781.398913, 78790.572485, - 78799.746162, 78808.919942, 78818.093826, 78827.267813, 78836.441905, 78845.616100, 78854.790398, 78863.964800, - 78873.139306, 78882.313916, 78891.488629, 78900.663446, 78909.838366, 78919.013390, 78928.188518, 78937.363749, - 78946.539084, 78955.714522, 78964.890064, 78974.065710, 78983.241458, 78992.417311, 79001.593267, 79010.769326, - 79019.945489, 79029.121756, 79038.298125, 79047.474599, 79056.651175, 79065.827856, 79075.004639, 79084.181526, - 79093.358517, 79102.535610, 79111.712808, 79120.890108, 79130.067512, 79139.245019, 79148.422630, 79157.600344, - 79166.778161, 79175.956081, 79185.134105, 79194.312232, 79203.490462, 79212.668796, 79221.847233, 79231.025773, - 79240.204416, 79249.383163, 79258.562012, 79267.740965, 79276.920021, 79286.099181, 79295.278443, 79304.457809, - 79313.637277, 79322.816849, 79331.996524, 79341.176302, 79350.356183, 79359.536168, 79368.716255, 79377.896445, - 79387.076739, 79396.257135, 79405.437635, 79414.618237, 79423.798943, 79432.979751, 79442.160663, 79451.341678, - 79460.522795, 79469.704016, 79478.885339, 79488.066765, 79497.248295, 79506.429927, 79515.611662, 79524.793500, - 79533.975441, 79543.157485, 79552.339631, 79561.521881, 79570.704233, 79579.886688, 79589.069246, 79598.251907, - 79607.434671, 79616.617537, 79625.800506, 79634.983578, 79644.166753, 79653.350030, 79662.533410, 79671.716893, - 79680.900479, 79690.084167, 79699.267958, 79708.451852, 79717.635849, 79726.819948, 79736.004149, 79745.188454, - 79754.372861, 79763.557370, 79772.741982, 79781.926697, 79791.111515, 79800.296435, 79809.481457, 79818.666582, - 79827.851810, 79837.037140, 79846.222573, 79855.408108, 79864.593746, 79873.779486, 79882.965329, 79892.151274, - 79901.337322, 79910.523472, 79919.709725, 79928.896080, 79938.082537, 79947.269097, 79956.455759, 79965.642524, - 79974.829391, 79984.016360, 79993.203432, 80002.390606, 80011.577882, 80020.765261, 80029.952742, 80039.140326, - 80048.328011, 80057.515799, 80066.703690, 80075.891682, 80085.079777, 80094.267974, 80103.456273, 80112.644675, - 80121.833178, 80131.021784, 80140.210492, 80149.399302, 80158.588215, 80167.777229, 80176.966346, 80186.155565, - 80195.344886, 80204.534309, 80213.723834, 80222.913462, 80232.103191, 80241.293023, 80250.482956, 80259.672992, - 80268.863130, 80278.053369, 80287.243711, 80296.434155, 80305.624700, 80314.815348, 80324.006098, 80333.196950, - 80342.387903, 80351.578959, 80360.770116, 80369.961376, 80379.152737, 80388.344201, 80397.535766, 80406.727433, - 80415.919202, 80425.111073, 80434.303045, 80443.495120, 80452.687296, 80461.879575, 80471.071955, 80480.264437, - 80489.457020, 80498.649706, 80507.842493, 80517.035382, 80526.228373, 80535.421465, 80544.614659, 80553.807955, - 80563.001353, 80572.194852, 80581.388453, 80590.582156, 80599.775960, 80608.969866, 80618.163874, 80627.357984, - 80636.552195, 80645.746507, 80654.940921, 80664.135437, 80673.330055, 80682.524774, 80691.719594, 80700.914516, - 80710.109540, 80719.304665, 80728.499892, 80737.695220, 80746.890650, 80756.086181, 80765.281814, 80774.477548, - 80783.673384, 80792.869321, 80802.065360, 80811.261500, 80820.457741, 80829.654084, 80838.850528, 80848.047074, - 80857.243721, 80866.440469, 80875.637319, 80884.834270, 80894.031323, 80903.228476, 80912.425732, 80921.623088, - 80930.820546, 80940.018105, 80949.215765, 80958.413527, 80967.611390, 80976.809354, 80986.007419, 80995.205586, - 81004.403853, 81013.602222, 81022.800693, 81031.999264, 81041.197937, 81050.396710, 81059.595585, 81068.794561, - 81077.993638, 81087.192817, 81096.392096, 81105.591477, 81114.790958, 81123.990541, 81133.190225, 81142.390010, - 81151.589896, 81160.789883, 81169.989971, 81179.190160, 81188.390450, 81197.590841, 81206.791333, 81215.991926, - 81225.192620, 81234.393415, 81243.594311, 81252.795307, 81261.996405, 81271.197604, 81280.398904, 81289.600304, - 81298.801805, 81308.003408, 81317.205111, 81326.406915, 81335.608820, 81344.810826, 81354.012932, 81363.215140, - 81372.417448, 81381.619857, 81390.822367, 81400.024977, 81409.227689, 81418.430501, 81427.633413, 81436.836427, - 81446.039541, 81455.242756, 81464.446072, 81473.649489, 81482.853006, 81492.056624, 81501.260342, 81510.464161, - 81519.668081, 81528.872102, 81538.076223, 81547.280444, 81556.484767, 81565.689189, 81574.893713, 81584.098337, - 81593.303062, 81602.507887, 81611.712813, 81620.917839, 81630.122966, 81639.328193, 81648.533521, 81657.738949, - 81666.944478, 81676.150107, 81685.355837, 81694.561667, 81703.767598, 81712.973629, 81722.179761, 81731.385992, - 81740.592325, 81749.798758, 81759.005291, 81768.211924, 81777.418658, 81786.625492, 81795.832427, 81805.039462, - 81814.246597, 81823.453833, 81832.661168, 81841.868605, 81851.076141, 81860.283778, 81869.491515, 81878.699352, - 81887.907290, 81897.115327, 81906.323465, 81915.531703, 81924.740042, 81933.948480, 81943.157019, 81952.365658, - 81961.574397, 81970.783236, 81979.992176, 81989.201215, 81998.410355, 82007.619595, 82016.828935, 82026.038374, - 82035.247915, 82044.457555, 82053.667295, 82062.877135, 82072.087075, 82081.297116, 82090.507256, 82099.717496, - 82108.927837 - }; - -/* Nat log values for 0.1, 0.2, 0.3, etc. */ + 0.000000, 0.000000, 0.693147, 1.791759, 3.178054, 4.787492, 6.579251, 8.525161, + 10.604603, 12.801827, 15.104413, 17.502308, 19.987214, 22.552164, 25.191221, 27.899271, + 30.671860, 33.505073, 36.395445, 39.339884, 42.335616, 45.380139, 48.471181, 51.606676, + 54.784729, 58.003605, 61.261702, 64.557539, 67.889743, 71.257039, 74.658236, 78.092224, + 81.557959, 85.054467, 88.580828, 92.136176, 95.719695, 99.330612, 102.968199, 106.631760, + 110.320640, 114.034212, 117.771881, 121.533082, 125.317271, 129.123934, 132.952575, 136.802723, + 140.673924, 144.565744, 148.477767, 152.409593, 156.360836, 160.331128, 164.320112, 168.327445, + 172.352797, 176.395848, 180.456291, 184.533829, 188.628173, 192.739047, 196.866182, 201.009316, + 205.168199, 209.342587, 213.532241, 217.736934, 221.956442, 226.190548, 230.439044, 234.701723, + 238.978390, 243.268849, 247.572914, 251.890402, 256.221136, 260.564941, 264.921650, 269.291098, + 273.673124, 278.067573, 282.474293, 286.893133, 291.323950, 295.766601, 300.220949, 304.686857, + 309.164194, 313.652830, 318.152640, 322.663499, 327.185288, 331.717887, 336.261182, 340.815059, + 345.379407, 349.954118, 354.539086, 359.134205, 363.739376, 368.354496, 372.979469, 377.614198, + 382.258589, 386.912549, 391.575988, 396.248817, 400.930948, 405.622296, 410.322777, 415.032307, + 419.750806, 424.478193, 429.214392, 433.959324, 438.712914, 443.475088, 448.245773, 453.024896, + 457.812388, 462.608179, 467.412200, 472.224384, 477.044665, 481.872979, 486.709261, 491.553448, + 496.405478, 501.265291, 506.132825, 511.008023, 515.890825, 520.781174, 525.679014, 530.584288, + 535.496943, 540.416924, 545.344178, 550.278652, 555.220294, 560.169054, 565.124881, 570.087726, + 575.057539, 580.034273, 585.017879, 590.008312, 595.005524, 600.009471, 605.020106, 610.037386, + 615.061266, 620.091704, 625.128657, 630.172082, 635.221938, 640.278184, 645.340779, 650.409683, + 655.484857, 660.566261, 665.653857, 670.747608, 675.847474, 680.953420, 686.065407, 691.183401, + 696.307365, 701.437264, 706.573062, 711.714726, 716.862220, 722.015512, 727.174567, 732.339353, + 737.509837, 742.685987, 747.867770, 753.055156, 758.248113, 763.446610, 768.650617, 773.860103, + 779.075039, 784.295395, 789.521141, 794.752250, 799.988692, 805.230439, 810.477463, 815.729736, + 820.987232, 826.249922, 831.517780, 836.790780, 842.068894, 847.352098, 852.640365, 857.933670, + 863.231987, 868.535292, 873.843560, 879.156766, 884.474886, 889.797896, 895.125772, 900.458491, + 905.796029, 911.138363, 916.485471, 921.837329, 927.193915, 932.555207, 937.921183, 943.291821, + 948.667100, 954.046997, 959.431492, 964.820564, 970.214191, 975.612354, 981.015031, 986.422203, + 991.833849, 997.249950, 1002.670485, 1008.095435, 1013.524780, 1018.958502, 1024.396582, 1029.838999, + 1035.285737, 1040.736775, 1046.192096, 1051.651682, 1057.115514, 1062.583574, 1068.055844, 1073.532308, + 1079.012947, 1084.497744, 1089.986681, 1095.479743, 1100.976911, 1106.478169, 1111.983501, 1117.492889, + 1123.006318, 1128.523771, 1134.045232, 1139.570685, 1145.100114, 1150.633503, 1156.170838, 1161.712101, + 1167.257279, 1172.806355, 1178.359314, 1183.916142, 1189.476824, 1195.041344, 1200.609689, 1206.181843, + 1211.757792, 1217.337522, 1222.921018, 1228.508267, 1234.099254, 1239.693965, 1245.292387, 1250.894506, + 1256.500308, 1262.109780, 1267.722908, 1273.339679, 1278.960080, 1284.584097, 1290.211718, 1295.842930, + 1301.477720, 1307.116075, 1312.757982, 1318.403428, 1324.052403, 1329.704892, 1335.360884, 1341.020366, + 1346.683326, 1352.349753, 1358.019634, 1363.692957, 1369.369711, 1375.049884, 1380.733463, 1386.420439, + 1392.110798, 1397.804530, 1403.501624, 1409.202067, 1414.905850, 1420.612960, 1426.323387, 1432.037120, + 1437.754148, 1443.474460, 1449.198045, 1454.924892, 1460.654992, 1466.388333, 1472.124906, 1477.864699, + 1483.607702, 1489.353905, 1495.103298, 1500.855871, 1506.611613, 1512.370515, 1518.132566, 1523.897757, + 1529.666078, 1535.437519, 1541.212071, 1546.989723, 1552.770467, 1558.554292, 1564.341189, 1570.131149, + 1575.924163, 1581.720221, 1587.519313, 1593.321432, 1599.126567, 1604.934709, 1610.745850, 1616.559981, + 1622.377092, 1628.197175, 1634.020221, 1639.846221, 1645.675166, 1651.507049, 1657.341860, 1663.179590, + 1669.020232, 1674.863776, 1680.710215, 1686.559540, 1692.411742, 1698.266814, 1704.124747, 1709.985533, + 1715.849165, 1721.715633, 1727.584930, 1733.457047, 1739.331978, 1745.209714, 1751.090247, 1756.973569, + 1762.859673, 1768.748551, 1774.640196, 1780.534598, 1786.431752, 1792.331650, 1798.234283, 1804.139645, + 1810.047728, 1815.958524, 1821.872027, 1827.788229, 1833.707123, 1839.628702, 1845.552957, 1851.479884, + 1857.409473, 1863.341718, 1869.276612, 1875.214148, 1881.154319, 1887.097119, 1893.042539, 1898.990574, + 1904.941217, 1910.894460, 1916.850298, 1922.808722, 1928.769728, 1934.733307, 1940.699454, 1946.668161, + 1952.639423, 1958.613233, 1964.589584, 1970.568470, 1976.549884, 1982.533820, 1988.520272, 1994.509233, + 2000.500698, 2006.494659, 2012.491111, 2018.490048, 2024.491463, 2030.495350, 2036.501703, 2042.510516, + 2048.521784, 2054.535499, 2060.551656, 2066.570249, 2072.591272, 2078.614720, 2084.640586, 2090.668864, + 2096.699550, 2102.732636, 2108.768117, 2114.805988, 2120.846243, 2126.888876, 2132.933881, 2138.981253, + 2145.030987, 2151.083076, 2157.137515, 2163.194299, 2169.253423, 2175.314879, 2181.378665, 2187.444773, + 2193.513198, 2199.583936, 2205.656981, 2211.732327, 2217.809969, 2223.889902, 2229.972121, 2236.056620, + 2242.143395, 2248.232440, 2254.323750, 2260.417320, 2266.513144, 2272.611219, 2278.711537, 2284.814096, + 2290.918889, 2297.025912, 2303.135160, 2309.246627, 2315.360309, 2321.476201, 2327.594299, 2333.714596, + 2339.837089, 2345.961772, 2352.088641, 2358.217692, 2364.348918, 2370.482316, 2376.617881, 2382.755608, + 2388.895493, 2395.037530, 2401.181716, 2407.328045, 2413.476513, 2419.627116, 2425.779849, 2431.934707, + 2438.091686, 2444.250781, 2450.411988, 2456.575303, 2462.740721, 2468.908238, 2475.077848, 2481.249549, + 2487.423335, 2493.599202, 2499.777146, 2505.957163, 2512.139248, 2518.323397, 2524.509606, 2530.697870, + 2536.888185, 2543.080548, 2549.274953, 2555.471397, 2561.669876, 2567.870385, 2574.072920, 2580.277478, + 2586.484054, 2592.692644, 2598.903244, 2605.115850, 2611.330458, 2617.547065, 2623.765665, 2629.986255, + 2636.208831, 2642.433390, 2648.659926, 2654.888437, 2661.118919, 2667.351367, 2673.585777, 2679.822147, + 2686.060472, 2692.300747, 2698.542971, 2704.787138, 2711.033244, 2717.281287, 2723.531263, 2729.783166, + 2736.036995, 2742.292745, 2748.550413, 2754.809994, 2761.071486, 2767.334884, 2773.600185, 2779.867386, + 2786.136482, 2792.407471, 2798.680348, 2804.955110, 2811.231753, 2817.510275, 2823.790671, 2830.072937, + 2836.357071, 2842.643070, 2848.930928, 2855.220644, 2861.512213, 2867.805632, 2874.100898, 2880.398007, + 2886.696957, 2892.997742, 2899.300361, 2905.604810, 2911.911085, 2918.219184, 2924.529102, 2930.840837, + 2937.154385, 2943.469743, 2949.786908, 2956.105876, 2962.426644, 2968.749209, 2975.073568, 2981.399718, + 2987.727655, 2994.057376, 3000.388877, 3006.722157, 3013.057211, 3019.394037, 3025.732631, 3032.072990, + 3038.415112, 3044.758992, 3051.104629, 3057.452018, 3063.801157, 3070.152043, 3076.504672, 3082.859042, + 3089.215150, 3095.572992, 3101.932566, 3108.293868, 3114.656896, 3121.021647, 3127.388118, 3133.756305, + 3140.126206, 3146.497818, 3152.871137, 3159.246162, 3165.622889, 3172.001315, 3178.381438, 3184.763254, + 3191.146760, 3197.531955, 3203.918834, 3210.307396, 3216.697636, 3223.089553, 3229.483144, 3235.878406, + 3242.275335, 3248.673930, 3255.074188, 3261.476105, 3267.879679, 3274.284908, 3280.691788, 3287.100316, + 3293.510491, 3299.922310, 3306.335768, 3312.750865, 3319.167598, 3325.585963, 3332.005958, 3338.427580, + 3344.850827, 3351.275696, 3357.702184, 3364.130290, 3370.560009, 3376.991340, 3383.424280, 3389.858827, + 3396.294977, 3402.732729, 3409.172079, 3415.613026, 3422.055566, 3428.499697, 3434.945417, 3441.392723, + 3447.841612, 3454.292083, 3460.744132, 3467.197757, 3473.652955, 3480.109725, 3486.568063, 3493.027968, + 3499.489436, 3505.952465, 3512.417053, 3518.883198, 3525.350897, 3531.820147, 3538.290947, 3544.763293, + 3551.237184, 3557.712616, 3564.189589, 3570.668098, 3577.148143, 3583.629720, 3590.112827, 3596.597463, + 3603.083624, 3609.571308, 3616.060512, 3622.551236, 3629.043476, 3635.537230, 3642.032495, 3648.529270, + 3655.027552, 3661.527339, 3668.028629, 3674.531419, 3681.035707, 3687.541491, 3694.048769, 3700.557538, + 3707.067797, 3713.579542, 3720.092772, 3726.607485, 3733.123678, 3739.641349, 3746.160496, 3752.681117, + 3759.203210, 3765.726773, 3772.251802, 3778.778297, 3785.306255, 3791.835674, 3798.366551, 3804.898886, + 3811.432675, 3817.967916, 3824.504607, 3831.042747, 3837.582333, 3844.123363, 3850.665835, 3857.209747, + 3863.755097, 3870.301882, 3876.850101, 3883.399752, 3889.950832, 3896.503340, 3903.057274, 3909.612630, + 3916.169409, 3922.727607, 3929.287222, 3935.848253, 3942.410697, 3948.974552, 3955.539817, 3962.106490, + 3968.674567, 3975.244049, 3981.814932, 3988.387214, 3994.960895, 4001.535970, 4008.112440, 4014.690301, + 4021.269553, 4027.850192, 4034.432217, 4041.015626, 4047.600417, 4054.186589, 4060.774139, 4067.363066, + 4073.953367, 4080.545040, 4087.138085, 4093.732498, 4100.328279, 4106.925425, 4113.523934, 4120.123804, + 4126.725034, 4133.327622, 4139.931566, 4146.536864, 4153.143514, 4159.751515, 4166.360864, 4172.971560, + 4179.583601, 4186.196985, 4192.811711, 4199.427776, 4206.045179, 4212.663918, 4219.283991, 4225.905397, + 4232.528133, 4239.152198, 4245.777591, 4252.404308, 4259.032350, 4265.661713, 4272.292396, 4278.924398, + 4285.557717, 4292.192350, 4298.828297, 4305.465555, 4312.104122, 4318.743998, 4325.385180, 4332.027667, + 4338.671457, 4345.316548, 4351.962938, 4358.610627, 4365.259611, 4371.909890, 4378.561462, 4385.214325, + 4391.868478, 4398.523918, 4405.180645, 4411.838656, 4418.497950, 4425.158525, 4431.820380, 4438.483512, + 4445.147921, 4451.813605, 4458.480562, 4465.148790, 4471.818288, 4478.489054, 4485.161087, 4491.834385, + 4498.508947, 4505.184770, 4511.861853, 4518.540196, 4525.219795, 4531.900649, 4538.582758, 4545.266119, + 4551.950731, 4558.636592, 4565.323700, 4572.012055, 4578.701654, 4585.392497, 4592.084580, 4598.777904, + 4605.472466, 4612.168265, 4618.865299, 4625.563567, 4632.263068, 4638.963799, 4645.665759, 4652.368947, + 4659.073361, 4665.779001, 4672.485863, 4679.193947, 4685.903251, 4692.613774, 4699.325515, 4706.038471, + 4712.752642, 4719.468025, 4726.184620, 4732.902424, 4739.621438, 4746.341658, 4753.063083, 4759.785713, + 4766.509546, 4773.234579, 4779.960813, 4786.688244, 4793.416873, 4800.146697, 4806.877715, 4813.609926, + 4820.343328, 4827.077919, 4833.813700, 4840.550666, 4847.288819, 4854.028156, 4860.768675, 4867.510376, + 4874.253256, 4880.997315, 4887.742552, 4894.488964, 4901.236550, 4907.985310, 4914.735241, 4921.486343, + 4928.238613, 4934.992051, 4941.746655, 4948.502424, 4955.259356, 4962.017451, 4968.776706, 4975.537121, + 4982.298694, 4989.061423, 4995.825308, 5002.590347, 5009.356539, 5016.123882, 5022.892375, 5029.662017, + 5036.432806, 5043.204742, 5049.977822, 5056.752046, 5063.527412, 5070.303919, 5077.081566, 5083.860351, + 5090.640273, 5097.421330, 5104.203522, 5110.986848, 5117.771305, 5124.556892, 5131.343609, 5138.131454, + 5144.920426, 5151.710523, 5158.501745, 5165.294089, 5172.087555, 5178.882142, 5185.677848, 5192.474671, + 5199.272612, 5206.071668, 5212.871838, 5219.673121, 5226.475515, 5233.279021, 5240.083635, 5246.889358, + 5253.696187, 5260.504122, 5267.313161, 5274.123304, 5280.934548, 5287.746893, 5294.560338, 5301.374881, + 5308.190521, 5315.007257, 5321.825087, 5328.644011, 5335.464028, 5342.285135, 5349.107333, 5355.930619, + 5362.754992, 5369.580452, 5376.406998, 5383.234627, 5390.063339, 5396.893133, 5403.724007, 5410.555960, + 5417.388992, 5424.223101, 5431.058286, 5437.894545, 5444.731878, 5451.570283, 5458.409759, 5465.250306, + 5472.091921, 5478.934605, 5485.778355, 5492.623170, 5499.469050, 5506.315993, 5513.163998, 5520.013065, + 5526.863191, 5533.714376, 5540.566618, 5547.419917, 5554.274272, 5561.129681, 5567.986143, 5574.843657, + 5581.702222, 5588.561837, 5595.422500, 5602.284212, 5609.146970, 5616.010773, 5622.875621, 5629.741512, + 5636.608445, 5643.476419, 5650.345434, 5657.215487, 5664.086579, 5670.958707, 5677.831871, 5684.706069, + 5691.581301, 5698.457566, 5705.334862, 5712.213188, 5719.092544, 5725.972928, 5732.854339, 5739.736777, + 5746.620240, 5753.504726, 5760.390236, 5767.276768, 5774.164320, 5781.052893, 5787.942484, 5794.833093, + 5801.724719, 5808.617361, 5815.511017, 5822.405687, 5829.301370, 5836.198064, 5843.095769, 5849.994483, + 5856.894207, 5863.794937, 5870.696674, 5877.599417, 5884.503164, 5891.407915, 5898.313668, 5905.220423, + 5912.128178, 5919.036933, 5925.946687, 5932.857437, 5939.769185, 5946.681927, 5953.595665, 5960.510396, + 5967.426119, 5974.342834, 5981.260540, 5988.179235, 5995.098919, 6002.019590, 6008.941249, 6015.863892, + 6022.787521, 6029.712133, 6036.637729, 6043.564306, 6050.491864, 6057.420401, 6064.349918, 6071.280413, + 6078.211885, 6085.144333, 6092.077756, 6099.012153, 6105.947523, 6112.883866, 6119.821180, 6126.759465, + 6133.698719, 6140.638941, 6147.580131, 6154.522288, 6161.465410, 6168.409497, 6175.354548, 6182.300562, + 6189.247538, 6196.195476, 6203.144373, 6210.094229, 6217.045044, 6223.996816, 6230.949545, 6237.903229, + 6244.857868, 6251.813460, 6258.770006, 6265.727503, 6272.685952, 6279.645350, 6286.605698, 6293.566994, + 6300.529237, 6307.492427, 6314.456563, 6321.421643, 6328.387668, 6335.354635, 6342.322544, 6349.291394, + 6356.261185, 6363.231915, 6370.203584, 6377.176190, 6384.149733, 6391.124212, 6398.099626, 6405.075974, + 6412.053255, 6419.031469, 6426.010614, 6432.990690, 6439.971696, 6446.953631, 6453.936493, 6460.920283, + 6467.905000, 6474.890641, 6481.877208, 6488.864698, 6495.853111, 6502.842447, 6509.832703, 6516.823880, + 6523.815976, 6530.808991, 6537.802924, 6544.797774, 6551.793541, 6558.790222, 6565.787818, 6572.786328, + 6579.785750, 6586.786085, 6593.787330, 6600.789486, 6607.792552, 6614.796526, 6621.801408, 6628.807197, + 6635.813892, 6642.821493, 6649.829998, 6656.839407, 6663.849719, 6670.860933, 6677.873048, 6684.886064, + 6691.899979, 6698.914794, 6705.930506, 6712.947116, 6719.964622, 6726.983024, 6734.002320, 6741.022511, + 6748.043595, 6755.065571, 6762.088439, 6769.112198, 6776.136847, 6783.162386, 6790.188813, 6797.216127, + 6804.244328, 6811.273416, 6818.303389, 6825.334246, 6832.365988, 6839.398612, 6846.432118, 6853.466506, + 6860.501775, 6867.537923, 6874.574951, 6881.612857, 6888.651641, 6895.691301, 6902.731837, 6909.773249, + 6916.815535, 6923.858695, 6930.902728, 6937.947633, 6944.993410, 6952.040057, 6959.087574, 6966.135961, + 6973.185215, 6980.235338, 6987.286327, 6994.338183, 7001.390904, 7008.444490, 7015.498939, 7022.554252, + 7029.610428, 7036.667465, 7043.725362, 7050.784121, 7057.843738, 7064.904215, 7071.965549, 7079.027741, + 7086.090789, 7093.154693, 7100.219452, 7107.285065, 7114.351532, 7121.418852, 7128.487024, 7135.556047, + 7142.625922, 7149.696646, 7156.768219, 7163.840641, 7170.913911, 7177.988027, 7185.062991, 7192.138799, + 7199.215453, 7206.292951, 7213.371293, 7220.450477, 7227.530504, 7234.611372, 7241.693080, 7248.775629, + 7255.859017, 7262.943243, 7270.028307, 7277.114209, 7284.200947, 7291.288521, 7298.376929, 7305.466172, + 7312.556249, 7319.647159, 7326.738901, 7333.831475, 7340.924880, 7348.019114, 7355.114179, 7362.210072, + 7369.306793, 7376.404342, 7383.502718, 7390.601920, 7397.701947, 7404.802799, 7411.904475, 7419.006974, + 7426.110296, 7433.214440, 7440.319406, 7447.425192, 7454.531798, 7461.639223, 7468.747468, 7475.856530, + 7482.966409, 7490.077105, 7497.188617, 7504.300945, 7511.414087, 7518.528043, 7525.642812, 7532.758395, + 7539.874789, 7546.991994, 7554.110010, 7561.228837, 7568.348472, 7575.468917, 7582.590169, 7589.712229, + 7596.835096, 7603.958769, 7611.083247, 7618.208530, 7625.334617, 7632.461508, 7639.589202, 7646.717698, + 7653.846995, 7660.977094, 7668.107992, 7675.239691, 7682.372189, 7689.505485, 7696.639578, 7703.774469, + 7710.910156, 7718.046640, 7725.183918, 7732.321991, 7739.460858, 7746.600518, 7753.740971, 7760.882217, + 7768.024253, 7775.167081, 7782.310698, 7789.455105, 7796.600301, 7803.746286, 7810.893058, 7818.040617, + 7825.188963, 7832.338095, 7839.488012, 7846.638713, 7853.790199, 7860.942467, 7868.095519, 7875.249353, + 7882.403968, 7889.559364, 7896.715541, 7903.872497, 7911.030233, 7918.188747, 7925.348039, 7932.508108, + 7939.668954, 7946.830576, 7953.992973, 7961.156146, 7968.320093, 7975.484813, 7982.650306, 7989.816572, + 7996.983610, 8004.151419, 8011.319999, 8018.489349, 8025.659469, 8032.830357, 8040.002014, 8047.174439, + 8054.347631, 8061.521589, 8068.696313, 8075.871803, 8083.048057, 8090.225076, 8097.402859, 8104.581404, + 8111.760712, 8118.940782, 8126.121613, 8133.303205, 8140.485557, 8147.668669, 8154.852540, 8162.037169, + 8169.222556, 8176.408700, 8183.595601, 8190.783258, 8197.971671, 8205.160839, 8212.350761, 8219.541437, + 8226.732866, 8233.925048, 8241.117983, 8248.311668, 8255.506105, 8262.701293, 8269.897230, 8277.093916, + 8284.291352, 8291.489535, 8298.688466, 8305.888145, 8313.088570, 8320.289741, 8327.491657, 8334.694318, + 8341.897724, 8349.101873, 8356.306765, 8363.512401, 8370.718778, 8377.925897, 8385.133757, 8392.342357, + 8399.551697, 8406.761777, 8413.972595, 8421.184152, 8428.396447, 8435.609478, 8442.823246, 8450.037751, + 8457.252991, 8464.468966, 8471.685675, 8478.903119, 8486.121296, 8493.340205, 8500.559847, 8507.780221, + 8515.001326, 8522.223162, 8529.445728, 8536.669024, 8543.893049, 8551.117802, 8558.343284, 8565.569493, + 8572.796429, 8580.024091, 8587.252480, 8594.481593, 8601.711432, 8608.941995, 8616.173282, 8623.405293, + 8630.638026, 8637.871481, 8645.105658, 8652.340557, 8659.576176, 8666.812515, 8674.049574, 8681.287353, + 8688.525849, 8695.765064, 8703.004997, 8710.245647, 8717.487013, 8724.729095, 8731.971893, 8739.215406, + 8746.459634, 8753.704575, 8760.950230, 8768.196598, 8775.443679, 8782.691472, 8789.939976, 8797.189191, + 8804.439116, 8811.689752, 8818.941097, 8826.193151, 8833.445913, 8840.699383, 8847.953561, 8855.208446, + 8862.464037, 8869.720335, 8876.977337, 8884.235045, 8891.493457, 8898.752573, 8906.012393, 8913.272915, + 8920.534141, 8927.796068, 8935.058696, 8942.322026, 8949.586056, 8956.850786, 8964.116216, 8971.382345, + 8978.649172, 8985.916697, 8993.184920, 9000.453841, 9007.723457, 9014.993770, 9022.264779, 9029.536483, + 9036.808881, 9044.081973, 9051.355760, 9058.630239, 9065.905412, 9073.181276, 9080.457833, 9087.735080, + 9095.013019, 9102.291648, 9109.570967, 9116.850975, 9124.131672, 9131.413058, 9138.695132, 9145.977893, + 9153.261341, 9160.545476, 9167.830297, 9175.115803, 9182.401995, 9189.688871, 9196.976432, 9204.264676, + 9211.553604, 9218.843215, 9226.133507, 9233.424482, 9240.716138, 9248.008476, 9255.301493, 9262.595191, + 9269.889568, 9277.184625, 9284.480360, 9291.776773, 9299.073864, 9306.371632, 9313.670077, 9320.969199, + 9328.268996, 9335.569469, 9342.870617, 9350.172439, 9357.474936, 9364.778106, 9372.081949, 9379.386465, + 9386.691653, 9393.997513, 9401.304045, 9408.611247, 9415.919120, 9423.227662, 9430.536875, 9437.846756, + 9445.157306, 9452.468525, 9459.780411, 9467.092965, 9474.406185, 9481.720072, 9489.034625, 9496.349843, + 9503.665726, 9510.982275, 9518.299487, 9525.617363, 9532.935903, 9540.255105, 9547.574970, 9554.895497, + 9562.216686, 9569.538535, 9576.861046, 9584.184217, 9591.508047, 9598.832537, 9606.157686, 9613.483494, + 9620.809959, 9628.137082, 9635.464863, 9642.793300, 9650.122394, 9657.452144, 9664.782549, 9672.113609, + 9679.445324, 9686.777694, 9694.110717, 9701.444393, 9708.778722, 9716.113704, 9723.449338, 9730.785624, + 9738.122561, 9745.460148, 9752.798387, 9760.137275, 9767.476812, 9774.816999, 9782.157835, 9789.499319, + 9796.841450, 9804.184230, 9811.527656, 9818.871729, 9826.216448, 9833.561813, 9840.907823, 9848.254478, + 9855.601778, 9862.949721, 9870.298309, 9877.647540, 9884.997414, 9892.347930, 9899.699088, 9907.050888, + 9914.403329, 9921.756411, 9929.110133, 9936.464495, 9943.819497, 9951.175138, 9958.531418, 9965.888337, + 9973.245893, 9980.604087, 9987.962917, 9995.322385, 10002.682489, 10010.043229, 10017.404604, 10024.766615, + 10032.129260, 10039.492540, 10046.856453, 10054.221000, 10061.586180, 10068.951993, 10076.318438, 10083.685515, + 10091.053224, 10098.421564, 10105.790534, 10113.160135, 10120.530366, 10127.901226, 10135.272715, 10142.644833, + 10150.017579, 10157.390954, 10164.764956, 10172.139585, 10179.514840, 10186.890722, 10194.267231, 10201.644364, + 10209.022123, 10216.400507, 10223.779515, 10231.159147, 10238.539403, 10245.920282, 10253.301784, 10260.683908, + 10268.066655, 10275.450023, 10282.834012, 10290.218623, 10297.603854, 10304.989705, 10312.376176, 10319.763266, + 10327.150975, 10334.539303, 10341.928249, 10349.317813, 10356.707994, 10364.098793, 10371.490208, 10378.882240, + 10386.274887, 10393.668150, 10401.062029, 10408.456522, 10415.851629, 10423.247351, 10430.643686, 10438.040635, + 10445.438196, 10452.836370, 10460.235157, 10467.634555, 10475.034564, 10482.435185, 10489.836416, 10497.238258, + 10504.640709, 10512.043770, 10519.447441, 10526.851720, 10534.256607, 10541.662103, 10549.068206, 10556.474917, + 10563.882235, 10571.290159, 10578.698690, 10586.107826, 10593.517568, 10600.927915, 10608.338867, 10615.750423, + 10623.162584, 10630.575348, 10637.988715, 10645.402685, 10652.817258, 10660.232433, 10667.648210, 10675.064589, + 10682.481568, 10689.899149, 10697.317330, 10704.736111, 10712.155491, 10719.575471, 10726.996050, 10734.417227, + 10741.839003, 10749.261377, 10756.684348, 10764.107917, 10771.532082, 10778.956844, 10786.382202, 10793.808155, + 10801.234704, 10808.661848, 10816.089587, 10823.517920, 10830.946848, 10838.376369, 10845.806483, 10853.237190, + 10860.668489, 10868.100381, 10875.532865, 10882.965940, 10890.399607, 10897.833864, 10905.268712, 10912.704150, + 10920.140178, 10927.576795, 10935.014002, 10942.451797, 10949.890180, 10957.329152, 10964.768711, 10972.208858, + 10979.649592, 10987.090912, 10994.532819, 11001.975312, 11009.418390, 11016.862054, 11024.306302, 11031.751136, + 11039.196553, 11046.642555, 11054.089140, 11061.536308, 11068.984059, 11076.432393, 11083.881309, 11091.330807, + 11098.780887, 11106.231548, 11113.682789, 11121.134612, 11128.587014, 11136.039996, 11143.493558, 11150.947699, + 11158.402419, 11165.857718, 11173.313594, 11180.770049, 11188.227081, 11195.684690, 11203.142876, 11210.601639, + 11218.060978, 11225.520893, 11232.981383, 11240.442449, 11247.904089, 11255.366304, 11262.829093, 11270.292456, + 11277.756393, 11285.220903, 11292.685985, 11300.151641, 11307.617868, 11315.084668, 11322.552039, 11330.019981, + 11337.488494, 11344.957578, 11352.427232, 11359.897457, 11367.368250, 11374.839613, 11382.311546, 11389.784046, + 11397.257115, 11404.730752, 11412.204957, 11419.679729, 11427.155069, 11434.630975, 11442.107447, 11449.584486, + 11457.062090, 11464.540259, 11472.018994, 11479.498294, 11486.978158, 11494.458586, 11501.939579, 11509.421134, + 11516.903253, 11524.385935, 11531.869179, 11539.352986, 11546.837355, 11554.322285, 11561.807777, 11569.293829, + 11576.780443, 11584.267616, 11591.755350, 11599.243644, 11606.732496, 11614.221909, 11621.711879, 11629.202409, + 11636.693496, 11644.185142, 11651.677345, 11659.170105, 11666.663423, 11674.157296, 11681.651727, 11689.146713, + 11696.642255, 11704.138352, 11711.635005, 11719.132212, 11726.629974, 11734.128289, 11741.627159, 11749.126582, + 11756.626559, 11764.127088, 11771.628171, 11779.129805, 11786.631991, 11794.134730, 11801.638019, 11809.141860, + 11816.646252, 11824.151194, 11831.656686, 11839.162728, 11846.669320, 11854.176461, 11861.684151, 11869.192390, + 11876.701177, 11884.210512, 11891.720395, 11899.230826, 11906.741804, 11914.253328, 11921.765400, 11929.278017, + 11936.791181, 11944.304890, 11951.819145, 11959.333944, 11966.849289, 11974.365178, 11981.881611, 11989.398589, + 11996.916109, 12004.434174, 12011.952781, 12019.471931, 12026.991623, 12034.511858, 12042.032634, 12049.553952, + 12057.075811, 12064.598212, 12072.121152, 12079.644634, 12087.168655, 12094.693216, 12102.218317, 12109.743957, + 12117.270136, 12124.796854, 12132.324110, 12139.851904, 12147.380235, 12154.909105, 12162.438511, 12169.968454, + 12177.498934, 12185.029951, 12192.561503, 12200.093591, 12207.626215, 12215.159374, 12222.693067, 12230.227296, + 12237.762058, 12245.297355, 12252.833186, 12260.369549, 12267.906447, 12275.443877, 12282.981839, 12290.520334, + 12298.059361, 12305.598920, 12313.139010, 12320.679632, 12328.220784, 12335.762468, 12343.304681, 12350.847425, + 12358.390698, 12365.934501, 12373.478833, 12381.023694, 12388.569084, 12396.115002, 12403.661448, 12411.208422, + 12418.755924, 12426.303953, 12433.852509, 12441.401592, 12448.951201, 12456.501336, 12464.051997, 12471.603184, + 12479.154896, 12486.707134, 12494.259896, 12501.813182, 12509.366993, 12516.921328, 12524.476187, 12532.031569, + 12539.587474, 12547.143902, 12554.700852, 12562.258325, 12569.816320, 12577.374837, 12584.933875, 12592.493435, + 12600.053515, 12607.614116, 12615.175238, 12622.736880, 12630.299041, 12637.861722, 12645.424923, 12652.988643, + 12660.552881, 12668.117638, 12675.682913, 12683.248707, 12690.815018, 12698.381846, 12705.949192, 12713.517054, + 12721.085434, 12728.654329, 12736.223741, 12743.793669, 12751.364112, 12758.935071, 12766.506544, 12774.078533, + 12781.651036, 12789.224053, 12796.797584, 12804.371629, 12811.946188, 12819.521259, 12827.096844, 12834.672941, + 12842.249551, 12849.826673, 12857.404307, 12864.982452, 12872.561109, 12880.140277, 12887.719956, 12895.300146, + 12902.880845, 12910.462055, 12918.043775, 12925.626004, 12933.208742, 12940.791990, 12948.375746, 12955.960011, + 12963.544784, 12971.130065, 12978.715854, 12986.302150, 12993.888954, 13001.476264, 13009.064082, 13016.652405, + 13024.241235, 13031.830571, 13039.420413, 13047.010759, 13054.601612, 13062.192969, 13069.784830, 13077.377196, + 13084.970067, 13092.563441, 13100.157319, 13107.751700, 13115.346584, 13122.941972, 13130.537862, 13138.134254, + 13145.731148, 13153.328545, 13160.926443, 13168.524842, 13176.123742, 13183.723144, 13191.323046, 13198.923448, + 13206.524351, 13214.125753, 13221.727655, 13229.330056, 13236.932957, 13244.536356, 13252.140254, 13259.744650, + 13267.349545, 13274.954937, 13282.560827, 13290.167214, 13297.774099, 13305.381480, 13312.989359, 13320.597733, + 13328.206604, 13335.815970, 13343.425832, 13351.036190, 13358.647043, 13366.258390, 13373.870233, 13381.482570, + 13389.095401, 13396.708726, 13404.322544, 13411.936857, 13419.551662, 13427.166960, 13434.782751, 13442.399035, + 13450.015811, 13457.633079, 13465.250838, 13472.869089, 13480.487832, 13488.107065, 13495.726789, 13503.347004, + 13510.967709, 13518.588904, 13526.210589, 13533.832764, 13541.455428, 13549.078581, 13556.702223, 13564.326353, + 13571.950972, 13579.576080, 13587.201675, 13594.827757, 13602.454328, 13610.081385, 13617.708929, 13625.336960, + 13632.965478, 13640.594482, 13648.223972, 13655.853948, 13663.484409, 13671.115355, 13678.746787, 13686.378704, + 13694.011105, 13701.643990, 13709.277360, 13716.911213, 13724.545551, 13732.180371, 13739.815675, 13747.451462, + 13755.087732, 13762.724484, 13770.361718, 13777.999435, 13785.637633, 13793.276313, 13800.915474, 13808.555116, + 13816.195239, 13823.835843, 13831.476927, 13839.118492, 13846.760536, 13854.403060, 13862.046064, 13869.689547, + 13877.333509, 13884.977950, 13892.622869, 13900.268267, 13907.914143, 13915.560496, 13923.207328, 13930.854637, + 13938.502423, 13946.150686, 13953.799425, 13961.448642, 13969.098334, 13976.748503, 13984.399148, 13992.050268, + 13999.701863, 14007.353934, 14015.006480, 14022.659500, 14030.312995, 14037.966964, 14045.621407, 14053.276325, + 14060.931715, 14068.587579, 14076.243916, 14083.900726, 14091.558009, 14099.215765, 14106.873992, 14114.532692, + 14122.191863, 14129.851506, 14137.511620, 14145.172206, 14152.833262, 14160.494789, 14168.156787, 14175.819255, + 14183.482192, 14191.145600, 14198.809477, 14206.473824, 14214.138640, 14221.803924, 14229.469678, 14237.135900, + 14244.802590, 14252.469748, 14260.137374, 14267.805468, 14275.474029, 14283.143057, 14290.812553, 14298.482515, + 14306.152943, 14313.823838, 14321.495199, 14329.167026, 14336.839318, 14344.512076, 14352.185299, 14359.858987, + 14367.533140, 14375.207758, 14382.882840, 14390.558386, 14398.234396, 14405.910869, 14413.587806, 14421.265207, + 14428.943070, 14436.621397, 14444.300186, 14451.979437, 14459.659151, 14467.339326, 14475.019964, 14482.701063, + 14490.382623, 14498.064645, 14505.747127, 14513.430070, 14521.113474, 14528.797338, 14536.481662, 14544.166446, + 14551.851690, 14559.537393, 14567.223555, 14574.910176, 14582.597256, 14590.284795, 14597.972792, 14605.661248, + 14613.350161, 14621.039532, 14628.729361, 14636.419647, 14644.110390, 14651.801590, 14659.493247, 14667.185360, + 14674.877930, 14682.570956, 14690.264437, 14697.958375, 14705.652767, 14713.347616, 14721.042919, 14728.738677, + 14736.434889, 14744.131556, 14751.828678, 14759.526253, 14767.224282, 14774.922765, 14782.621701, 14790.321091, + 14798.020933, 14805.721228, 14813.421976, 14821.123176, 14828.824829, 14836.526933, 14844.229489, 14851.932497, + 14859.635956, 14867.339866, 14875.044227, 14882.749039, 14890.454302, 14898.160014, 14905.866177, 14913.572790, + 14921.279853, 14928.987365, 14936.695327, 14944.403737, 14952.112597, 14959.821905, 14967.531662, 14975.241867, + 14982.952521, 14990.663622, 14998.375171, 15006.087167, 15013.799611, 15021.512502, 15029.225840, 15036.939625, + 15044.653856, 15052.368533, 15060.083657, 15067.799226, 15075.515242, 15083.231702, 15090.948609, 15098.665960, + 15106.383756, 15114.101997, 15121.820683, 15129.539812, 15137.259386, 15144.979404, 15152.699866, 15160.420771, + 15168.142120, 15175.863912, 15183.586146, 15191.308824, 15199.031944, 15206.755506, 15214.479511, 15222.203958, + 15229.928846, 15237.654176, 15245.379948, 15253.106160, 15260.832814, 15268.559908, 15276.287444, 15284.015419, + 15291.743835, 15299.472691, 15307.201986, 15314.931722, 15322.661897, 15330.392511, 15338.123564, 15345.855056, + 15353.586986, 15361.319356, 15369.052163, 15376.785409, 15384.519092, 15392.253214, 15399.987773, 15407.722769, + 15415.458202, 15423.194072, 15430.930380, 15438.667123, 15446.404303, 15454.141920, 15461.879972, 15469.618460, + 15477.357384, 15485.096743, 15492.836537, 15500.576767, 15508.317431, 15516.058530, 15523.800064, 15531.542032, + 15539.284434, 15547.027270, 15554.770540, 15562.514243, 15570.258380, 15578.002949, 15585.747952, 15593.493388, + 15601.239256, 15608.985557, 15616.732290, 15624.479455, 15632.227051, 15639.975080, 15647.723540, 15655.472431, + 15663.221754, 15670.971507, 15678.721691, 15686.472306, 15694.223351, 15701.974826, 15709.726732, 15717.479067, + 15725.231832, 15732.985026, 15740.738650, 15748.492702, 15756.247184, 15764.002094, 15771.757433, 15779.513200, + 15787.269395, 15795.026019, 15802.783070, 15810.540549, 15818.298455, 15826.056788, 15833.815549, 15841.574736, + 15849.334350, 15857.094391, 15864.854858, 15872.615751, 15880.377070, 15888.138815, 15895.900986, 15903.663582, + 15911.426603, 15919.190050, 15926.953921, 15934.718217, 15942.482938, 15950.248083, 15958.013652, 15965.779645, + 15973.546062, 15981.312902, 15989.080166, 15996.847853, 16004.615964, 16012.384497, 16020.153453, 16027.922832, + 16035.692633, 16043.462856, 16051.233501, 16059.004568, 16066.776057, 16074.547967, 16082.320299, 16090.093052, + 16097.866225, 16105.639820, 16113.413835, 16121.188270, 16128.963126, 16136.738402, 16144.514098, 16152.290213, + 16160.066748, 16167.843703, 16175.621076, 16183.398869, 16191.177080, 16198.955710, 16206.734759, 16214.514226, + 16222.294111, 16230.074414, 16237.855135, 16245.636274, 16253.417830, 16261.199803, 16268.982193, 16276.765000, + 16284.548224, 16292.331865, 16300.115922, 16307.900395, 16315.685285, 16323.470590, 16331.256311, 16339.042447, + 16346.828999, 16354.615966, 16362.403348, 16370.191145, 16377.979356, 16385.767982, 16393.557023, 16401.346477, + 16409.136346, 16416.926628, 16424.717324, 16432.508434, 16440.299957, 16448.091893, 16455.884242, 16463.677003, + 16471.470178, 16479.263764, 16487.057764, 16494.852175, 16502.646998, 16510.442233, 16518.237879, 16526.033937, + 16533.830407, 16541.627287, 16549.424578, 16557.222280, 16565.020393, 16572.818916, 16580.617849, 16588.417193, + 16596.216946, 16604.017109, 16611.817682, 16619.618664, 16627.420055, 16635.221855, 16643.024065, 16650.826683, + 16658.629710, 16666.433145, 16674.236988, 16682.041239, 16689.845899, 16697.650966, 16705.456440, 16713.262322, + 16721.068612, 16728.875308, 16736.682411, 16744.489921, 16752.297838, 16760.106161, 16767.914890, 16775.724026, + 16783.533567, 16791.343514, 16799.153867, 16806.964625, 16814.775788, 16822.587357, 16830.399330, 16838.211708, + 16846.024491, 16853.837678, 16861.651270, 16869.465266, 16877.279665, 16885.094469, 16892.909676, 16900.725286, + 16908.541300, 16916.357717, 16924.174537, 16931.991760, 16939.809385, 16947.627413, 16955.445844, 16963.264676, + 16971.083910, 16978.903547, 16986.723585, 16994.544024, 17002.364865, 17010.186107, 17018.007750, 17025.829794, + 17033.652239, 17041.475084, 17049.298330, 17057.121976, 17064.946022, 17072.770468, 17080.595314, 17088.420559, + 17096.246204, 17104.072248, 17111.898691, 17119.725533, 17127.552774, 17135.380413, 17143.208451, 17151.036888, + 17158.865722, 17166.694955, 17174.524585, 17182.354613, 17190.185039, 17198.015862, 17205.847082, 17213.678699, + 17221.510714, 17229.343124, 17237.175932, 17245.009136, 17252.842736, 17260.676733, 17268.511125, 17276.345913, + 17284.181097, 17292.016676, 17299.852651, 17307.689020, 17315.525785, 17323.362945, 17331.200499, 17339.038448, + 17346.876791, 17354.715529, 17362.554661, 17370.394186, 17378.234105, 17386.074418, 17393.915125, 17401.756225, + 17409.597718, 17417.439604, 17425.281882, 17433.124554, 17440.967618, 17448.811074, 17456.654923, 17464.499164, + 17472.343796, 17480.188821, 17488.034237, 17495.880044, 17503.726243, 17511.572833, 17519.419814, 17527.267186, + 17535.114948, 17542.963101, 17550.811645, 17558.660579, 17566.509902, 17574.359616, 17582.209720, 17590.060213, + 17597.911096, 17605.762368, 17613.614029, 17621.466079, 17629.318518, 17637.171346, 17645.024562, 17652.878167, + 17660.732160, 17668.586541, 17676.441311, 17684.296468, 17692.152012, 17700.007944, 17707.864264, 17715.720971, + 17723.578065, 17731.435545, 17739.293413, 17747.151667, 17755.010308, 17762.869335, 17770.728748, 17778.588547, + 17786.448732, 17794.309303, 17802.170259, 17810.031601, 17817.893328, 17825.755440, 17833.617938, 17841.480820, + 17849.344086, 17857.207738, 17865.071773, 17872.936193, 17880.800997, 17888.666185, 17896.531757, 17904.397712, + 17912.264051, 17920.130774, 17927.997879, 17935.865368, 17943.733239, 17951.601493, 17959.470130, 17967.339150, + 17975.208551, 17983.078335, 17990.948501, 17998.819049, 18006.689979, 18014.561290, 18022.432983, 18030.305056, + 18038.177512, 18046.050348, 18053.923565, 18061.797163, 18069.671141, 18077.545500, 18085.420239, 18093.295358, + 18101.170858, 18109.046737, 18116.922996, 18124.799634, 18132.676652, 18140.554049, 18148.431825, 18156.309981, + 18164.188515, 18172.067428, 18179.946719, 18187.826389, 18195.706438, 18203.586864, 18211.467668, 18219.348850, + 18227.230410, 18235.112348, 18242.994663, 18250.877355, 18258.760424, 18266.643871, 18274.527694, 18282.411894, + 18290.296470, 18298.181423, 18306.066752, 18313.952458, 18321.838539, 18329.724997, 18337.611830, 18345.499038, + 18353.386622, 18361.274582, 18369.162916, 18377.051626, 18384.940710, 18392.830169, 18400.720003, 18408.610211, + 18416.500794, 18424.391750, 18432.283081, 18440.174786, 18448.066864, 18455.959316, 18463.852142, 18471.745341, + 18479.638913, 18487.532858, 18495.427176, 18503.321867, 18511.216930, 18519.112366, 18527.008175, 18534.904355, + 18542.800908, 18550.697833, 18558.595129, 18566.492797, 18574.390837, 18582.289248, 18590.188030, 18598.087184, + 18605.986708, 18613.886604, 18621.786870, 18629.687506, 18637.588513, 18645.489891, 18653.391638, 18661.293756, + 18669.196243, 18677.099100, 18685.002327, 18692.905923, 18700.809889, 18708.714224, 18716.618928, 18724.524001, + 18732.429442, 18740.335253, 18748.241431, 18756.147979, 18764.054894, 18771.962178, 18779.869829, 18787.777849, + 18795.686236, 18803.594991, 18811.504113, 18819.413602, 18827.323459, 18835.233683, 18843.144273, 18851.055231, + 18858.966555, 18866.878245, 18874.790302, 18882.702725, 18890.615515, 18898.528670, 18906.442191, 18914.356077, + 18922.270330, 18930.184947, 18938.099930, 18946.015279, 18953.930992, 18961.847070, 18969.763513, 18977.680320, + 18985.597492, 18993.515029, 19001.432929, 19009.351194, 19017.269823, 19025.188815, 19033.108171, 19041.027891, + 19048.947974, 19056.868421, 19064.789230, 19072.710403, 19080.631939, 19088.553837, 19096.476098, 19104.398722, + 19112.321708, 19120.245056, 19128.168766, 19136.092839, 19144.017273, 19151.942069, 19159.867226, 19167.792745, + 19175.718626, 19183.644867, 19191.571470, 19199.498433, 19207.425758, 19215.353443, 19223.281488, 19231.209894, + 19239.138661, 19247.067787, 19254.997274, 19262.927120, 19270.857326, 19278.787892, 19286.718817, 19294.650102, + 19302.581746, 19310.513749, 19318.446112, 19326.378833, 19334.311912, 19342.245351, 19350.179148, 19358.113303, + 19366.047816, 19373.982688, 19381.917917, 19389.853505, 19397.789450, 19405.725753, 19413.662413, 19421.599430, + 19429.536805, 19437.474537, 19445.412625, 19453.351071, 19461.289873, 19469.229032, 19477.168547, 19485.108419, + 19493.048647, 19500.989230, 19508.930170, 19516.871466, 19524.813117, 19532.755124, 19540.697486, 19548.640204, + 19556.583276, 19564.526704, 19572.470487, 19580.414624, 19588.359116, 19596.303963, 19604.249164, 19612.194720, + 19620.140629, 19628.086893, 19636.033511, 19643.980482, 19651.927807, 19659.875485, 19667.823517, 19675.771903, + 19683.720641, 19691.669733, 19699.619177, 19707.568974, 19715.519124, 19723.469627, 19731.420482, 19739.371689, + 19747.323248, 19755.275159, 19763.227423, 19771.180038, 19779.133005, 19787.086323, 19795.039993, 19802.994014, + 19810.948386, 19818.903109, 19826.858184, 19834.813609, 19842.769385, 19850.725511, 19858.681988, 19866.638815, + 19874.595992, 19882.553520, 19890.511397, 19898.469624, 19906.428201, 19914.387128, 19922.346403, 19930.306029, + 19938.266003, 19946.226327, 19954.187000, 19962.148021, 19970.109391, 19978.071110, 19986.033177, 19993.995593, + 20001.958357, 20009.921469, 20017.884929, 20025.848737, 20033.812893, 20041.777396, 20049.742247, 20057.707445, + 20065.672991, 20073.638884, 20081.605123, 20089.571710, 20097.538644, 20105.505924, 20113.473550, 20121.441524, + 20129.409843, 20137.378509, 20145.347521, 20153.316878, 20161.286582, 20169.256631, 20177.227026, 20185.197767, + 20193.168852, 20201.140283, 20209.112059, 20217.084181, 20225.056647, 20233.029457, 20241.002613, 20248.976113, + 20256.949957, 20264.924146, 20272.898679, 20280.873556, 20288.848776, 20296.824341, 20304.800249, 20312.776501, + 20320.753097, 20328.730036, 20336.707318, 20344.684943, 20352.662911, 20360.641222, 20368.619875, 20376.598872, + 20384.578211, 20392.557892, 20400.537916, 20408.518281, 20416.498989, 20424.480039, 20432.461431, 20440.443164, + 20448.425239, 20456.407655, 20464.390413, 20472.373512, 20480.356952, 20488.340733, 20496.324855, 20504.309317, + 20512.294121, 20520.279265, 20528.264749, 20536.250574, 20544.236739, 20552.223244, 20560.210089, 20568.197273, + 20576.184798, 20584.172662, 20592.160865, 20600.149408, 20608.138291, 20616.127512, 20624.117073, 20632.106972, + 20640.097210, 20648.087787, 20656.078702, 20664.069956, 20672.061549, 20680.053479, 20688.045748, 20696.038354, + 20704.031299, 20712.024581, 20720.018201, 20728.012159, 20736.006454, 20744.001086, 20751.996056, 20759.991362, + 20767.987006, 20775.982986, 20783.979304, 20791.975958, 20799.972948, 20807.970275, 20815.967938, 20823.965937, + 20831.964273, 20839.962944, 20847.961951, 20855.961294, 20863.960973, 20871.960987, 20879.961336, 20887.962021, + 20895.963041, 20903.964396, 20911.966086, 20919.968111, 20927.970470, 20935.973165, 20943.976193, 20951.979556, + 20959.983254, 20967.987285, 20975.991651, 20983.996350, 20992.001384, 21000.006751, 21008.012451, 21016.018485, + 21024.024853, 21032.031554, 21040.038588, 21048.045955, 21056.053655, 21064.061688, 21072.070053, 21080.078752, + 21088.087782, 21096.097145, 21104.106841, 21112.116868, 21120.127228, 21128.137919, 21136.148943, 21144.160298, + 21152.171985, 21160.184003, 21168.196352, 21176.209033, 21184.222045, 21192.235389, 21200.249063, 21208.263068, + 21216.277404, 21224.292070, 21232.307067, 21240.322394, 21248.338052, 21256.354040, 21264.370357, 21272.387005, + 21280.403983, 21288.421291, 21296.438928, 21304.456894, 21312.475191, 21320.493816, 21328.512771, 21336.532055, + 21344.551667, 21352.571609, 21360.591879, 21368.612479, 21376.633406, 21384.654663, 21392.676247, 21400.698160, + 21408.720401, 21416.742970, 21424.765867, 21432.789091, 21440.812644, 21448.836524, 21456.860731, 21464.885266, + 21472.910128, 21480.935317, 21488.960834, 21496.986677, 21505.012847, 21513.039344, 21521.066168, 21529.093318, + 21537.120795, 21545.148597, 21553.176726, 21561.205182, 21569.233963, 21577.263070, 21585.292503, 21593.322261, + 21601.352345, 21609.382755, 21617.413490, 21625.444550, 21633.475935, 21641.507646, 21649.539681, 21657.572041, + 21665.604726, 21673.637736, 21681.671070, 21689.704728, 21697.738711, 21705.773018, 21713.807649, 21721.842604, + 21729.877883, 21737.913485, 21745.949412, 21753.985662, 21762.022235, 21770.059132, 21778.096352, 21786.133895, + 21794.171761, 21802.209950, 21810.248462, 21818.287297, 21826.326455, 21834.365934, 21842.405737, 21850.445862, + 21858.486308, 21866.527077, 21874.568168, 21882.609581, 21890.651316, 21898.693372, 21906.735750, 21914.778450, + 21922.821471, 21930.864813, 21938.908476, 21946.952461, 21954.996766, 21963.041392, 21971.086339, 21979.131607, + 21987.177195, 21995.223104, 22003.269333, 22011.315883, 22019.362752, 22027.409942, 22035.457451, 22043.505281, + 22051.553430, 22059.601898, 22067.650687, 22075.699794, 22083.749222, 22091.798968, 22099.849033, 22107.899418, + 22115.950121, 22124.001143, 22132.052484, 22140.104144, 22148.156122, 22156.208418, 22164.261033, 22172.313966, + 22180.367217, 22188.420787, 22196.474674, 22204.528879, 22212.583401, 22220.638241, 22228.693399, 22236.748874, + 22244.804667, 22252.860776, 22260.917203, 22268.973947, 22277.031008, 22285.088385, 22293.146079, 22301.204090, + 22309.262417, 22317.321061, 22325.380021, 22333.439297, 22341.498890, 22349.558798, 22357.619022, 22365.679562, + 22373.740418, 22381.801589, 22389.863076, 22397.924879, 22405.986996, 22414.049429, 22422.112177, 22430.175240, + 22438.238618, 22446.302310, 22454.366318, 22462.430639, 22470.495276, 22478.560227, 22486.625492, 22494.691071, + 22502.756965, 22510.823173, 22518.889694, 22526.956529, 22535.023678, 22543.091141, 22551.158917, 22559.227007, + 22567.295410, 22575.364126, 22583.433155, 22591.502498, 22599.572153, 22607.642121, 22615.712402, 22623.782996, + 22631.853902, 22639.925120, 22647.996651, 22656.068494, 22664.140650, 22672.213117, 22680.285896, 22688.358988, + 22696.432391, 22704.506105, 22712.580131, 22720.654469, 22728.729118, 22736.804078, 22744.879350, 22752.954933, + 22761.030826, 22769.107031, 22777.183546, 22785.260372, 22793.337509, 22801.414956, 22809.492714, 22817.570781, + 22825.649160, 22833.727848, 22841.806846, 22849.886154, 22857.965772, 22866.045700, 22874.125937, 22882.206484, + 22890.287341, 22898.368507, 22906.449982, 22914.531766, 22922.613859, 22930.696261, 22938.778972, 22946.861992, + 22954.945321, 22963.028958, 22971.112904, 22979.197158, 22987.281720, 22995.366591, 23003.451770, 23011.537257, + 23019.623051, 23027.709154, 23035.795564, 23043.882282, 23051.969308, 23060.056640, 23068.144281, 23076.232228, + 23084.320483, 23092.409045, 23100.497914, 23108.587089, 23116.676572, 23124.766361, 23132.856457, 23140.946859, + 23149.037568, 23157.128583, 23165.219904, 23173.311531, 23181.403465, 23189.495704, 23197.588250, 23205.681101, + 23213.774257, 23221.867720, 23229.961487, 23238.055560, 23246.149939, 23254.244623, 23262.339611, 23270.434905, + 23278.530504, 23286.626407, 23294.722616, 23302.819129, 23310.915946, 23319.013068, 23327.110494, 23335.208225, + 23343.306260, 23351.404598, 23359.503241, 23367.602188, 23375.701439, 23383.800993, 23391.900851, 23400.001012, + 23408.101477, 23416.202245, 23424.303317, 23432.404692, 23440.506369, 23448.608350, 23456.710634, 23464.813220, + 23472.916109, 23481.019301, 23489.122795, 23497.226592, 23505.330691, 23513.435092, 23521.539796, 23529.644801, + 23537.750109, 23545.855718, 23553.961629, 23562.067842, 23570.174357, 23578.281173, 23586.388290, 23594.495709, + 23602.603429, 23610.711450, 23618.819773, 23626.928396, 23635.037320, 23643.146545, 23651.256071, 23659.365897, + 23667.476024, 23675.586451, 23683.697179, 23691.808206, 23699.919534, 23708.031163, 23716.143091, 23724.255319, + 23732.367846, 23740.480674, 23748.593801, 23756.707228, 23764.820954, 23772.934979, 23781.049304, 23789.163928, + 23797.278851, 23805.394073, 23813.509594, 23821.625413, 23829.741532, 23837.857949, 23845.974664, 23854.091678, + 23862.208991, 23870.326602, 23878.444511, 23886.562718, 23894.681223, 23902.800026, 23910.919127, 23919.038525, + 23927.158221, 23935.278215, 23943.398507, 23951.519095, 23959.639981, 23967.761165, 23975.882645, 23984.004422, + 23992.126497, 24000.248868, 24008.371536, 24016.494501, 24024.617762, 24032.741320, 24040.865174, 24048.989325, + 24057.113772, 24065.238515, 24073.363554, 24081.488889, 24089.614520, 24097.740447, 24105.866669, 24113.993187, + 24122.120001, 24130.247110, 24138.374515, 24146.502215, 24154.630210, 24162.758500, 24170.887085, 24179.015965, + 24187.145140, 24195.274610, 24203.404374, 24211.534433, 24219.664787, 24227.795435, 24235.926377, 24244.057614, + 24252.189144, 24260.320969, 24268.453088, 24276.585501, 24284.718207, 24292.851207, 24300.984501, 24309.118089, + 24317.251970, 24325.386144, 24333.520611, 24341.655372, 24349.790426, 24357.925773, 24366.061413, 24374.197346, + 24382.333571, 24390.470090, 24398.606900, 24406.744004, 24414.881400, 24423.019088, 24431.157068, 24439.295341, + 24447.433906, 24455.572762, 24463.711911, 24471.851352, 24479.991084, 24488.131108, 24496.271423, 24504.412030, + 24512.552929, 24520.694119, 24528.835600, 24536.977372, 24545.119435, 24553.261789, 24561.404435, 24569.547371, + 24577.690597, 24585.834115, 24593.977923, 24602.122021, 24610.266410, 24618.411089, 24626.556059, 24634.701318, + 24642.846868, 24650.992708, 24659.138837, 24667.285256, 24675.431965, 24683.578964, 24691.726252, 24699.873830, + 24708.021697, 24716.169854, 24724.318299, 24732.467034, 24740.616058, 24748.765371, 24756.914973, 24765.064863, + 24773.215042, 24781.365510, 24789.516267, 24797.667312, 24805.818645, 24813.970267, 24822.122177, 24830.274375, + 24838.426861, 24846.579635, 24854.732697, 24862.886046, 24871.039684, 24879.193609, 24887.347822, 24895.502322, + 24903.657110, 24911.812184, 24919.967547, 24928.123196, 24936.279132, 24944.435355, 24952.591866, 24960.748663, + 24968.905746, 24977.063117, 24985.220774, 24993.378717, 25001.536947, 25009.695464, 25017.854266, 25026.013355, + 25034.172730, 25042.332390, 25050.492337, 25058.652569, 25066.813088, 25074.973892, 25083.134981, 25091.296356, + 25099.458017, 25107.619962, 25115.782193, 25123.944710, 25132.107511, 25140.270597, 25148.433969, 25156.597625, + 25164.761566, 25172.925791, 25181.090302, 25189.255097, 25197.420176, 25205.585539, 25213.751187, 25221.917120, + 25230.083336, 25238.249836, 25246.416620, 25254.583689, 25262.751041, 25270.918676, 25279.086596, 25287.254799, + 25295.423285, 25303.592055, 25311.761108, 25319.930444, 25328.100064, 25336.269967, 25344.440152, 25352.610621, + 25360.781372, 25368.952406, 25377.123723, 25385.295323, 25393.467205, 25401.639369, 25409.811816, 25417.984545, + 25426.157556, 25434.330850, 25442.504425, 25450.678283, 25458.852422, 25467.026843, 25475.201546, 25483.376531, + 25491.551797, 25499.727344, 25507.903173, 25516.079284, 25524.255675, 25532.432348, 25540.609302, 25548.786537, + 25556.964053, 25565.141849, 25573.319927, 25581.498285, 25589.676924, 25597.855843, 25606.035043, 25614.214523, + 25622.394284, 25630.574324, 25638.754645, 25646.935246, 25655.116127, 25663.297288, 25671.478729, 25679.660449, + 25687.842449, 25696.024729, 25704.207288, 25712.390127, 25720.573245, 25728.756642, 25736.940319, 25745.124275, + 25753.308510, 25761.493023, 25769.677816, 25777.862887, 25786.048238, 25794.233867, 25802.419774, 25810.605960, + 25818.792424, 25826.979167, 25835.166188, 25843.353488, 25851.541065, 25859.728920, 25867.917054, 25876.105465, + 25884.294154, 25892.483121, 25900.672366, 25908.861888, 25917.051687, 25925.241764, 25933.432119, 25941.622750, + 25949.813659, 25958.004845, 25966.196308, 25974.388048, 25982.580065, 25990.772359, 25998.964930, 26007.157777, + 26015.350900, 26023.544301, 26031.737977, 26039.931930, 26048.126160, 26056.320665, 26064.515447, 26072.710504, + 26080.905838, 26089.101448, 26097.297333, 26105.493494, 26113.689931, 26121.886643, 26130.083631, 26138.280895, + 26146.478434, 26154.676248, 26162.874337, 26171.072701, 26179.271341, 26187.470255, 26195.669444, 26203.868909, + 26212.068648, 26220.268661, 26228.468950, 26236.669512, 26244.870350, 26253.071461, 26261.272847, 26269.474507, + 26277.676442, 26285.878650, 26294.081133, 26302.283889, 26310.486919, 26318.690223, 26326.893801, 26335.097652, + 26343.301777, 26351.506176, 26359.710848, 26367.915793, 26376.121011, 26384.326503, 26392.532267, 26400.738305, + 26408.944616, 26417.151200, 26425.358056, 26433.565185, 26441.772587, 26449.980261, 26458.188208, 26466.396428, + 26474.604919, 26482.813684, 26491.022720, 26499.232028, 26507.441609, 26515.651461, 26523.861586, 26532.071982, + 26540.282650, 26548.493590, 26556.704801, 26564.916284, 26573.128038, 26581.340064, 26589.552361, 26597.764930, + 26605.977769, 26614.190880, 26622.404262, 26630.617914, 26638.831838, 26647.046032, 26655.260498, 26663.475233, + 26671.690240, 26679.905517, 26688.121064, 26696.336882, 26704.552970, 26712.769328, 26720.985957, 26729.202855, + 26737.420024, 26745.637463, 26753.855171, 26762.073149, 26770.291397, 26778.509915, 26786.728702, 26794.947759, + 26803.167085, 26811.386680, 26819.606545, 26827.826679, 26836.047082, 26844.267754, 26852.488695, 26860.709905, + 26868.931384, 26877.153132, 26885.375148, 26893.597433, 26901.819987, 26910.042809, 26918.265900, 26926.489259, + 26934.712886, 26942.936781, 26951.160945, 26959.385376, 26967.610076, 26975.835043, 26984.060279, 26992.285782, + 27000.511553, 27008.737591, 27016.963897, 27025.190470, 27033.417311, 27041.644420, 27049.871795, 27058.099438, + 27066.327348, 27074.555525, 27082.783968, 27091.012679, 27099.241657, 27107.470901, 27115.700412, 27123.930190, + 27132.160234, 27140.390545, 27148.621123, 27156.851966, 27165.083076, 27173.314452, 27181.546094, 27189.778002, + 27198.010177, 27206.242617, 27214.475323, 27222.708295, 27230.941532, 27239.175035, 27247.408804, 27255.642838, + 27263.877138, 27272.111703, 27280.346533, 27288.581629, 27296.816989, 27305.052615, 27313.288506, 27321.524661, + 27329.761082, 27337.997767, 27346.234717, 27354.471932, 27362.709411, 27370.947155, 27379.185163, 27387.423436, + 27395.661973, 27403.900774, 27412.139839, 27420.379169, 27428.618762, 27436.858620, 27445.098741, 27453.339126, + 27461.579775, 27469.820687, 27478.061864, 27486.303303, 27494.545006, 27502.786973, 27511.029203, 27519.271696, + 27527.514452, 27535.757472, 27544.000754, 27552.244300, 27560.488108, 27568.732180, 27576.976514, 27585.221110, + 27593.465970, 27601.711092, 27609.956476, 27618.202123, 27626.448032, 27634.694204, 27642.940638, 27651.187334, + 27659.434292, 27667.681512, 27675.928994, 27684.176738, 27692.424743, 27700.673011, 27708.921540, 27717.170331, + 27725.419383, 27733.668697, 27741.918272, 27750.168108, 27758.418206, 27766.668565, 27774.919185, 27783.170066, + 27791.421208, 27799.672611, 27807.924275, 27816.176200, 27824.428385, 27832.680832, 27840.933538, 27849.186505, + 27857.439733, 27865.693221, 27873.946969, 27882.200978, 27890.455247, 27898.709776, 27906.964565, 27915.219614, + 27923.474922, 27931.730491, 27939.986319, 27948.242408, 27956.498755, 27964.755363, 27973.012230, 27981.269356, + 27989.526741, 27997.784386, 28006.042291, 28014.300454, 28022.558876, 28030.817558, 28039.076498, 28047.335698, + 28055.595156, 28063.854873, 28072.114849, 28080.375083, 28088.635576, 28096.896327, 28105.157337, 28113.418605, + 28121.680131, 28129.941916, 28138.203959, 28146.466260, 28154.728819, 28162.991636, 28171.254711, 28179.518043, + 28187.781634, 28196.045482, 28204.309588, 28212.573951, 28220.838572, 28229.103450, 28237.368586, 28245.633979, + 28253.899629, 28262.165536, 28270.431701, 28278.698122, 28286.964801, 28295.231736, 28303.498928, 28311.766377, + 28320.034083, 28328.302045, 28336.570264, 28344.838739, 28353.107471, 28361.376459, 28369.645704, 28377.915205, + 28386.184962, 28394.454975, 28402.725244, 28410.995769, 28419.266550, 28427.537587, 28435.808879, 28444.080428, + 28452.352232, 28460.624291, 28468.896606, 28477.169177, 28485.442003, 28493.715084, 28501.988421, 28510.262013, + 28518.535860, 28526.809962, 28535.084319, 28543.358931, 28551.633798, 28559.908919, 28568.184296, 28576.459927, + 28584.735812, 28593.011952, 28601.288347, 28609.564996, 28617.841900, 28626.119058, 28634.396470, 28642.674136, + 28650.952056, 28659.230230, 28667.508659, 28675.787341, 28684.066277, 28692.345466, 28700.624910, 28708.904607, + 28717.184558, 28725.464762, 28733.745220, 28742.025931, 28750.306895, 28758.588113, 28766.869584, 28775.151308, + 28783.433285, 28791.715515, 28799.997998, 28808.280734, 28816.563722, 28824.846964, 28833.130458, 28841.414205, + 28849.698204, 28857.982456, 28866.266960, 28874.551717, 28882.836726, 28891.121987, 28899.407500, 28907.693265, + 28915.979283, 28924.265552, 28932.552074, 28940.838847, 28949.125872, 28957.413149, 28965.700677, 28973.988457, + 28982.276489, 28990.564772, 28998.853306, 29007.142092, 29015.431129, 29023.720417, 29032.009957, 29040.299748, + 29048.589789, 29056.880082, 29065.170625, 29073.461420, 29081.752465, 29090.043761, 29098.335307, 29106.627104, + 29114.919152, 29123.211450, 29131.503998, 29139.796797, 29148.089846, 29156.383146, 29164.676695, 29172.970495, + 29181.264545, 29189.558844, 29197.853394, 29206.148193, 29214.443242, 29222.738541, 29231.034090, 29239.329888, + 29247.625935, 29255.922232, 29264.218779, 29272.515575, 29280.812620, 29289.109914, 29297.407458, 29305.705251, + 29314.003292, 29322.301583, 29330.600122, 29338.898911, 29347.197948, 29355.497234, 29363.796768, 29372.096552, + 29380.396583, 29388.696863, 29396.997392, 29405.298169, 29413.599194, 29421.900468, 29430.201989, 29438.503759, + 29446.805777, 29455.108043, 29463.410557, 29471.713318, 29480.016327, 29488.319585, 29496.623089, 29504.926842, + 29513.230842, 29521.535089, 29529.839584, 29538.144326, 29546.449316, 29554.754553, 29563.060037, 29571.365768, + 29579.671746, 29587.977971, 29596.284444, 29604.591163, 29612.898129, 29621.205341, 29629.512800, 29637.820506, + 29646.128459, 29654.436658, 29662.745104, 29671.053795, 29679.362734, 29687.671918, 29695.981349, 29704.291026, + 29712.600949, 29720.911118, 29729.221533, 29737.532194, 29745.843101, 29754.154253, 29762.465651, 29770.777295, + 29779.089185, 29787.401320, 29795.713701, 29804.026327, 29812.339198, 29820.652315, 29828.965677, 29837.279284, + 29845.593136, 29853.907233, 29862.221576, 29870.536163, 29878.850995, 29887.166072, 29895.481394, 29903.796960, + 29912.112772, 29920.428827, 29928.745128, 29937.061672, 29945.378461, 29953.695495, 29962.012773, 29970.330295, + 29978.648061, 29986.966071, 29995.284325, 30003.602824, 30011.921566, 30020.240552, 30028.559782, 30036.879256, + 30045.198973, 30053.518934, 30061.839139, 30070.159587, 30078.480278, 30086.801213, 30095.122392, 30103.443813, + 30111.765478, 30120.087386, 30128.409537, 30136.731931, 30145.054568, 30153.377448, 30161.700571, 30170.023937, + 30178.347545, 30186.671397, 30194.995490, 30203.319827, 30211.644406, 30219.969227, 30228.294290, 30236.619597, + 30244.945145, 30253.270935, 30261.596968, 30269.923243, 30278.249760, 30286.576518, 30294.903519, 30303.230762, + 30311.558246, 30319.885972, 30328.213940, 30336.542150, 30344.870601, 30353.199293, 30361.528227, 30369.857403, + 30378.186820, 30386.516478, 30394.846377, 30403.176517, 30411.506899, 30419.837522, 30428.168385, 30436.499490, + 30444.830835, 30453.162422, 30461.494249, 30469.826316, 30478.158625, 30486.491174, 30494.823963, 30503.156993, + 30511.490263, 30519.823774, 30528.157525, 30536.491516, 30544.825748, 30553.160219, 30561.494931, 30569.829882, + 30578.165074, 30586.500506, 30594.836177, 30603.172088, 30611.508239, 30619.844629, 30628.181259, 30636.518129, + 30644.855238, 30653.192587, 30661.530175, 30669.868002, 30678.206068, 30686.544374, 30694.882919, 30703.221703, + 30711.560726, 30719.899988, 30728.239489, 30736.579229, 30744.919207, 30753.259425, 30761.599881, 30769.940575, + 30778.281508, 30786.622680, 30794.964090, 30803.305739, 30811.647626, 30819.989751, 30828.332115, 30836.674716, + 30845.017556, 30853.360634, 30861.703950, 30870.047504, 30878.391296, 30886.735325, 30895.079592, 30903.424098, + 30911.768840, 30920.113821, 30928.459039, 30936.804494, 30945.150187, 30953.496117, 30961.842285, 30970.188690, + 30978.535332, 30986.882211, 30995.229327, 31003.576681, 31011.924271, 31020.272098, 31028.620163, 31036.968464, + 31045.317002, 31053.665776, 31062.014787, 31070.364035, 31078.713519, 31087.063240, 31095.413198, 31103.763391, + 31112.113821, 31120.464487, 31128.815390, 31137.166529, 31145.517903, 31153.869514, 31162.221361, 31170.573443, + 31178.925762, 31187.278316, 31195.631106, 31203.984132, 31212.337394, 31220.690891, 31229.044624, 31237.398592, + 31245.752795, 31254.107234, 31262.461908, 31270.816818, 31279.171963, 31287.527343, 31295.882958, 31304.238808, + 31312.594893, 31320.951213, 31329.307767, 31337.664557, 31346.021582, 31354.378841, 31362.736335, 31371.094063, + 31379.452026, 31387.810223, 31396.168655, 31404.527322, 31412.886222, 31421.245357, 31429.604726, 31437.964329, + 31446.324167, 31454.684238, 31463.044544, 31471.405083, 31479.765856, 31488.126863, 31496.488104, 31504.849579, + 31513.211287, 31521.573229, 31529.935405, 31538.297814, 31546.660456, 31555.023332, 31563.386441, 31571.749784, + 31580.113359, 31588.477168, 31596.841210, 31605.205485, 31613.569993, 31621.934734, 31630.299708, 31638.664915, + 31647.030355, 31655.396027, 31663.761932, 31672.128070, 31680.494440, 31688.861043, 31697.227878, 31705.594946, + 31713.962246, 31722.329779, 31730.697543, 31739.065540, 31747.433769, 31755.802230, 31764.170924, 31772.539849, + 31780.909006, 31789.278395, 31797.648016, 31806.017868, 31814.387953, 31822.758269, 31831.128816, 31839.499595, + 31847.870606, 31856.241848, 31864.613322, 31872.985027, 31881.356963, 31889.729130, 31898.101529, 31906.474159, + 31914.847019, 31923.220111, 31931.593434, 31939.966988, 31948.340772, 31956.714788, 31965.089034, 31973.463511, + 31981.838218, 31990.213157, 31998.588325, 32006.963725, 32015.339354, 32023.715214, 32032.091305, 32040.467625, + 32048.844176, 32057.220957, 32065.597968, 32073.975209, 32082.352681, 32090.730382, 32099.108313, 32107.486474, + 32115.864865, 32124.243485, 32132.622336, 32141.001415, 32149.380725, 32157.760264, 32166.140032, 32174.520030, + 32182.900258, 32191.280714, 32199.661400, 32208.042316, 32216.423460, 32224.804833, 32233.186436, 32241.568267, + 32249.950328, 32258.332617, 32266.715136, 32275.097883, 32283.480859, 32291.864063, 32300.247496, 32308.631158, + 32317.015049, 32325.399167, 32333.783515, 32342.168090, 32350.552894, 32358.937927, 32367.323187, 32375.708676, + 32384.094393, 32392.480338, 32400.866510, 32409.252911, 32417.639540, 32426.026397, 32434.413481, 32442.800794, + 32451.188334, 32459.576101, 32467.964097, 32476.352319, 32484.740770, 32493.129447, 32501.518353, 32509.907485, + 32518.296845, 32526.686432, 32535.076246, 32543.466288, 32551.856556, 32560.247052, 32568.637774, 32577.028724, + 32585.419900, 32593.811303, 32602.202933, 32610.594790, 32618.986873, 32627.379183, 32635.771720, 32644.164483, + 32652.557473, 32660.950689, 32669.344131, 32677.737800, 32686.131695, 32694.525816, 32702.920163, 32711.314737, + 32719.709536, 32728.104562, 32736.499813, 32744.895291, 32753.290994, 32761.686923, 32770.083078, 32778.479459, + 32786.876065, 32795.272897, 32803.669954, 32812.067237, 32820.464745, 32828.862479, 32837.260438, 32845.658623, + 32854.057032, 32862.455667, 32870.854527, 32879.253612, 32887.652922, 32896.052457, 32904.452218, 32912.852203, + 32921.252412, 32929.652847, 32938.053506, 32946.454390, 32954.855499, 32963.256832, 32971.658390, 32980.060173, + 32988.462179, 32996.864411, 33005.266866, 33013.669546, 33022.072450, 33030.475578, 33038.878931, 33047.282507, + 33055.686308, 33064.090332, 33072.494581, 33080.899053, 33089.303749, 33097.708669, 33106.113813, 33114.519180, + 33122.924771, 33131.330586, 33139.736624, 33148.142885, 33156.549370, 33164.956079, 33173.363011, 33181.770166, + 33190.177544, 33198.585146, 33206.992970, 33215.401018, 33223.809289, 33232.217783, 33240.626499, 33249.035439, + 33257.444601, 33265.853987, 33274.263595, 33282.673425, 33291.083479, 33299.493754, 33307.904253, 33316.314974, + 33324.725917, 33333.137083, 33341.548471, 33349.960082, 33358.371914, 33366.783969, 33375.196246, 33383.608745, + 33392.021466, 33400.434410, 33408.847575, 33417.260962, 33425.674571, 33434.088401, 33442.502454, 33450.916728, + 33459.331224, 33467.745941, 33476.160880, 33484.576041, 33492.991422, 33501.407026, 33509.822850, 33518.238897, + 33526.655164, 33535.071652, 33543.488362, 33551.905293, 33560.322445, 33568.739817, 33577.157411, 33585.575226, + 33593.993262, 33602.411518, 33610.829995, 33619.248693, 33627.667612, 33636.086751, 33644.506111, 33652.925691, + 33661.345492, 33669.765513, 33678.185755, 33686.606217, 33695.026899, 33703.447802, 33711.868925, 33720.290267, + 33728.711830, 33737.133613, 33745.555616, 33753.977839, 33762.400282, 33770.822945, 33779.245827, 33787.668930, + 33796.092252, 33804.515793, 33812.939555, 33821.363535, 33829.787736, 33838.212156, 33846.636795, 33855.061653, + 33863.486731, 33871.912028, 33880.337545, 33888.763280, 33897.189235, 33905.615409, 33914.041802, 33922.468414, + 33930.895244, 33939.322294, 33947.749562, 33956.177050, 33964.604756, 33973.032680, 33981.460824, 33989.889186, + 33998.317766, 34006.746565, 34015.175583, 34023.604819, 34032.034273, 34040.463946, 34048.893836, 34057.323946, + 34065.754273, 34074.184818, 34082.615582, 34091.046563, 34099.477763, 34107.909180, 34116.340815, 34124.772669, + 34133.204739, 34141.637028, 34150.069535, 34158.502259, 34166.935200, 34175.368359, 34183.801736, 34192.235330, + 34200.669142, 34209.103171, 34217.537417, 34225.971881, 34234.406561, 34242.841459, 34251.276574, 34259.711907, + 34268.147456, 34276.583222, 34285.019205, 34293.455405, 34301.891822, 34310.328456, 34318.765306, 34327.202373, + 34335.639657, 34344.077158, 34352.514874, 34360.952808, 34369.390958, 34377.829324, 34386.267907, 34394.706706, + 34403.145722, 34411.584953, 34420.024401, 34428.464065, 34436.903945, 34445.344041, 34453.784354, 34462.224882, + 34470.665626, 34479.106586, 34487.547761, 34495.989153, 34504.430760, 34512.872583, 34521.314621, 34529.756875, + 34538.199345, 34546.642030, 34555.084931, 34563.528047, 34571.971378, 34580.414925, 34588.858687, 34597.302664, + 34605.746856, 34614.191264, 34622.635886, 34631.080724, 34639.525776, 34647.971044, 34656.416526, 34664.862223, + 34673.308135, 34681.754262, 34690.200603, 34698.647159, 34707.093930, 34715.540915, 34723.988115, 34732.435530, + 34740.883158, 34749.331001, 34757.779059, 34766.227331, 34774.675817, 34783.124517, 34791.573431, 34800.022560, + 34808.471902, 34816.921459, 34825.371229, 34833.821214, 34842.271412, 34850.721824, 34859.172450, 34867.623290, + 34876.074343, 34884.525610, 34892.977091, 34901.428785, 34909.880693, 34918.332814, 34926.785149, 34935.237697, + 34943.690458, 34952.143433, 34960.596620, 34969.050021, 34977.503636, 34985.957463, 34994.411503, 35002.865757, + 35011.320223, 35019.774902, 35028.229795, 35036.684900, 35045.140217, 35053.595748, 35062.051491, 35070.507447, + 35078.963615, 35087.419997, 35095.876590, 35104.333396, 35112.790415, 35121.247645, 35129.705089, 35138.162744, + 35146.620612, 35155.078692, 35163.536984, 35171.995488, 35180.454204, 35188.913133, 35197.372273, 35205.831625, + 35214.291189, 35222.750965, 35231.210953, 35239.671152, 35248.131563, 35256.592186, 35265.053021, 35273.514067, + 35281.975324, 35290.436793, 35298.898474, 35307.360366, 35315.822469, 35324.284783, 35332.747309, 35341.210046, + 35349.672994, 35358.136154, 35366.599524, 35375.063106, 35383.526898, 35391.990901, 35400.455116, 35408.919541, + 35417.384177, 35425.849023, 35434.314081, 35442.779349, 35451.244828, 35459.710517, 35468.176417, 35476.642527, + 35485.108848, 35493.575379, 35502.042121, 35510.509073, 35518.976235, 35527.443608, 35535.911191, 35544.378983, + 35552.846986, 35561.315199, 35569.783622, 35578.252255, 35586.721098, 35595.190151, 35603.659414, 35612.128886, + 35620.598568, 35629.068460, 35637.538562, 35646.008873, 35654.479394, 35662.950124, 35671.421064, 35679.892213, + 35688.363572, 35696.835140, 35705.306917, 35713.778904, 35722.251100, 35730.723505, 35739.196119, 35747.668942, + 35756.141974, 35764.615216, 35773.088666, 35781.562325, 35790.036193, 35798.510270, 35806.984556, 35815.459050, + 35823.933753, 35832.408665, 35840.883786, 35849.359115, 35857.834652, 35866.310398, 35874.786353, 35883.262515, + 35891.738887, 35900.215466, 35908.692254, 35917.169250, 35925.646454, 35934.123866, 35942.601487, 35951.079315, + 35959.557352, 35968.035596, 35976.514049, 35984.992709, 35993.471577, 36001.950653, 36010.429936, 36018.909428, + 36027.389127, 36035.869033, 36044.349147, 36052.829469, 36061.309998, 36069.790735, 36078.271679, 36086.752831, + 36095.234189, 36103.715755, 36112.197529, 36120.679509, 36129.161697, 36137.644091, 36146.126693, 36154.609502, + 36163.092517, 36171.575740, 36180.059170, 36188.542806, 36197.026649, 36205.510699, 36213.994956, 36222.479419, + 36230.964089, 36239.448966, 36247.934049, 36256.419339, 36264.904835, 36273.390537, 36281.876446, 36290.362561, + 36298.848883, 36307.335411, 36315.822145, 36324.309085, 36332.796231, 36341.283584, 36349.771142, 36358.258906, + 36366.746877, 36375.235053, 36383.723435, 36392.212023, 36400.700817, 36409.189816, 36417.679021, 36426.168432, + 36434.658048, 36443.147870, 36451.637898, 36460.128131, 36468.618569, 36477.109213, 36485.600063, 36494.091117, + 36502.582377, 36511.073842, 36519.565512, 36528.057388, 36536.549468, 36545.041754, 36553.534244, 36562.026940, + 36570.519840, 36579.012946, 36587.506256, 36595.999771, 36604.493491, 36612.987415, 36621.481545, 36629.975878, + 36638.470417, 36646.965160, 36655.460108, 36663.955260, 36672.450616, 36680.946177, 36689.441942, 36697.937912, + 36706.434086, 36714.930464, 36723.427046, 36731.923832, 36740.420823, 36748.918017, 36757.415416, 36765.913019, + 36774.410825, 36782.908835, 36791.407050, 36799.905468, 36808.404089, 36816.902915, 36825.401944, 36833.901177, + 36842.400614, 36850.900254, 36859.400097, 36867.900144, 36876.400395, 36884.900848, 36893.401506, 36901.902366, + 36910.403430, 36918.904697, 36927.406167, 36935.907841, 36944.409717, 36952.911797, 36961.414079, 36969.916565, + 36978.419253, 36986.922145, 36995.425239, 37003.928536, 37012.432036, 37020.935739, 37029.439644, 37037.943752, + 37046.448062, 37054.952576, 37063.457291, 37071.962209, 37080.467330, 37088.972653, 37097.478178, 37105.983906, + 37114.489836, 37122.995968, 37131.502303, 37140.008839, 37148.515578, 37157.022519, 37165.529662, 37174.037007, + 37182.544554, 37191.052302, 37199.560253, 37208.068405, 37216.576760, 37225.085316, 37233.594073, 37242.103033, + 37250.612194, 37259.121556, 37267.631120, 37276.140886, 37284.650853, 37293.161022, 37301.671392, 37310.181963, + 37318.692736, 37327.203710, 37335.714885, 37344.226261, 37352.737838, 37361.249617, 37369.761597, 37378.273777, + 37386.786159, 37395.298742, 37403.811525, 37412.324509, 37420.837695, 37429.351080, 37437.864667, 37446.378455, + 37454.892443, 37463.406631, 37471.921021, 37480.435610, 37488.950401, 37497.465391, 37505.980583, 37514.495974, + 37523.011566, 37531.527358, 37540.043351, 37548.559544, 37557.075936, 37565.592529, 37574.109323, 37582.626316, + 37591.143509, 37599.660902, 37608.178495, 37616.696288, 37625.214281, 37633.732474, 37642.250866, 37650.769458, + 37659.288250, 37667.807242, 37676.326433, 37684.845824, 37693.365414, 37701.885204, 37710.405193, 37718.925382, + 37727.445770, 37735.966357, 37744.487144, 37753.008130, 37761.529315, 37770.050700, 37778.572283, 37787.094066, + 37795.616048, 37804.138228, 37812.660608, 37821.183187, 37829.705964, 37838.228941, 37846.752116, 37855.275490, + 37863.799063, 37872.322834, 37880.846805, 37889.370973, 37897.895341, 37906.419907, 37914.944671, 37923.469634, + 37931.994796, 37940.520155, 37949.045713, 37957.571470, 37966.097424, 37974.623577, 37983.149929, 37991.676478, + 38000.203225, 38008.730171, 38017.257314, 38025.784656, 38034.312195, 38042.839933, 38051.367868, 38059.896001, + 38068.424332, 38076.952861, 38085.481587, 38094.010511, 38102.539633, 38111.068952, 38119.598469, 38128.128184, + 38136.658096, 38145.188205, 38153.718512, 38162.249016, 38170.779718, 38179.310617, 38187.841713, 38196.373006, + 38204.904497, 38213.436184, 38221.968069, 38230.500151, 38239.032430, 38247.564905, 38256.097578, 38264.630448, + 38273.163514, 38281.696778, 38290.230238, 38298.763895, 38307.297748, 38315.831799, 38324.366046, 38332.900489, + 38341.435129, 38349.969966, 38358.504999, 38367.040229, 38375.575655, 38384.111277, 38392.647096, 38401.183110, + 38409.719322, 38418.255729, 38426.792333, 38435.329132, 38443.866128, 38452.403320, 38460.940708, 38469.478292, + 38478.016072, 38486.554047, 38495.092219, 38503.630586, 38512.169150, 38520.707909, 38529.246863, 38537.786014, + 38546.325360, 38554.864901, 38563.404638, 38571.944571, 38580.484699, 38589.025023, 38597.565542, 38606.106256, + 38614.647166, 38623.188271, 38631.729571, 38640.271067, 38648.812757, 38657.354643, 38665.896724, 38674.439000, + 38682.981471, 38691.524137, 38700.066998, 38708.610054, 38717.153305, 38725.696750, 38734.240391, 38742.784226, + 38751.328256, 38759.872480, 38768.416899, 38776.961513, 38785.506321, 38794.051324, 38802.596522, 38811.141913, + 38819.687500, 38828.233280, 38836.779255, 38845.325425, 38853.871788, 38862.418346, 38870.965098, 38879.512044, + 38888.059184, 38896.606519, 38905.154047, 38913.701770, 38922.249686, 38930.797796, 38939.346100, 38947.894598, + 38956.443290, 38964.992176, 38973.541255, 38982.090528, 38990.639995, 38999.189656, 39007.739510, 39016.289557, + 39024.839798, 39033.390233, 39041.940861, 39050.491682, 39059.042697, 39067.593905, 39076.145306, 39084.696901, + 39093.248689, 39101.800670, 39110.352844, 39118.905211, 39127.457771, 39136.010525, 39144.563471, 39153.116610, + 39161.669943, 39170.223468, 39178.777186, 39187.331097, 39195.885200, 39204.439496, 39212.993985, 39221.548667, + 39230.103541, 39238.658608, 39247.213867, 39255.769319, 39264.324964, 39272.880801, 39281.436830, 39289.993051, + 39298.549465, 39307.106071, 39315.662870, 39324.219861, 39332.777043, 39341.334418, 39349.891985, 39358.449745, + 39367.007696, 39375.565839, 39384.124174, 39392.682701, 39401.241420, 39409.800331, 39418.359434, 39426.918728, + 39435.478214, 39444.037892, 39452.597761, 39461.157822, 39469.718075, 39478.278519, 39486.839155, 39495.399982, + 39503.961001, 39512.522211, 39521.083612, 39529.645205, 39538.206989, 39546.768965, 39555.331131, 39563.893489, + 39572.456038, 39581.018778, 39589.581709, 39598.144831, 39606.708144, 39615.271648, 39623.835343, 39632.399229, + 39640.963306, 39649.527574, 39658.092032, 39666.656681, 39675.221521, 39683.786551, 39692.351773, 39700.917184, + 39709.482787, 39718.048580, 39726.614563, 39735.180737, 39743.747101, 39752.313656, 39760.880401, 39769.447336, + 39778.014461, 39786.581777, 39795.149283, 39803.716979, 39812.284866, 39820.852942, 39829.421209, 39837.989665, + 39846.558311, 39855.127148, 39863.696174, 39872.265390, 39880.834797, 39889.404392, 39897.974178, 39906.544153, + 39915.114319, 39923.684673, 39932.255218, 39940.825952, 39949.396875, 39957.967988, 39966.539291, 39975.110783, + 39983.682464, 39992.254335, 40000.826395, 40009.398644, 40017.971083, 40026.543711, 40035.116528, 40043.689534, + 40052.262730, 40060.836114, 40069.409688, 40077.983450, 40086.557402, 40095.131542, 40103.705871, 40112.280390, + 40120.855097, 40129.429993, 40138.005077, 40146.580351, 40155.155813, 40163.731464, 40172.307303, 40180.883331, + 40189.459548, 40198.035953, 40206.612546, 40215.189328, 40223.766298, 40232.343457, 40240.920804, 40249.498340, + 40258.076063, 40266.653975, 40275.232076, 40283.810364, 40292.388840, 40300.967505, 40309.546357, 40318.125398, + 40326.704627, 40335.284043, 40343.863648, 40352.443440, 40361.023420, 40369.603588, 40378.183944, 40386.764487, + 40395.345218, 40403.926137, 40412.507244, 40421.088538, 40429.670020, 40438.251689, 40446.833546, 40455.415590, + 40463.997821, 40472.580240, 40481.162847, 40489.745640, 40498.328621, 40506.911789, 40515.495145, 40524.078687, + 40532.662417, 40541.246334, 40549.830438, 40558.414729, 40566.999207, 40575.583872, 40584.168723, 40592.753762, + 40601.338988, 40609.924400, 40618.509999, 40627.095785, 40635.681758, 40644.267918, 40652.854264, 40661.440796, + 40670.027515, 40678.614421, 40687.201514, 40695.788792, 40704.376258, 40712.963909, 40721.551747, 40730.139772, + 40738.727982, 40747.316379, 40755.904963, 40764.493732, 40773.082687, 40781.671829, 40790.261157, 40798.850671, + 40807.440371, 40816.030257, 40824.620328, 40833.210586, 40841.801030, 40850.391659, 40858.982475, 40867.573476, + 40876.164663, 40884.756035, 40893.347594, 40901.939337, 40910.531267, 40919.123382, 40927.715683, 40936.308169, + 40944.900841, 40953.493698, 40962.086740, 40970.679968, 40979.273381, 40987.866980, 40996.460764, 41005.054733, + 41013.648887, 41022.243226, 41030.837751, 41039.432460, 41048.027355, 41056.622435, 41065.217700, 41073.813149, + 41082.408784, 41091.004603, 41099.600608, 41108.196797, 41116.793171, 41125.389730, 41133.986473, 41142.583401, + 41151.180514, 41159.777812, 41168.375294, 41176.972960, 41185.570811, 41194.168847, 41202.767067, 41211.365471, + 41219.964060, 41228.562833, 41237.161791, 41245.760933, 41254.360259, 41262.959769, 41271.559463, 41280.159342, + 41288.759405, 41297.359651, 41305.960082, 41314.560697, 41323.161496, 41331.762478, 41340.363645, 41348.964995, + 41357.566530, 41366.168248, 41374.770150, 41383.372236, 41391.974505, 41400.576958, 41409.179595, 41417.782415, + 41426.385419, 41434.988606, 41443.591977, 41452.195531, 41460.799269, 41469.403190, 41478.007295, 41486.611583, + 41495.216054, 41503.820708, 41512.425546, 41521.030567, 41529.635771, 41538.241158, 41546.846729, 41555.452482, + 41564.058418, 41572.664538, 41581.270840, 41589.877325, 41598.483994, 41607.090845, 41615.697879, 41624.305095, + 41632.912495, 41641.520077, 41650.127842, 41658.735789, 41667.343920, 41675.952232, 41684.560728, 41693.169406, + 41701.778266, 41710.387309, 41718.996534, 41727.605942, 41736.215532, 41744.825304, 41753.435259, 41762.045396, + 41770.655715, 41779.266216, 41787.876900, 41796.487766, 41805.098813, 41813.710043, 41822.321455, 41830.933049, + 41839.544825, 41848.156783, 41856.768922, 41865.381244, 41873.993747, 41882.606432, 41891.219299, 41899.832348, + 41908.445578, 41917.058990, 41925.672584, 41934.286359, 41942.900316, 41951.514455, 41960.128774, 41968.743276, + 41977.357959, 41985.972823, 41994.587868, 42003.203095, 42011.818504, 42020.434093, 42029.049864, 42037.665816, + 42046.281949, 42054.898263, 42063.514759, 42072.131435, 42080.748293, 42089.365331, 42097.982551, 42106.599951, + 42115.217532, 42123.835295, 42132.453238, 42141.071362, 42149.689666, 42158.308152, 42166.926818, 42175.545665, + 42184.164692, 42192.783900, 42201.403289, 42210.022858, 42218.642608, 42227.262539, 42235.882649, 42244.502940, + 42253.123412, 42261.744064, 42270.364896, 42278.985909, 42287.607101, 42296.228474, 42304.850028, 42313.471761, + 42322.093674, 42330.715768, 42339.338042, 42347.960495, 42356.583129, 42365.205943, 42373.828936, 42382.452110, + 42391.075463, 42399.698997, 42408.322710, 42416.946602, 42425.570675, 42434.194927, 42442.819359, 42451.443971, + 42460.068762, 42468.693733, 42477.318883, 42485.944213, 42494.569722, 42503.195411, 42511.821279, 42520.447327, + 42529.073554, 42537.699960, 42546.326546, 42554.953310, 42563.580254, 42572.207378, 42580.834680, 42589.462162, + 42598.089822, 42606.717662, 42615.345681, 42623.973879, 42632.602255, 42641.230811, 42649.859545, 42658.488459, + 42667.117551, 42675.746822, 42684.376272, 42693.005901, 42701.635708, 42710.265694, 42718.895859, 42727.526202, + 42736.156724, 42744.787424, 42753.418303, 42762.049361, 42770.680597, 42779.312011, 42787.943604, 42796.575375, + 42805.207324, 42813.839452, 42822.471758, 42831.104242, 42839.736905, 42848.369745, 42857.002764, 42865.635961, + 42874.269336, 42882.902889, 42891.536620, 42900.170529, 42908.804616, 42917.438881, 42926.073323, 42934.707944, + 42943.342743, 42951.977719, 42960.612873, 42969.248204, 42977.883714, 42986.519401, 42995.155266, 43003.791308, + 43012.427528, 43021.063925, 43029.700500, 43038.337253, 43046.974183, 43055.611290, 43064.248575, 43072.886037, + 43081.523676, 43090.161493, 43098.799486, 43107.437658, 43116.076006, 43124.714531, 43133.353234, 43141.992114, + 43150.631170, 43159.270404, 43167.909815, 43176.549403, 43185.189168, 43193.829109, 43202.469228, 43211.109523, + 43219.749995, 43228.390644, 43237.031470, 43245.672473, 43254.313652, 43262.955008, 43271.596540, 43280.238249, + 43288.880135, 43297.522197, 43306.164436, 43314.806851, 43323.449442, 43332.092210, 43340.735155, 43349.378276, + 43358.021573, 43366.665046, 43375.308696, 43383.952521, 43392.596524, 43401.240702, 43409.885056, 43418.529586, + 43427.174293, 43435.819176, 43444.464234, 43453.109469, 43461.754879, 43470.400466, 43479.046228, 43487.692166, + 43496.338280, 43504.984570, 43513.631035, 43522.277677, 43530.924493, 43539.571486, 43548.218654, 43556.865998, + 43565.513518, 43574.161213, 43582.809083, 43591.457129, 43600.105351, 43608.753748, 43617.402320, 43626.051067, + 43634.699990, 43643.349089, 43651.998362, 43660.647811, 43669.297435, 43677.947234, 43686.597208, 43695.247358, + 43703.897682, 43712.548182, 43721.198856, 43729.849706, 43738.500731, 43747.151930, 43755.803304, 43764.454854, + 43773.106578, 43781.758477, 43790.410550, 43799.062799, 43807.715222, 43816.367820, 43825.020592, 43833.673539, + 43842.326661, 43850.979957, 43859.633428, 43868.287073, 43876.940893, 43885.594887, 43894.249056, 43902.903399, + 43911.557917, 43920.212608, 43928.867474, 43937.522514, 43946.177729, 43954.833118, 43963.488681, 43972.144418, + 43980.800329, 43989.456414, 43998.112673, 44006.769106, 44015.425714, 44024.082495, 44032.739450, 44041.396579, + 44050.053882, 44058.711359, 44067.369009, 44076.026833, 44084.684831, 44093.343003, 44102.001349, 44110.659868, + 44119.318561, 44127.977427, 44136.636467, 44145.295680, 44153.955067, 44162.614628, 44171.274362, 44179.934269, + 44188.594350, 44197.254604, 44205.915031, 44214.575632, 44223.236406, 44231.897353, 44240.558473, 44249.219767, + 44257.881233, 44266.542873, 44275.204686, 44283.866672, 44292.528831, 44301.191163, 44309.853668, 44318.516346, + 44327.179196, 44335.842220, 44344.505416, 44353.168786, 44361.832328, 44370.496043, 44379.159930, 44387.823991, + 44396.488223, 44405.152629, 44413.817207, 44422.481958, 44431.146881, 44439.811977, 44448.477245, 44457.142686, + 44465.808299, 44474.474085, 44483.140043, 44491.806173, 44500.472476, 44509.138951, 44517.805598, 44526.472417, + 44535.139409, 44543.806573, 44552.473908, 44561.141416, 44569.809096, 44578.476948, 44587.144973, 44595.813169, + 44604.481537, 44613.150077, 44621.818788, 44630.487672, 44639.156728, 44647.825955, 44656.495354, 44665.164925, + 44673.834668, 44682.504582, 44691.174668, 44699.844925, 44708.515355, 44717.185955, 44725.856728, 44734.527671, + 44743.198787, 44751.870073, 44760.541531, 44769.213161, 44777.884962, 44786.556934, 44795.229078, 44803.901393, + 44812.573879, 44821.246536, 44829.919364, 44838.592364, 44847.265535, 44855.938877, 44864.612390, 44873.286074, + 44881.959929, 44890.633955, 44899.308152, 44907.982519, 44916.657058, 44925.331768, 44934.006648, 44942.681700, + 44951.356922, 44960.032314, 44968.707878, 44977.383612, 44986.059517, 44994.735593, 45003.411839, 45012.088255, + 45020.764843, 45029.441600, 45038.118529, 45046.795627, 45055.472896, 45064.150336, 45072.827946, 45081.505726, + 45090.183677, 45098.861798, 45107.540089, 45116.218550, 45124.897182, 45133.575983, 45142.254955, 45150.934097, + 45159.613409, 45168.292891, 45176.972543, 45185.652366, 45194.332358, 45203.012520, 45211.692852, 45220.373353, + 45229.054025, 45237.734866, 45246.415878, 45255.097059, 45263.778410, 45272.459930, 45281.141620, 45289.823480, + 45298.505509, 45307.187709, 45315.870077, 45324.552615, 45333.235323, 45341.918200, 45350.601247, 45359.284462, + 45367.967848, 45376.651403, 45385.335127, 45394.019020, 45402.703083, 45411.387315, 45420.071716, 45428.756286, + 45437.441025, 45446.125934, 45454.811012, 45463.496258, 45472.181674, 45480.867259, 45489.553013, 45498.238936, + 45506.925028, 45515.611288, 45524.297718, 45532.984316, 45541.671083, 45550.358019, 45559.045124, 45567.732397, + 45576.419840, 45585.107450, 45593.795230, 45602.483178, 45611.171295, 45619.859580, 45628.548034, 45637.236656, + 45645.925447, 45654.614406, 45663.303534, 45671.992830, 45680.682294, 45689.371927, 45698.061728, 45706.751697, + 45715.441835, 45724.132141, 45732.822615, 45741.513257, 45750.204067, 45758.895046, 45767.586192, 45776.277507, + 45784.968989, 45793.660640, 45802.352458, 45811.044445, 45819.736599, 45828.428921, 45837.121412, 45845.814070, + 45854.506895, 45863.199889, 45871.893050, 45880.586379, 45889.279876, 45897.973540, 45906.667372, 45915.361372, + 45924.055539, 45932.749874, 45941.444376, 45950.139045, 45958.833883, 45967.528887, 45976.224059, 45984.919399, + 45993.614905, 46002.310579, 46011.006421, 46019.702429, 46028.398605, 46037.094948, 46045.791458, 46054.488136, + 46063.184980, 46071.881992, 46080.579171, 46089.276516, 46097.974029, 46106.671709, 46115.369556, 46124.067569, + 46132.765750, 46141.464097, 46150.162611, 46158.861292, 46167.560140, 46176.259155, 46184.958336, 46193.657684, + 46202.357199, 46211.056880, 46219.756728, 46228.456743, 46237.156924, 46245.857272, 46254.557786, 46263.258467, + 46271.959314, 46280.660328, 46289.361508, 46298.062854, 46306.764367, 46315.466046, 46324.167891, 46332.869903, + 46341.572081, 46350.274425, 46358.976935, 46367.679612, 46376.382454, 46385.085463, 46393.788638, 46402.491978, + 46411.195485, 46419.899158, 46428.602997, 46437.307001, 46446.011172, 46454.715508, 46463.420011, 46472.124679, + 46480.829513, 46489.534512, 46498.239678, 46506.945009, 46515.650506, 46524.356168, 46533.061996, 46541.767990, + 46550.474149, 46559.180474, 46567.886964, 46576.593620, 46585.300442, 46594.007428, 46602.714581, 46611.421898, + 46620.129381, 46628.837029, 46637.544843, 46646.252822, 46654.960966, 46663.669275, 46672.377749, 46681.086389, + 46689.795194, 46698.504164, 46707.213299, 46715.922599, 46724.632064, 46733.341694, 46742.051489, 46750.761449, + 46759.471574, 46768.181864, 46776.892319, 46785.602938, 46794.313722, 46803.024672, 46811.735785, 46820.447064, + 46829.158507, 46837.870115, 46846.581888, 46855.293825, 46864.005927, 46872.718194, 46881.430625, 46890.143220, + 46898.855980, 46907.568904, 46916.281993, 46924.995247, 46933.708664, 46942.422246, 46951.135993, 46959.849903, + 46968.563978, 46977.278217, 46985.992621, 46994.707188, 47003.421920, 47012.136816, 47020.851876, 47029.567100, + 47038.282488, 47046.998040, 47055.713756, 47064.429636, 47073.145680, 47081.861888, 47090.578260, 47099.294796, + 47108.011495, 47116.728359, 47125.445386, 47134.162577, 47142.879932, 47151.597450, 47160.315132, 47169.032978, + 47177.750987, 47186.469160, 47195.187496, 47203.905996, 47212.624660, 47221.343487, 47230.062478, 47238.781632, + 47247.500949, 47256.220430, 47264.940074, 47273.659881, 47282.379852, 47291.099986, 47299.820283, 47308.540744, + 47317.261368, 47325.982154, 47334.703104, 47343.424218, 47352.145494, 47360.866933, 47369.588536, 47378.310301, + 47387.032229, 47395.754321, 47404.476575, 47413.198992, 47421.921572, 47430.644315, 47439.367220, 47448.090289, + 47456.813520, 47465.536914, 47474.260471, 47482.984190, 47491.708073, 47500.432117, 47509.156325, 47517.880695, + 47526.605227, 47535.329922, 47544.054780, 47552.779800, 47561.504982, 47570.230327, 47578.955835, 47587.681504, + 47596.407336, 47605.133331, 47613.859487, 47622.585806, 47631.312288, 47640.038931, 47648.765737, 47657.492704, + 47666.219834, 47674.947126, 47683.674580, 47692.402197, 47701.129975, 47709.857915, 47718.586017, 47727.314281, + 47736.042707, 47744.771295, 47753.500045, 47762.228957, 47770.958031, 47779.687266, 47788.416663, 47797.146222, + 47805.875943, 47814.605825, 47823.335869, 47832.066074, 47840.796442, 47849.526970, 47858.257661, 47866.988513, + 47875.719526, 47884.450701, 47893.182037, 47901.913535, 47910.645194, 47919.377015, 47928.108997, 47936.841140, + 47945.573445, 47954.305911, 47963.038538, 47971.771326, 47980.504275, 47989.237386, 47997.970658, 48006.704091, + 48015.437685, 48024.171440, 48032.905356, 48041.639434, 48050.373672, 48059.108071, 48067.842631, 48076.577352, + 48085.312234, 48094.047277, 48102.782480, 48111.517845, 48120.253370, 48128.989056, 48137.724902, 48146.460910, + 48155.197078, 48163.933407, 48172.669896, 48181.406546, 48190.143356, 48198.880328, 48207.617459, 48216.354751, + 48225.092204, 48233.829817, 48242.567590, 48251.305524, 48260.043618, 48268.781873, 48277.520288, 48286.258863, + 48294.997599, 48303.736494, 48312.475550, 48321.214766, 48329.954143, 48338.693679, 48347.433376, 48356.173232, + 48364.913249, 48373.653426, 48382.393762, 48391.134259, 48399.874916, 48408.615732, 48417.356709, 48426.097845, + 48434.839142, 48443.580598, 48452.322214, 48461.063989, 48469.805925, 48478.548020, 48487.290275, 48496.032689, + 48504.775264, 48513.517998, 48522.260891, 48531.003944, 48539.747157, 48548.490529, 48557.234060, 48565.977752, + 48574.721602, 48583.465612, 48592.209782, 48600.954110, 48609.698598, 48618.443246, 48627.188053, 48635.933019, + 48644.678144, 48653.423428, 48662.168872, 48670.914475, 48679.660237, 48688.406158, 48697.152238, 48705.898477, + 48714.644876, 48723.391433, 48732.138150, 48740.885025, 48749.632059, 48758.379252, 48767.126604, 48775.874115, + 48784.621785, 48793.369614, 48802.117601, 48810.865747, 48819.614052, 48828.362516, 48837.111138, 48845.859919, + 48854.608859, 48863.357957, 48872.107214, 48880.856629, 48889.606203, 48898.355936, 48907.105827, 48915.855876, + 48924.606084, 48933.356450, 48942.106975, 48950.857658, 48959.608499, 48968.359499, 48977.110657, 48985.861973, + 48994.613448, 49003.365080, 49012.116871, 49020.868820, 49029.620928, 49038.373193, 49047.125616, 49055.878198, + 49064.630937, 49073.383835, 49082.136890, 49090.890104, 49099.643475, 49108.397005, 49117.150692, 49125.904537, + 49134.658540, 49143.412701, 49152.167019, 49160.921495, 49169.676129, 49178.430921, 49187.185871, 49195.940978, + 49204.696243, 49213.451665, 49222.207245, 49230.962982, 49239.718877, 49248.474930, 49257.231140, 49265.987508, + 49274.744033, 49283.500715, 49292.257555, 49301.014552, 49309.771707, 49318.529019, 49327.286488, 49336.044114, + 49344.801898, 49353.559839, 49362.317937, 49371.076192, 49379.834604, 49388.593174, 49397.351900, 49406.110784, + 49414.869825, 49423.629023, 49432.388377, 49441.147889, 49449.907558, 49458.667383, 49467.427366, 49476.187505, + 49484.947801, 49493.708254, 49502.468864, 49511.229631, 49519.990554, 49528.751634, 49537.512871, 49546.274265, + 49555.035815, 49563.797522, 49572.559385, 49581.321405, 49590.083581, 49598.845915, 49607.608404, 49616.371050, + 49625.133853, 49633.896811, 49642.659927, 49651.423199, 49660.186627, 49668.950211, 49677.713952, 49686.477849, + 49695.241902, 49704.006112, 49712.770477, 49721.534999, 49730.299677, 49739.064511, 49747.829502, 49756.594648, + 49765.359951, 49774.125409, 49782.891024, 49791.656794, 49800.422721, 49809.188803, 49817.955042, 49826.721436, + 49835.487986, 49844.254692, 49853.021554, 49861.788572, 49870.555745, 49879.323074, 49888.090559, 49896.858200, + 49905.625996, 49914.393948, 49923.162055, 49931.930318, 49940.698737, 49949.467311, 49958.236041, 49967.004927, + 49975.773967, 49984.543164, 49993.312515, 50002.082022, 50010.851685, 50019.621503, 50028.391476, 50037.161605, + 50045.931888, 50054.702327, 50063.472922, 50072.243671, 50081.014576, 50089.785636, 50098.556851, 50107.328221, + 50116.099747, 50124.871427, 50133.643262, 50142.415253, 50151.187398, 50159.959699, 50168.732154, 50177.504764, + 50186.277529, 50195.050450, 50203.823525, 50212.596754, 50221.370139, 50230.143678, 50238.917372, 50247.691221, + 50256.465225, 50265.239383, 50274.013696, 50282.788164, 50291.562786, 50300.337563, 50309.112494, 50317.887580, + 50326.662821, 50335.438216, 50344.213765, 50352.989469, 50361.765327, 50370.541340, 50379.317507, 50388.093828, + 50396.870304, 50405.646934, 50414.423719, 50423.200657, 50431.977750, 50440.754997, 50449.532399, 50458.309954, + 50467.087664, 50475.865527, 50484.643545, 50493.421717, 50502.200043, 50510.978523, 50519.757157, 50528.535945, + 50537.314887, 50546.093983, 50554.873232, 50563.652636, 50572.432193, 50581.211905, 50589.991770, 50598.771789, + 50607.551961, 50616.332288, 50625.112768, 50633.893402, 50642.674189, 50651.455130, 50660.236225, 50669.017473, + 50677.798875, 50686.580431, 50695.362140, 50704.144002, 50712.926018, 50721.708187, 50730.490510, 50739.272987, + 50748.055616, 50756.838399, 50765.621336, 50774.404425, 50783.187668, 50791.971064, 50800.754614, 50809.538317, + 50818.322173, 50827.106182, 50835.890344, 50844.674659, 50853.459128, 50862.243749, 50871.028524, 50879.813451, + 50888.598532, 50897.383766, 50906.169152, 50914.954692, 50923.740384, 50932.526230, 50941.312228, 50950.098379, + 50958.884683, 50967.671139, 50976.457749, 50985.244511, 50994.031426, 51002.818494, 51011.605714, 51020.393087, + 51029.180613, 51037.968291, 51046.756122, 51055.544105, 51064.332241, 51073.120529, 51081.908970, 51090.697564, + 51099.486310, 51108.275208, 51117.064259, 51125.853462, 51134.642817, 51143.432325, 51152.221985, 51161.011798, + 51169.801762, 51178.591879, 51187.382148, 51196.172569, 51204.963143, 51213.753869, 51222.544746, 51231.335776, + 51240.126958, 51248.918292, 51257.709778, 51266.501416, 51275.293206, 51284.085148, 51292.877242, 51301.669488, + 51310.461886, 51319.254435, 51328.047137, 51336.839990, 51345.632995, 51354.426152, 51363.219461, 51372.012921, + 51380.806533, 51389.600297, 51398.394212, 51407.188279, 51415.982498, 51424.776868, 51433.571390, 51442.366064, + 51451.160889, 51459.955865, 51468.750993, 51477.546272, 51486.341703, 51495.137285, 51503.933019, 51512.728904, + 51521.524940, 51530.321128, 51539.117467, 51547.913957, 51556.710598, 51565.507391, 51574.304335, 51583.101430, + 51591.898676, 51600.696074, 51609.493622, 51618.291322, 51627.089172, 51635.887174, 51644.685327, 51653.483631, + 51662.282085, 51671.080691, 51679.879447, 51688.678355, 51697.477413, 51706.276623, 51715.075983, 51723.875494, + 51732.675155, 51741.474968, 51750.274931, 51759.075045, 51767.875310, 51776.675725, 51785.476291, 51794.277007, + 51803.077875, 51811.878893, 51820.680061, 51829.481380, 51838.282849, 51847.084469, 51855.886240, 51864.688161, + 51873.490232, 51882.292454, 51891.094826, 51899.897348, 51908.700021, 51917.502844, 51926.305818, 51935.108942, + 51943.912216, 51952.715640, 51961.519214, 51970.322939, 51979.126814, 51987.930838, 51996.735013, 52005.539339, + 52014.343814, 52023.148439, 52031.953214, 52040.758140, 52049.563215, 52058.368440, 52067.173815, 52075.979340, + 52084.785015, 52093.590840, 52102.396815, 52111.202939, 52120.009213, 52128.815637, 52137.622211, 52146.428935, + 52155.235808, 52164.042831, 52172.850004, 52181.657326, 52190.464798, 52199.272419, 52208.080190, 52216.888111, + 52225.696181, 52234.504401, 52243.312770, 52252.121289, 52260.929957, 52269.738774, 52278.547741, 52287.356857, + 52296.166123, 52304.975538, 52313.785102, 52322.594816, 52331.404678, 52340.214690, 52349.024852, 52357.835162, + 52366.645622, 52375.456231, 52384.266989, 52393.077896, 52401.888952, 52410.700157, 52419.511511, 52428.323014, + 52437.134667, 52445.946468, 52454.758418, 52463.570517, 52472.382765, 52481.195162, 52490.007708, 52498.820402, + 52507.633246, 52516.446238, 52525.259379, 52534.072669, 52542.886107, 52551.699695, 52560.513430, 52569.327315, + 52578.141348, 52586.955530, 52595.769860, 52604.584339, 52613.398967, 52622.213743, 52631.028668, 52639.843741, + 52648.658962, 52657.474332, 52666.289851, 52675.105518, 52683.921333, 52692.737296, 52701.553408, 52710.369668, + 52719.186077, 52728.002634, 52736.819339, 52745.636192, 52754.453193, 52763.270343, 52772.087641, 52780.905087, + 52789.722681, 52798.540423, 52807.358313, 52816.176351, 52824.994538, 52833.812872, 52842.631354, 52851.449984, + 52860.268763, 52869.087689, 52877.906763, 52886.725985, 52895.545354, 52904.364872, 52913.184537, 52922.004350, + 52930.824311, 52939.644420, 52948.464676, 52957.285080, 52966.105632, 52974.926331, 52983.747178, 52992.568173, + 53001.389315, 53010.210605, 53019.032042, 53027.853627, 53036.675360, 53045.497240, 53054.319267, 53063.141442, + 53071.963764, 53080.786233, 53089.608850, 53098.431615, 53107.254526, 53116.077585, 53124.900791, 53133.724145, + 53142.547646, 53151.371294, 53160.195089, 53169.019031, 53177.843121, 53186.667357, 53195.491741, 53204.316272, + 53213.140950, 53221.965775, 53230.790747, 53239.615866, 53248.441131, 53257.266544, 53266.092104, 53274.917811, + 53283.743665, 53292.569665, 53301.395813, 53310.222107, 53319.048548, 53327.875136, 53336.701870, 53345.528752, + 53354.355780, 53363.182955, 53372.010276, 53380.837744, 53389.665359, 53398.493120, 53407.321028, 53416.149083, + 53424.977284, 53433.805631, 53442.634126, 53451.462766, 53460.291553, 53469.120487, 53477.949567, 53486.778793, + 53495.608166, 53504.437685, 53513.267350, 53522.097162, 53530.927120, 53539.757224, 53548.587475, 53557.417872, + 53566.248415, 53575.079104, 53583.909939, 53592.740921, 53601.572049, 53610.403322, 53619.234742, 53628.066308, + 53636.898020, 53645.729878, 53654.561882, 53663.394032, 53672.226328, 53681.058769, 53689.891357, 53698.724091, + 53707.556970, 53716.389995, 53725.223167, 53734.056483, 53742.889946, 53751.723555, 53760.557309, 53769.391209, + 53778.225254, 53787.059446, 53795.893783, 53804.728265, 53813.562894, 53822.397667, 53831.232587, 53840.067652, + 53848.902862, 53857.738218, 53866.573720, 53875.409367, 53884.245159, 53893.081097, 53901.917180, 53910.753408, + 53919.589782, 53928.426302, 53937.262966, 53946.099776, 53954.936731, 53963.773832, 53972.611077, 53981.448468, + 53990.286004, 53999.123685, 54007.961512, 54016.799483, 54025.637600, 54034.475862, 54043.314268, 54052.152820, + 54060.991517, 54069.830359, 54078.669346, 54087.508477, 54096.347754, 54105.187176, 54114.026742, 54122.866453, + 54131.706310, 54140.546311, 54149.386457, 54158.226747, 54167.067183, 54175.907763, 54184.748488, 54193.589357, + 54202.430372, 54211.271531, 54220.112834, 54228.954283, 54237.795875, 54246.637613, 54255.479495, 54264.321521, + 54273.163692, 54282.006008, 54290.848468, 54299.691073, 54308.533821, 54317.376715, 54326.219753, 54335.062935, + 54343.906261, 54352.749732, 54361.593347, 54370.437106, 54379.281010, 54388.125058, 54396.969250, 54405.813586, + 54414.658067, 54423.502692, 54432.347460, 54441.192373, 54450.037430, 54458.882631, 54467.727977, 54476.573466, + 54485.419099, 54494.264876, 54503.110798, 54511.956863, 54520.803072, 54529.649425, 54538.495922, 54547.342563, + 54556.189347, 54565.036276, 54573.883348, 54582.730564, 54591.577924, 54600.425428, 54609.273075, 54618.120866, + 54626.968801, 54635.816879, 54644.665102, 54653.513467, 54662.361977, 54671.210629, 54680.059426, 54688.908366, + 54697.757449, 54706.606676, 54715.456047, 54724.305561, 54733.155218, 54742.005019, 54750.854963, 54759.705051, + 54768.555282, 54777.405656, 54786.256174, 54795.106835, 54803.957639, 54812.808586, 54821.659677, 54830.510911, + 54839.362288, 54848.213808, 54857.065472, 54865.917278, 54874.769228, 54883.621321, 54892.473557, 54901.325936, + 54910.178457, 54919.031122, 54927.883930, 54936.736881, 54945.589975, 54954.443212, 54963.296591, 54972.150114, + 54981.003779, 54989.857588, 54998.711539, 55007.565633, 55016.419869, 55025.274249, 55034.128771, 55042.983436, + 55051.838244, 55060.693194, 55069.548287, 55078.403523, 55087.258901, 55096.114422, 55104.970085, 55113.825891, + 55122.681840, 55131.537931, 55140.394164, 55149.250540, 55158.107059, 55166.963720, 55175.820523, 55184.677469, + 55193.534557, 55202.391787, 55211.249160, 55220.106675, 55228.964333, 55237.822133, 55246.680075, 55255.538159, + 55264.396385, 55273.254754, 55282.113265, 55290.971918, 55299.830713, 55308.689650, 55317.548729, 55326.407951, + 55335.267314, 55344.126820, 55352.986467, 55361.846257, 55370.706188, 55379.566261, 55388.426477, 55397.286834, + 55406.147333, 55415.007974, 55423.868757, 55432.729682, 55441.590749, 55450.451957, 55459.313307, 55468.174799, + 55477.036432, 55485.898208, 55494.760125, 55503.622183, 55512.484384, 55521.346726, 55530.209209, 55539.071834, + 55547.934601, 55556.797509, 55565.660559, 55574.523751, 55583.387083, 55592.250558, 55601.114174, 55609.977931, + 55618.841829, 55627.705869, 55636.570051, 55645.434373, 55654.298837, 55663.163443, 55672.028190, 55680.893077, + 55689.758107, 55698.623277, 55707.488589, 55716.354042, 55725.219636, 55734.085371, 55742.951247, 55751.817264, + 55760.683423, 55769.549722, 55778.416163, 55787.282745, 55796.149467, 55805.016331, 55813.883336, 55822.750481, + 55831.617768, 55840.485195, 55849.352764, 55858.220473, 55867.088323, 55875.956314, 55884.824445, 55893.692718, + 55902.561131, 55911.429685, 55920.298380, 55929.167216, 55938.036192, 55946.905309, 55955.774566, 55964.643964, + 55973.513503, 55982.383182, 55991.253002, 56000.122963, 56008.993064, 56017.863305, 56026.733688, 56035.604210, + 56044.474873, 56053.345677, 56062.216620, 56071.087705, 56079.958929, 56088.830294, 56097.701800, 56106.573445, + 56115.445231, 56124.317158, 56133.189224, 56142.061431, 56150.933778, 56159.806265, 56168.678892, 56177.551660, + 56186.424568, 56195.297615, 56204.170803, 56213.044131, 56221.917599, 56230.791207, 56239.664956, 56248.538844, + 56257.412872, 56266.287040, 56275.161348, 56284.035796, 56292.910384, 56301.785112, 56310.659979, 56319.534987, + 56328.410134, 56337.285421, 56346.160848, 56355.036415, 56363.912121, 56372.787967, 56381.663953, 56390.540079, + 56399.416344, 56408.292749, 56417.169294, 56426.045978, 56434.922801, 56443.799765, 56452.676868, 56461.554110, + 56470.431492, 56479.309014, 56488.186674, 56497.064475, 56505.942415, 56514.820494, 56523.698713, 56532.577071, + 56541.455568, 56550.334205, 56559.212981, 56568.091896, 56576.970951, 56585.850145, 56594.729478, 56603.608950, + 56612.488562, 56621.368313, 56630.248203, 56639.128232, 56648.008400, 56656.888708, 56665.769154, 56674.649740, + 56683.530464, 56692.411328, 56701.292330, 56710.173472, 56719.054753, 56727.936172, 56736.817731, 56745.699428, + 56754.581264, 56763.463239, 56772.345354, 56781.227606, 56790.109998, 56798.992529, 56807.875198, 56816.758006, + 56825.640953, 56834.524038, 56843.407263, 56852.290625, 56861.174127, 56870.057767, 56878.941546, 56887.825464, + 56896.709520, 56905.593714, 56914.478047, 56923.362519, 56932.247129, 56941.131878, 56950.016765, 56958.901791, + 56967.786955, 56976.672258, 56985.557699, 56994.443278, 57003.328995, 57012.214851, 57021.100846, 57029.986978, + 57038.873249, 57047.759658, 57056.646206, 57065.532892, 57074.419715, 57083.306677, 57092.193778, 57101.081016, + 57109.968392, 57118.855907, 57127.743560, 57136.631350, 57145.519279, 57154.407346, 57163.295551, 57172.183894, + 57181.072375, 57189.960994, 57198.849750, 57207.738645, 57216.627678, 57225.516848, 57234.406156, 57243.295602, + 57252.185186, 57261.074908, 57269.964768, 57278.854765, 57287.744900, 57296.635173, 57305.525584, 57314.416132, + 57323.306818, 57332.197641, 57341.088603, 57349.979702, 57358.870938, 57367.762312, 57376.653824, 57385.545473, + 57394.437259, 57403.329183, 57412.221245, 57421.113444, 57430.005781, 57438.898255, 57447.790866, 57456.683615, + 57465.576501, 57474.469524, 57483.362685, 57492.255983, 57501.149419, 57510.042992, 57518.936702, 57527.830549, + 57536.724533, 57545.618655, 57554.512914, 57563.407310, 57572.301843, 57581.196513, 57590.091320, 57598.986265, + 57607.881346, 57616.776565, 57625.671921, 57634.567413, 57643.463043, 57652.358809, 57661.254713, 57670.150754, + 57679.046931, 57687.943245, 57696.839696, 57705.736285, 57714.633009, 57723.529871, 57732.426870, 57741.324005, + 57750.221277, 57759.118686, 57768.016232, 57776.913914, 57785.811733, 57794.709689, 57803.607781, 57812.506010, + 57821.404376, 57830.302878, 57839.201517, 57848.100292, 57856.999204, 57865.898252, 57874.797437, 57883.696759, + 57892.596217, 57901.495811, 57910.395542, 57919.295409, 57928.195413, 57937.095553, 57945.995829, 57954.896242, + 57963.796791, 57972.697476, 57981.598298, 57990.499255, 57999.400350, 58008.301580, 58017.202946, 58026.104449, + 58035.006088, 58043.907863, 58052.809774, 58061.711822, 58070.614005, 58079.516325, 58088.418780, 58097.321372, + 58106.224100, 58115.126963, 58124.029963, 58132.933099, 58141.836370, 58150.739778, 58159.643321, 58168.547001, + 58177.450816, 58186.354767, 58195.258854, 58204.163076, 58213.067435, 58221.971929, 58230.876559, 58239.781325, + 58248.686227, 58257.591264, 58266.496437, 58275.401746, 58284.307190, 58293.212770, 58302.118486, 58311.024337, + 58319.930324, 58328.836446, 58337.742704, 58346.649097, 58355.555626, 58364.462291, 58373.369090, 58382.276026, + 58391.183097, 58400.090303, 58408.997644, 58417.905121, 58426.812734, 58435.720481, 58444.628364, 58453.536383, + 58462.444536, 58471.352825, 58480.261249, 58489.169809, 58498.078503, 58506.987333, 58515.896298, 58524.805398, + 58533.714633, 58542.624004, 58551.533509, 58560.443150, 58569.352926, 58578.262836, 58587.172882, 58596.083063, + 58604.993379, 58613.903829, 58622.814415, 58631.725136, 58640.635991, 58649.546982, 58658.458107, 58667.369368, + 58676.280763, 58685.192293, 58694.103957, 58703.015757, 58711.927691, 58720.839760, 58729.751964, 58738.664303, + 58747.576776, 58756.489384, 58765.402127, 58774.315004, 58783.228016, 58792.141162, 58801.054444, 58809.967859, + 58818.881410, 58827.795094, 58836.708914, 58845.622868, 58854.536956, 58863.451179, 58872.365536, 58881.280028, + 58890.194654, 58899.109414, 58908.024309, 58916.939339, 58925.854502, 58934.769800, 58943.685232, 58952.600799, + 58961.516500, 58970.432335, 58979.348304, 58988.264408, 58997.180645, 59006.097017, 59015.013523, 59023.930164, + 59032.846938, 59041.763846, 59050.680889, 59059.598066, 59068.515376, 59077.432821, 59086.350400, 59095.268113, + 59104.185959, 59113.103940, 59122.022055, 59130.940303, 59139.858686, 59148.777202, 59157.695852, 59166.614637, + 59175.533555, 59184.452606, 59193.371792, 59202.291111, 59211.210565, 59220.130151, 59229.049872, 59237.969726, + 59246.889715, 59255.809836, 59264.730092, 59273.650481, 59282.571003, 59291.491660, 59300.412450, 59309.333373, + 59318.254430, 59327.175621, 59336.096945, 59345.018402, 59353.939993, 59362.861718, 59371.783576, 59380.705567, + 59389.627692, 59398.549950, 59407.472342, 59416.394867, 59425.317525, 59434.240317, 59443.163242, 59452.086300, + 59461.009491, 59469.932816, 59478.856274, 59487.779865, 59496.703590, 59505.627447, 59514.551438, 59523.475562, + 59532.399819, 59541.324209, 59550.248732, 59559.173389, 59568.098178, 59577.023100, 59585.948156, 59594.873344, + 59603.798666, 59612.724120, 59621.649707, 59630.575428, 59639.501281, 59648.427267, 59657.353386, 59666.279638, + 59675.206023, 59684.132540, 59693.059190, 59701.985973, 59710.912889, 59719.839938, 59728.767119, 59737.694433, + 59746.621880, 59755.549460, 59764.477172, 59773.405017, 59782.332994, 59791.261104, 59800.189347, 59809.117722, + 59818.046230, 59826.974870, 59835.903643, 59844.832549, 59853.761587, 59862.690757, 59871.620060, 59880.549495, + 59889.479063, 59898.408763, 59907.338596, 59916.268560, 59925.198658, 59934.128887, 59943.059249, 59951.989743, + 59960.920370, 59969.851128, 59978.782019, 59987.713043, 59996.644198, 60005.575486, 60014.506906, 60023.438458, + 60032.370142, 60041.301958, 60050.233906, 60059.165987, 60068.098199, 60077.030544, 60085.963020, 60094.895629, + 60103.828370, 60112.761242, 60121.694247, 60130.627383, 60139.560652, 60148.494052, 60157.427585, 60166.361249, + 60175.295045, 60184.228973, 60193.163032, 60202.097224, 60211.031547, 60219.966002, 60228.900589, 60237.835308, + 60246.770158, 60255.705140, 60264.640254, 60273.575499, 60282.510876, 60291.446385, 60300.382025, 60309.317797, + 60318.253701, 60327.189736, 60336.125903, 60345.062201, 60353.998631, 60362.935192, 60371.871884, 60380.808709, + 60389.745664, 60398.682751, 60407.619970, 60416.557320, 60425.494801, 60434.432413, 60443.370157, 60452.308033, + 60461.246039, 60470.184177, 60479.122446, 60488.060847, 60496.999378, 60505.938041, 60514.876835, 60523.815760, + 60532.754817, 60541.694005, 60550.633323, 60559.572773, 60568.512354, 60577.452066, 60586.391909, 60595.331883, + 60604.271989, 60613.212225, 60622.152592, 60631.093090, 60640.033720, 60648.974480, 60657.915371, 60666.856393, + 60675.797546, 60684.738829, 60693.680244, 60702.621789, 60711.563466, 60720.505273, 60729.447211, 60738.389279, + 60747.331479, 60756.273809, 60765.216270, 60774.158862, 60783.101584, 60792.044437, 60800.987421, 60809.930535, + 60818.873780, 60827.817155, 60836.760662, 60845.704298, 60854.648066, 60863.591963, 60872.535992, 60881.480151, + 60890.424440, 60899.368860, 60908.313410, 60917.258091, 60926.202902, 60935.147843, 60944.092915, 60953.038117, + 60961.983450, 60970.928913, 60979.874506, 60988.820230, 60997.766084, 61006.712068, 61015.658182, 61024.604427, + 61033.550802, 61042.497307, 61051.443942, 61060.390707, 61069.337603, 61078.284628, 61087.231784, 61096.179070, + 61105.126486, 61114.074032, 61123.021708, 61131.969514, 61140.917450, 61149.865516, 61158.813712, 61167.762038, + 61176.710494, 61185.659080, 61194.607796, 61203.556642, 61212.505618, 61221.454723, 61230.403958, 61239.353323, + 61248.302818, 61257.252443, 61266.202198, 61275.152082, 61284.102096, 61293.052240, 61302.002513, 61310.952916, + 61319.903449, 61328.854112, 61337.804904, 61346.755826, 61355.706877, 61364.658058, 61373.609369, 61382.560809, + 61391.512378, 61400.464077, 61409.415906, 61418.367864, 61427.319952, 61436.272169, 61445.224516, 61454.176992, + 61463.129597, 61472.082332, 61481.035196, 61489.988189, 61498.941312, 61507.894564, 61516.847946, 61525.801457, + 61534.755097, 61543.708866, 61552.662764, 61561.616792, 61570.570949, 61579.525235, 61588.479651, 61597.434195, + 61606.388869, 61615.343672, 61624.298603, 61633.253664, 61642.208854, 61651.164173, 61660.119622, 61669.075199, + 61678.030905, 61686.986740, 61695.942704, 61704.898797, 61713.855019, 61722.811370, 61731.767850, 61740.724459, + 61749.681196, 61758.638063, 61767.595058, 61776.552182, 61785.509435, 61794.466817, 61803.424327, 61812.381967, + 61821.339735, 61830.297631, 61839.255657, 61848.213811, 61857.172094, 61866.130505, 61875.089045, 61884.047714, + 61893.006512, 61901.965437, 61910.924492, 61919.883675, 61928.842987, 61937.802427, 61946.761995, 61955.721693, + 61964.681518, 61973.641472, 61982.601555, 61991.561766, 62000.522105, 62009.482573, 62018.443169, 62027.403894, + 62036.364746, 62045.325728, 62054.286837, 62063.248075, 62072.209441, 62081.170935, 62090.132558, 62099.094309, + 62108.056188, 62117.018195, 62125.980330, 62134.942594, 62143.904985, 62152.867505, 62161.830153, 62170.792929, + 62179.755833, 62188.718866, 62197.682026, 62206.645314, 62215.608730, 62224.572275, 62233.535947, 62242.499747, + 62251.463675, 62260.427732, 62269.391916, 62278.356228, 62287.320667, 62296.285235, 62305.249931, 62314.214754, + 62323.179705, 62332.144784, 62341.109991, 62350.075326, 62359.040788, 62368.006378, 62376.972096, 62385.937941, + 62394.903915, 62403.870015, 62412.836244, 62421.802600, 62430.769084, 62439.735695, 62448.702434, 62457.669301, + 62466.636295, 62475.603416, 62484.570666, 62493.538042, 62502.505547, 62511.473178, 62520.440937, 62529.408824, + 62538.376838, 62547.344979, 62556.313248, 62565.281644, 62574.250168, 62583.218819, 62592.187597, 62601.156503, + 62610.125535, 62619.094696, 62628.063983, 62637.033398, 62646.002940, 62654.972609, 62663.942405, 62672.912328, + 62681.882379, 62690.852557, 62699.822862, 62708.793294, 62717.763853, 62726.734539, 62735.705353, 62744.676293, + 62753.647361, 62762.618555, 62771.589876, 62780.561325, 62789.532900, 62798.504603, 62807.476432, 62816.448388, + 62825.420472, 62834.392682, 62843.365019, 62852.337482, 62861.310073, 62870.282791, 62879.255635, 62888.228606, + 62897.201704, 62906.174929, 62915.148280, 62924.121758, 62933.095363, 62942.069095, 62951.042953, 62960.016938, + 62968.991049, 62977.965288, 62986.939652, 62995.914144, 63004.888762, 63013.863507, 63022.838378, 63031.813375, + 63040.788500, 63049.763750, 63058.739128, 63067.714631, 63076.690262, 63085.666018, 63094.641901, 63103.617911, + 63112.594047, 63121.570309, 63130.546697, 63139.523212, 63148.499854, 63157.476621, 63166.453515, 63175.430535, + 63184.407682, 63193.384955, 63202.362354, 63211.339879, 63220.317530, 63229.295308, 63238.273212, 63247.251242, + 63256.229398, 63265.207680, 63274.186088, 63283.164623, 63292.143283, 63301.122070, 63310.100982, 63319.080021, + 63328.059186, 63337.038476, 63346.017893, 63354.997435, 63363.977104, 63372.956898, 63381.936819, 63390.916865, + 63399.897037, 63408.877335, 63417.857759, 63426.838309, 63435.818985, 63444.799786, 63453.780713, 63462.761766, + 63471.742945, 63480.724250, 63489.705680, 63498.687236, 63507.668917, 63516.650725, 63525.632658, 63534.614716, + 63543.596901, 63552.579211, 63561.561646, 63570.544207, 63579.526894, 63588.509706, 63597.492644, 63606.475707, + 63615.458896, 63624.442210, 63633.425650, 63642.409215, 63651.392906, 63660.376722, 63669.360664, 63678.344730, + 63687.328923, 63696.313240, 63705.297684, 63714.282252, 63723.266946, 63732.251765, 63741.236709, 63750.221778, + 63759.206973, 63768.192293, 63777.177739, 63786.163309, 63795.149005, 63804.134826, 63813.120772, 63822.106843, + 63831.093039, 63840.079361, 63849.065807, 63858.052379, 63867.039075, 63876.025897, 63885.012844, 63893.999916, + 63902.987113, 63911.974434, 63920.961881, 63929.949453, 63938.937150, 63947.924971, 63956.912918, 63965.900989, + 63974.889186, 63983.877507, 63992.865953, 64001.854524, 64010.843219, 64019.832040, 64028.820985, 64037.810055, + 64046.799250, 64055.788570, 64064.778014, 64073.767583, 64082.757277, 64091.747095, 64100.737038, 64109.727106, + 64118.717298, 64127.707615, 64136.698057, 64145.688623, 64154.679313, 64163.670129, 64172.661069, 64181.652133, + 64190.643322, 64199.634635, 64208.626073, 64217.617635, 64226.609322, 64235.601133, 64244.593069, 64253.585129, + 64262.577313, 64271.569622, 64280.562055, 64289.554612, 64298.547294, 64307.540100, 64316.533030, 64325.526085, + 64334.519264, 64343.512567, 64352.505994, 64361.499546, 64370.493222, 64379.487022, 64388.480946, 64397.474994, + 64406.469167, 64415.463463, 64424.457884, 64433.452429, 64442.447097, 64451.441890, 64460.436807, 64469.431848, + 64478.427013, 64487.422302, 64496.417715, 64505.413252, 64514.408913, 64523.404698, 64532.400607, 64541.396639, + 64550.392796, 64559.389076, 64568.385481, 64577.382009, 64586.378661, 64595.375437, 64604.372336, 64613.369360, + 64622.366507, 64631.363778, 64640.361172, 64649.358691, 64658.356333, 64667.354098, 64676.351988, 64685.350001, + 64694.348138, 64703.346398, 64712.344782, 64721.343290, 64730.341921, 64739.340676, 64748.339554, 64757.338556, + 64766.337681, 64775.336930, 64784.336303, 64793.335799, 64802.335418, 64811.335161, 64820.335027, 64829.335016, + 64838.335130, 64847.335366, 64856.335726, 64865.336209, 64874.336815, 64883.337545, 64892.338398, 64901.339375, + 64910.340475, 64919.341698, 64928.343044, 64937.344513, 64946.346106, 64955.347822, 64964.349661, 64973.351623, + 64982.353709, 64991.355917, 65000.358249, 65009.360704, 65018.363282, 65027.365983, 65036.368807, 65045.371754, + 65054.374824, 65063.378017, 65072.381334, 65081.384773, 65090.388335, 65099.392020, 65108.395828, 65117.399759, + 65126.403813, 65135.407990, 65144.412290, 65153.416712, 65162.421258, 65171.425926, 65180.430717, 65189.435631, + 65198.440668, 65207.445827, 65216.451110, 65225.456515, 65234.462042, 65243.467693, 65252.473466, 65261.479362, + 65270.485381, 65279.491522, 65288.497786, 65297.504172, 65306.510681, 65315.517313, 65324.524067, 65333.530944, + 65342.537944, 65351.545066, 65360.552310, 65369.559677, 65378.567167, 65387.574779, 65396.582513, 65405.590370, + 65414.598350, 65423.606451, 65432.614676, 65441.623022, 65450.631491, 65459.640082, 65468.648796, 65477.657632, + 65486.666590, 65495.675671, 65504.684874, 65513.694199, 65522.703647, 65531.713216, 65540.722908, 65549.732722, + 65558.742659, 65567.752717, 65576.762898, 65585.773200, 65594.783625, 65603.794172, 65612.804842, 65621.815633, + 65630.826546, 65639.837582, 65648.848739, 65657.860019, 65666.871420, 65675.882944, 65684.894589, 65693.906357, + 65702.918246, 65711.930257, 65720.942391, 65729.954646, 65738.967023, 65747.979522, 65756.992143, 65766.004886, + 65775.017750, 65784.030737, 65793.043845, 65802.057075, 65811.070427, 65820.083900, 65829.097495, 65838.111213, + 65847.125051, 65856.139012, 65865.153094, 65874.167298, 65883.181623, 65892.196070, 65901.210639, 65910.225329, + 65919.240141, 65928.255075, 65937.270130, 65946.285307, 65955.300605, 65964.316025, 65973.331566, 65982.347229, + 65991.363013, 66000.378919, 66009.394946, 66018.411095, 66027.427365, 66036.443756, 66045.460269, 66054.476904, + 66063.493659, 66072.510536, 66081.527534, 66090.544654, 66099.561895, 66108.579257, 66117.596741, 66126.614346, + 66135.632072, 66144.649919, 66153.667887, 66162.685977, 66171.704188, 66180.722520, 66189.740973, 66198.759548, + 66207.778243, 66216.797060, 66225.815997, 66234.835056, 66243.854236, 66252.873537, 66261.892959, 66270.912502, + 66279.932166, 66288.951951, 66297.971857, 66306.991884, 66316.012032, 66325.032301, 66334.052690, 66343.073201, + 66352.093833, 66361.114585, 66370.135459, 66379.156453, 66388.177568, 66397.198804, 66406.220160, 66415.241638, + 66424.263236, 66433.284955, 66442.306795, 66451.328755, 66460.350837, 66469.373038, 66478.395361, 66487.417804, + 66496.440368, 66505.463053, 66514.485858, 66523.508784, 66532.531831, 66541.554998, 66550.578285, 66559.601693, + 66568.625222, 66577.648871, 66586.672641, 66595.696532, 66604.720542, 66613.744674, 66622.768925, 66631.793298, + 66640.817790, 66649.842403, 66658.867137, 66667.891990, 66676.916965, 66685.942059, 66694.967274, 66703.992609, + 66713.018065, 66722.043641, 66731.069337, 66740.095153, 66749.121090, 66758.147147, 66767.173324, 66776.199621, + 66785.226039, 66794.252576, 66803.279234, 66812.306012, 66821.332911, 66830.359929, 66839.387067, 66848.414326, + 66857.441704, 66866.469203, 66875.496822, 66884.524561, 66893.552419, 66902.580398, 66911.608497, 66920.636716, + 66929.665055, 66938.693513, 66947.722092, 66956.750791, 66965.779609, 66974.808547, 66983.837606, 66992.866784, + 67001.896082, 67010.925500, 67019.955037, 67028.984695, 67038.014472, 67047.044369, 67056.074386, 67065.104522, + 67074.134779, 67083.165155, 67092.195651, 67101.226266, 67110.257001, 67119.287856, 67128.318830, 67137.349924, + 67146.381138, 67155.412471, 67164.443924, 67173.475497, 67182.507189, 67191.539001, 67200.570932, 67209.602982, + 67218.635153, 67227.667442, 67236.699851, 67245.732380, 67254.765028, 67263.797796, 67272.830683, 67281.863689, + 67290.896815, 67299.930060, 67308.963424, 67317.996908, 67327.030511, 67336.064234, 67345.098076, 67354.132037, + 67363.166117, 67372.200317, 67381.234636, 67390.269074, 67399.303631, 67408.338308, 67417.373104, 67426.408019, + 67435.443053, 67444.478206, 67453.513479, 67462.548870, 67471.584381, 67480.620011, 67489.655760, 67498.691628, + 67507.727615, 67516.763721, 67525.799946, 67534.836290, 67543.872753, 67552.909335, 67561.946036, 67570.982856, + 67580.019795, 67589.056853, 67598.094029, 67607.131325, 67616.168739, 67625.206273, 67634.243925, 67643.281696, + 67652.319586, 67661.357595, 67670.395722, 67679.433969, 67688.472334, 67697.510818, 67706.549420, 67715.588142, + 67724.626982, 67733.665941, 67742.705018, 67751.744214, 67760.783529, 67769.822962, 67778.862514, 67787.902185, + 67796.941974, 67805.981882, 67815.021909, 67824.062054, 67833.102317, 67842.142699, 67851.183200, 67860.223819, + 67869.264556, 67878.305413, 67887.346387, 67896.387480, 67905.428691, 67914.470021, 67923.511469, 67932.553036, + 67941.594721, 67950.636525, 67959.678446, 67968.720486, 67977.762645, 67986.804921, 67995.847316, 68004.889830, + 68013.932461, 68022.975211, 68032.018079, 68041.061065, 68050.104170, 68059.147392, 68068.190733, 68077.234192, + 68086.277769, 68095.321465, 68104.365278, 68113.409209, 68122.453259, 68131.497427, 68140.541713, 68149.586116, + 68158.630638, 68167.675278, 68176.720036, 68185.764912, 68194.809906, 68203.855018, 68212.900248, 68221.945596, + 68230.991061, 68240.036645, 68249.082347, 68258.128166, 68267.174103, 68276.220158, 68285.266331, 68294.312622, + 68303.359031, 68312.405558, 68321.452202, 68330.498964, 68339.545844, 68348.592841, 68357.639957, 68366.687190, + 68375.734540, 68384.782009, 68393.829595, 68402.877299, 68411.925120, 68420.973059, 68430.021116, 68439.069290, + 68448.117582, 68457.165992, 68466.214519, 68475.263163, 68484.311926, 68493.360805, 68502.409802, 68511.458917, + 68520.508149, 68529.557499, 68538.606966, 68547.656551, 68556.706253, 68565.756072, 68574.806009, 68583.856063, + 68592.906235, 68601.956524, 68611.006930, 68620.057454, 68629.108095, 68638.158853, 68647.209729, 68656.260722, + 68665.311832, 68674.363059, 68683.414404, 68692.465866, 68701.517445, 68710.569141, 68719.620955, 68728.672885, + 68737.724933, 68746.777098, 68755.829380, 68764.881779, 68773.934296, 68782.986929, 68792.039679, 68801.092547, + 68810.145531, 68819.198633, 68828.251852, 68837.305187, 68846.358640, 68855.412210, 68864.465896, 68873.519700, + 68882.573620, 68891.627657, 68900.681812, 68909.736083, 68918.790471, 68927.844976, 68936.899598, 68945.954336, + 68955.009192, 68964.064164, 68973.119253, 68982.174459, 68991.229782, 69000.285221, 69009.340777, 69018.396450, + 69027.452240, 69036.508146, 69045.564169, 69054.620309, 69063.676565, 69072.732938, 69081.789428, 69090.846034, + 69099.902757, 69108.959596, 69118.016553, 69127.073625, 69136.130814, 69145.188120, 69154.245542, 69163.303081, + 69172.360736, 69181.418508, 69190.476396, 69199.534401, 69208.592522, 69217.650760, 69226.709114, 69235.767584, + 69244.826171, 69253.884874, 69262.943694, 69272.002630, 69281.061682, 69290.120851, 69299.180136, 69308.239537, + 69317.299054, 69326.358688, 69335.418438, 69344.478304, 69353.538287, 69362.598385, 69371.658600, 69380.718931, + 69389.779379, 69398.839942, 69407.900622, 69416.961418, 69426.022329, 69435.083357, 69444.144501, 69453.205762, + 69462.267138, 69471.328630, 69480.390238, 69489.451963, 69498.513803, 69507.575759, 69516.637832, 69525.700020, + 69534.762324, 69543.824745, 69552.887281, 69561.949933, 69571.012701, 69580.075585, 69589.138585, 69598.201700, + 69607.264932, 69616.328279, 69625.391742, 69634.455321, 69643.519016, 69652.582827, 69661.646753, 69670.710795, + 69679.774953, 69688.839227, 69697.903616, 69706.968121, 69716.032742, 69725.097478, 69734.162330, 69743.227298, + 69752.292381, 69761.357580, 69770.422895, 69779.488325, 69788.553871, 69797.619532, 69806.685309, 69815.751202, + 69824.817210, 69833.883333, 69842.949572, 69852.015927, 69861.082397, 69870.148982, 69879.215683, 69888.282499, + 69897.349431, 69906.416478, 69915.483641, 69924.550919, 69933.618312, 69942.685821, 69951.753445, 69960.821185, + 69969.889039, 69978.957009, 69988.025095, 69997.093295, 70006.161611, 70015.230042, 70024.298589, 70033.367250, + 70042.436027, 70051.504919, 70060.573926, 70069.643049, 70078.712286, 70087.781639, 70096.851107, 70105.920690, + 70114.990388, 70124.060201, 70133.130129, 70142.200172, 70151.270331, 70160.340604, 70169.410992, 70178.481496, + 70187.552114, 70196.622848, 70205.693696, 70214.764659, 70223.835738, 70232.906931, 70241.978239, 70251.049662, + 70260.121200, 70269.192853, 70278.264621, 70287.336503, 70296.408501, 70305.480613, 70314.552840, 70323.625182, + 70332.697639, 70341.770210, 70350.842896, 70359.915697, 70368.988613, 70378.061643, 70387.134788, 70396.208048, + 70405.281423, 70414.354912, 70423.428516, 70432.502234, 70441.576067, 70450.650015, 70459.724078, 70468.798254, + 70477.872546, 70486.946952, 70496.021473, 70505.096108, 70514.170858, 70523.245722, 70532.320701, 70541.395794, + 70550.471002, 70559.546324, 70568.621760, 70577.697311, 70586.772977, 70595.848757, 70604.924651, 70614.000660, + 70623.076783, 70632.153020, 70641.229372, 70650.305838, 70659.382418, 70668.459113, 70677.535922, 70686.612845, + 70695.689883, 70704.767034, 70713.844300, 70722.921681, 70731.999175, 70741.076784, 70750.154507, 70759.232344, + 70768.310295, 70777.388360, 70786.466540, 70795.544833, 70804.623241, 70813.701763, 70822.780399, 70831.859149, + 70840.938013, 70850.016991, 70859.096083, 70868.175289, 70877.254609, 70886.334043, 70895.413591, 70904.493253, + 70913.573029, 70922.652919, 70931.732923, 70940.813041, 70949.893272, 70958.973618, 70968.054077, 70977.134651, + 70986.215338, 70995.296139, 71004.377054, 71013.458082, 71022.539225, 71031.620481, 71040.701851, 71049.783335, + 71058.864932, 71067.946644, 71077.028469, 71086.110407, 71095.192460, 71104.274626, 71113.356905, 71122.439299, + 71131.521806, 71140.604426, 71149.687160, 71158.770008, 71167.852970, 71176.936045, 71186.019233, 71195.102536, + 71204.185951, 71213.269480, 71222.353123, 71231.436879, 71240.520749, 71249.604732, 71258.688829, 71267.773039, + 71276.857363, 71285.941799, 71295.026350, 71304.111014, 71313.195791, 71322.280681, 71331.365685, 71340.450802, + 71349.536033, 71358.621377, 71367.706834, 71376.792404, 71385.878088, 71394.963885, 71404.049796, 71413.135819, + 71422.221956, 71431.308206, 71440.394569, 71449.481045, 71458.567635, 71467.654338, 71476.741154, 71485.828083, + 71494.915125, 71504.002280, 71513.089548, 71522.176930, 71531.264424, 71540.352032, 71549.439753, 71558.527586, + 71567.615533, 71576.703593, 71585.791766, 71594.880051, 71603.968450, 71613.056962, 71622.145586, 71631.234324, + 71640.323174, 71649.412138, 71658.501214, 71667.590403, 71676.679705, 71685.769120, 71694.858648, 71703.948288, + 71713.038042, 71722.127908, 71731.217887, 71740.307979, 71749.398184, 71758.488501, 71767.578931, 71776.669474, + 71785.760129, 71794.850897, 71803.941778, 71813.032772, 71822.123878, 71831.215097, 71840.306429, 71849.397873, + 71858.489430, 71867.581099, 71876.672881, 71885.764776, 71894.856783, 71903.948903, 71913.041135, 71922.133480, + 71931.225937, 71940.318507, 71949.411190, 71958.503984, 71967.596892, 71976.689911, 71985.783043, 71994.876288, + 72003.969645, 72013.063115, 72022.156696, 72031.250391, 72040.344197, 72049.438116, 72058.532147, 72067.626291, + 72076.720547, 72085.814915, 72094.909395, 72104.003988, 72113.098693, 72122.193510, 72131.288440, 72140.383482, + 72149.478636, 72158.573902, 72167.669280, 72176.764771, 72185.860373, 72194.956088, 72204.051915, 72213.147854, + 72222.243906, 72231.340069, 72240.436344, 72249.532732, 72258.629231, 72267.725843, 72276.822567, 72285.919402, + 72295.016350, 72304.113410, 72313.210581, 72322.307865, 72331.405261, 72340.502768, 72349.600388, 72358.698119, + 72367.795962, 72376.893918, 72385.991985, 72395.090164, 72404.188455, 72413.286857, 72422.385372, 72431.483998, + 72440.582737, 72449.681587, 72458.780548, 72467.879622, 72476.978807, 72486.078104, 72495.177513, 72504.277034, + 72513.376666, 72522.476410, 72531.576265, 72540.676233, 72549.776312, 72558.876502, 72567.976805, 72577.077219, + 72586.177744, 72595.278381, 72604.379130, 72613.479990, 72622.580962, 72631.682045, 72640.783240, 72649.884547, + 72658.985965, 72668.087494, 72677.189135, 72686.290888, 72695.392751, 72704.494727, 72713.596814, 72722.699012, + 72731.801321, 72740.903742, 72750.006275, 72759.108919, 72768.211674, 72777.314540, 72786.417518, 72795.520607, + 72804.623808, 72813.727120, 72822.830543, 72831.934077, 72841.037723, 72850.141480, 72859.245348, 72868.349327, + 72877.453418, 72886.557619, 72895.661932, 72904.766357, 72913.870892, 72922.975538, 72932.080296, 72941.185165, + 72950.290145, 72959.395236, 72968.500438, 72977.605751, 72986.711175, 72995.816710, 73004.922356, 73014.028114, + 73023.133982, 73032.239962, 73041.346052, 73050.452253, 73059.558566, 73068.664989, 73077.771523, 73086.878168, + 73095.984924, 73105.091791, 73114.198769, 73123.305858, 73132.413057, 73141.520368, 73150.627789, 73159.735321, + 73168.842964, 73177.950718, 73187.058583, 73196.166558, 73205.274644, 73214.382841, 73223.491149, 73232.599567, + 73241.708096, 73250.816736, 73259.925486, 73269.034348, 73278.143320, 73287.252402, 73296.361595, 73305.470899, + 73314.580314, 73323.689839, 73332.799474, 73341.909221, 73351.019077, 73360.129045, 73369.239123, 73378.349311, + 73387.459610, 73396.570020, 73405.680540, 73414.791170, 73423.901911, 73433.012763, 73442.123725, 73451.234797, + 73460.345980, 73469.457273, 73478.568677, 73487.680191, 73496.791815, 73505.903550, 73515.015395, 73524.127351, + 73533.239416, 73542.351592, 73551.463879, 73560.576276, 73569.688783, 73578.801400, 73587.914127, 73597.026965, + 73606.139913, 73615.252972, 73624.366140, 73633.479419, 73642.592808, 73651.706307, 73660.819916, 73669.933635, + 73679.047465, 73688.161404, 73697.275454, 73706.389614, 73715.503884, 73724.618264, 73733.732754, 73742.847354, + 73751.962064, 73761.076884, 73770.191814, 73779.306854, 73788.422005, 73797.537265, 73806.652635, 73815.768115, + 73824.883705, 73833.999405, 73843.115215, 73852.231135, 73861.347164, 73870.463304, 73879.579553, 73888.695913, + 73897.812382, 73906.928961, 73916.045650, 73925.162448, 73934.279357, 73943.396375, 73952.513503, 73961.630741, + 73970.748088, 73979.865545, 73988.983112, 73998.100789, 74007.218575, 74016.336472, 74025.454477, 74034.572593, + 74043.690818, 74052.809153, 74061.927597, 74071.046151, 74080.164814, 74089.283588, 74098.402470, 74107.521463, + 74116.640565, 74125.759776, 74134.879097, 74143.998528, 74153.118068, 74162.237717, 74171.357476, 74180.477344, + 74189.597322, 74198.717410, 74207.837607, 74216.957913, 74226.078329, 74235.198854, 74244.319488, 74253.440232, + 74262.561085, 74271.682048, 74280.803120, 74289.924301, 74299.045591, 74308.166991, 74317.288500, 74326.410119, + 74335.531847, 74344.653684, 74353.775630, 74362.897685, 74372.019850, 74381.142124, 74390.264507, 74399.386999, + 74408.509601, 74417.632311, 74426.755131, 74435.878060, 74445.001098, 74454.124245, 74463.247501, 74472.370867, + 74481.494341, 74490.617925, 74499.741617, 74508.865419, 74517.989330, 74527.113349, 74536.237478, 74545.361716, + 74554.486062, 74563.610518, 74572.735082, 74581.859756, 74590.984538, 74600.109430, 74609.234430, 74618.359539, + 74627.484758, 74636.610085, 74645.735520, 74654.861065, 74663.986719, 74673.112481, 74682.238352, 74691.364332, + 74700.490421, 74709.616619, 74718.742925, 74727.869340, 74736.995864, 74746.122497, 74755.249238, 74764.376088, + 74773.503047, 74782.630114, 74791.757290, 74800.884575, 74810.011969, 74819.139471, 74828.267082, 74837.394801, + 74846.522629, 74855.650565, 74864.778611, 74873.906764, 74883.035026, 74892.163397, 74901.291877, 74910.420465, + 74919.549161, 74928.677966, 74937.806879, 74946.935901, 74956.065031, 74965.194270, 74974.323617, 74983.453073, + 74992.582637, 75001.712309, 75010.842090, 75019.971980, 75029.101977, 75038.232083, 75047.362298, 75056.492620, + 75065.623051, 75074.753590, 75083.884238, 75093.014994, 75102.145858, 75111.276831, 75120.407911, 75129.539100, + 75138.670397, 75147.801803, 75156.933316, 75166.064938, 75175.196668, 75184.328506, 75193.460453, 75202.592507, + 75211.724670, 75220.856940, 75229.989319, 75239.121806, 75248.254401, 75257.387104, 75266.519915, 75275.652835, + 75284.785862, 75293.918997, 75303.052240, 75312.185592, 75321.319051, 75330.452618, 75339.586294, 75348.720077, + 75357.853968, 75366.987967, 75376.122074, 75385.256289, 75394.390612, 75403.525043, 75412.659582, 75421.794228, + 75430.928983, 75440.063845, 75449.198815, 75458.333893, 75467.469078, 75476.604372, 75485.739773, 75494.875282, + 75504.010899, 75513.146624, 75522.282456, 75531.418396, 75540.554444, 75549.690599, 75558.826863, 75567.963233, + 75577.099712, 75586.236298, 75595.372992, 75604.509793, 75613.646702, 75622.783719, 75631.920843, 75641.058075, + 75650.195415, 75659.332862, 75668.470417, 75677.608079, 75686.745848, 75695.883726, 75705.021710, 75714.159802, + 75723.298002, 75732.436309, 75741.574724, 75750.713246, 75759.851876, 75768.990613, 75778.129457, 75787.268409, + 75796.407468, 75805.546634, 75814.685908, 75823.825290, 75832.964778, 75842.104374, 75851.244077, 75860.383888, + 75869.523806, 75878.663831, 75887.803964, 75896.944203, 75906.084550, 75915.225005, 75924.365566, 75933.506235, + 75942.647011, 75951.787894, 75960.928884, 75970.069982, 75979.211186, 75988.352498, 75997.493917, 76006.635443, + 76015.777076, 76024.918816, 76034.060664, 76043.202618, 76052.344680, 76061.486848, 76070.629124, 76079.771507, + 76088.913996, 76098.056593, 76107.199297, 76116.342108, 76125.485025, 76134.628050, 76143.771182, 76152.914420, + 76162.057766, 76171.201218, 76180.344777, 76189.488444, 76198.632217, 76207.776097, 76216.920084, 76226.064177, + 76235.208378, 76244.352685, 76253.497100, 76262.641621, 76271.786248, 76280.930983, 76290.075824, 76299.220773, + 76308.365828, 76317.510989, 76326.656258, 76335.801633, 76344.947114, 76354.092703, 76363.238398, 76372.384200, + 76381.530108, 76390.676124, 76399.822245, 76408.968474, 76418.114809, 76427.261251, 76436.407799, 76445.554454, + 76454.701215, 76463.848083, 76472.995057, 76482.142138, 76491.289326, 76500.436620, 76509.584021, 76518.731528, + 76527.879141, 76537.026861, 76546.174688, 76555.322621, 76564.470660, 76573.618806, 76582.767058, 76591.915417, + 76601.063882, 76610.212453, 76619.361131, 76628.509915, 76637.658805, 76646.807802, 76655.956905, 76665.106114, + 76674.255430, 76683.404852, 76692.554380, 76701.704015, 76710.853755, 76720.003602, 76729.153556, 76738.303615, + 76747.453781, 76756.604052, 76765.754431, 76774.904915, 76784.055505, 76793.206202, 76802.357004, 76811.507913, + 76820.658928, 76829.810049, 76838.961276, 76848.112609, 76857.264049, 76866.415594, 76875.567245, 76884.719003, + 76893.870866, 76903.022836, 76912.174911, 76921.327092, 76930.479380, 76939.631773, 76948.784273, 76957.936878, + 76967.089589, 76976.242406, 76985.395330, 76994.548359, 77003.701493, 77012.854734, 77022.008081, 77031.161533, + 77040.315092, 77049.468756, 77058.622526, 77067.776402, 77076.930383, 77086.084471, 77095.238664, 77104.392963, + 77113.547368, 77122.701878, 77131.856495, 77141.011216, 77150.166044, 77159.320977, 77168.476017, 77177.631161, + 77186.786412, 77195.941768, 77205.097229, 77214.252797, 77223.408470, 77232.564248, 77241.720133, 77250.876122, + 77260.032218, 77269.188419, 77278.344725, 77287.501137, 77296.657655, 77305.814278, 77314.971006, 77324.127840, + 77333.284780, 77342.441825, 77351.598976, 77360.756232, 77369.913593, 77379.071060, 77388.228632, 77397.386310, + 77406.544093, 77415.701982, 77424.859976, 77434.018075, 77443.176279, 77452.334589, 77461.493005, 77470.651525, + 77479.810151, 77488.968883, 77498.127719, 77507.286661, 77516.445708, 77525.604860, 77534.764118, 77543.923481, + 77553.082949, 77562.242522, 77571.402200, 77580.561984, 77589.721873, 77598.881867, 77608.041966, 77617.202170, + 77626.362480, 77635.522894, 77644.683414, 77653.844039, 77663.004769, 77672.165604, 77681.326544, 77690.487589, + 77699.648739, 77708.809994, 77717.971354, 77727.132819, 77736.294390, 77745.456065, 77754.617845, 77763.779730, + 77772.941720, 77782.103815, 77791.266015, 77800.428320, 77809.590730, 77818.753245, 77827.915864, 77837.078589, + 77846.241418, 77855.404353, 77864.567392, 77873.730536, 77882.893784, 77892.057138, 77901.220596, 77910.384160, + 77919.547828, 77928.711600, 77937.875478, 77947.039460, 77956.203547, 77965.367739, 77974.532035, 77983.696436, + 77992.860942, 78002.025553, 78011.190268, 78020.355088, 78029.520012, 78038.685041, 78047.850175, 78057.015414, + 78066.180757, 78075.346204, 78084.511756, 78093.677413, 78102.843174, 78112.009040, 78121.175011, 78130.341086, + 78139.507265, 78148.673549, 78157.839938, 78167.006431, 78176.173028, 78185.339730, 78194.506536, 78203.673447, + 78212.840462, 78222.007582, 78231.174806, 78240.342135, 78249.509568, 78258.677105, 78267.844746, 78277.012492, + 78286.180343, 78295.348297, 78304.516356, 78313.684520, 78322.852787, 78332.021159, 78341.189635, 78350.358216, + 78359.526900, 78368.695689, 78377.864583, 78387.033580, 78396.202682, 78405.371887, 78414.541197, 78423.710612, + 78432.880130, 78442.049753, 78451.219479, 78460.389310, 78469.559245, 78478.729284, 78487.899427, 78497.069675, + 78506.240026, 78515.410481, 78524.581041, 78533.751704, 78542.922472, 78552.093344, 78561.264319, 78570.435399, + 78579.606583, 78588.777870, 78597.949262, 78607.120757, 78616.292357, 78625.464060, 78634.635868, 78643.807779, + 78652.979794, 78662.151914, 78671.324137, 78680.496464, 78689.668894, 78698.841429, 78708.014068, 78717.186810, + 78726.359656, 78735.532606, 78744.705660, 78753.878817, 78763.052079, 78772.225444, 78781.398913, 78790.572485, + 78799.746162, 78808.919942, 78818.093826, 78827.267813, 78836.441905, 78845.616100, 78854.790398, 78863.964800, + 78873.139306, 78882.313916, 78891.488629, 78900.663446, 78909.838366, 78919.013390, 78928.188518, 78937.363749, + 78946.539084, 78955.714522, 78964.890064, 78974.065710, 78983.241458, 78992.417311, 79001.593267, 79010.769326, + 79019.945489, 79029.121756, 79038.298125, 79047.474599, 79056.651175, 79065.827856, 79075.004639, 79084.181526, + 79093.358517, 79102.535610, 79111.712808, 79120.890108, 79130.067512, 79139.245019, 79148.422630, 79157.600344, + 79166.778161, 79175.956081, 79185.134105, 79194.312232, 79203.490462, 79212.668796, 79221.847233, 79231.025773, + 79240.204416, 79249.383163, 79258.562012, 79267.740965, 79276.920021, 79286.099181, 79295.278443, 79304.457809, + 79313.637277, 79322.816849, 79331.996524, 79341.176302, 79350.356183, 79359.536168, 79368.716255, 79377.896445, + 79387.076739, 79396.257135, 79405.437635, 79414.618237, 79423.798943, 79432.979751, 79442.160663, 79451.341678, + 79460.522795, 79469.704016, 79478.885339, 79488.066765, 79497.248295, 79506.429927, 79515.611662, 79524.793500, + 79533.975441, 79543.157485, 79552.339631, 79561.521881, 79570.704233, 79579.886688, 79589.069246, 79598.251907, + 79607.434671, 79616.617537, 79625.800506, 79634.983578, 79644.166753, 79653.350030, 79662.533410, 79671.716893, + 79680.900479, 79690.084167, 79699.267958, 79708.451852, 79717.635849, 79726.819948, 79736.004149, 79745.188454, + 79754.372861, 79763.557370, 79772.741982, 79781.926697, 79791.111515, 79800.296435, 79809.481457, 79818.666582, + 79827.851810, 79837.037140, 79846.222573, 79855.408108, 79864.593746, 79873.779486, 79882.965329, 79892.151274, + 79901.337322, 79910.523472, 79919.709725, 79928.896080, 79938.082537, 79947.269097, 79956.455759, 79965.642524, + 79974.829391, 79984.016360, 79993.203432, 80002.390606, 80011.577882, 80020.765261, 80029.952742, 80039.140326, + 80048.328011, 80057.515799, 80066.703690, 80075.891682, 80085.079777, 80094.267974, 80103.456273, 80112.644675, + 80121.833178, 80131.021784, 80140.210492, 80149.399302, 80158.588215, 80167.777229, 80176.966346, 80186.155565, + 80195.344886, 80204.534309, 80213.723834, 80222.913462, 80232.103191, 80241.293023, 80250.482956, 80259.672992, + 80268.863130, 80278.053369, 80287.243711, 80296.434155, 80305.624700, 80314.815348, 80324.006098, 80333.196950, + 80342.387903, 80351.578959, 80360.770116, 80369.961376, 80379.152737, 80388.344201, 80397.535766, 80406.727433, + 80415.919202, 80425.111073, 80434.303045, 80443.495120, 80452.687296, 80461.879575, 80471.071955, 80480.264437, + 80489.457020, 80498.649706, 80507.842493, 80517.035382, 80526.228373, 80535.421465, 80544.614659, 80553.807955, + 80563.001353, 80572.194852, 80581.388453, 80590.582156, 80599.775960, 80608.969866, 80618.163874, 80627.357984, + 80636.552195, 80645.746507, 80654.940921, 80664.135437, 80673.330055, 80682.524774, 80691.719594, 80700.914516, + 80710.109540, 80719.304665, 80728.499892, 80737.695220, 80746.890650, 80756.086181, 80765.281814, 80774.477548, + 80783.673384, 80792.869321, 80802.065360, 80811.261500, 80820.457741, 80829.654084, 80838.850528, 80848.047074, + 80857.243721, 80866.440469, 80875.637319, 80884.834270, 80894.031323, 80903.228476, 80912.425732, 80921.623088, + 80930.820546, 80940.018105, 80949.215765, 80958.413527, 80967.611390, 80976.809354, 80986.007419, 80995.205586, + 81004.403853, 81013.602222, 81022.800693, 81031.999264, 81041.197937, 81050.396710, 81059.595585, 81068.794561, + 81077.993638, 81087.192817, 81096.392096, 81105.591477, 81114.790958, 81123.990541, 81133.190225, 81142.390010, + 81151.589896, 81160.789883, 81169.989971, 81179.190160, 81188.390450, 81197.590841, 81206.791333, 81215.991926, + 81225.192620, 81234.393415, 81243.594311, 81252.795307, 81261.996405, 81271.197604, 81280.398904, 81289.600304, + 81298.801805, 81308.003408, 81317.205111, 81326.406915, 81335.608820, 81344.810826, 81354.012932, 81363.215140, + 81372.417448, 81381.619857, 81390.822367, 81400.024977, 81409.227689, 81418.430501, 81427.633413, 81436.836427, + 81446.039541, 81455.242756, 81464.446072, 81473.649489, 81482.853006, 81492.056624, 81501.260342, 81510.464161, + 81519.668081, 81528.872102, 81538.076223, 81547.280444, 81556.484767, 81565.689189, 81574.893713, 81584.098337, + 81593.303062, 81602.507887, 81611.712813, 81620.917839, 81630.122966, 81639.328193, 81648.533521, 81657.738949, + 81666.944478, 81676.150107, 81685.355837, 81694.561667, 81703.767598, 81712.973629, 81722.179761, 81731.385992, + 81740.592325, 81749.798758, 81759.005291, 81768.211924, 81777.418658, 81786.625492, 81795.832427, 81805.039462, + 81814.246597, 81823.453833, 81832.661168, 81841.868605, 81851.076141, 81860.283778, 81869.491515, 81878.699352, + 81887.907290, 81897.115327, 81906.323465, 81915.531703, 81924.740042, 81933.948480, 81943.157019, 81952.365658, + 81961.574397, 81970.783236, 81979.992176, 81989.201215, 81998.410355, 82007.619595, 82016.828935, 82026.038374, + 82035.247915, 82044.457555, 82053.667295, 82062.877135, 82072.087075, 82081.297116, 82090.507256, 82099.717496, + 82108.927837 + }; + +/* Nat log values for 0.1, 0.2, 0.3, etc. */ /* Used instead of repeatedly calculating them. */ -double log_win10[] = +double log_win10[] = { 0.0, -2.30258509, -1.60943791, -1.203982804, -0.91629073, -0.6931478, -0.510825623, -0.356674944, -0.22314355, -0.105360515, 0.0 -}; +}; @@ -1346,7 +1343,7 @@ typedef struct SSequence Boolean punctuation; /**< FIXME: always FALSE, never set to TRUE? */ Int4* composition; /**< totals number of each type of residue */ Int4* state; /**< "state vector as described on pg. 151 of Wootton and Federhen - (Comput. Chem. 17, 149 (1993)). Tracks number of each residue, + (Comput. Chem. 17, 149 (1993)). Tracks number of each residue, like composition, but without gaps in array. */ double entropy; /**< entropy of what this array refers to. */ } SSequence; @@ -1360,7 +1357,7 @@ typedef struct SSeg } SSeg; /** Initializes SSequence structure */ -static SSequence* +static SSequence* s_SSequenceNew(void) { SSequence* seq; @@ -1388,7 +1385,7 @@ s_SSequenceNew(void) /** Frees the Alpha structure and underlying structures. * @param palpha the object to be freed [in] */ -static void +static void s_AlphaFree (Alpha* palpha) { @@ -1406,7 +1403,7 @@ s_AlphaFree (Alpha* palpha) /** Frees the SSequence structure and the underlying structure * @param seq the object to be freed [in] */ -static void +static void s_SSequenceFree(SSequence* seq) { if (seq==NULL) return; @@ -1424,7 +1421,7 @@ s_SSequenceFree(SSequence* seq) /** Frees the SSeg structure * @param seg the object to be freed [in] */ -static void +static void s_SegFree(SSeg* seg) { SSeg* nextseg; @@ -1445,7 +1442,7 @@ s_SegFree(SSeg* seg) * @param win SSequence structure for a piece of a sequence [in] * @return TRUE if dash is found in the sequence, otherwise FALSE [in] */ -static Boolean +static Boolean s_HasDash(SSequence* win) { char *seq, *seqmax; @@ -1463,7 +1460,7 @@ s_HasDash(SSequence* win) /*------------------------------------------------------------(state_cmp)---*/ /** State comparison function */ -static int +static int s_StateCmp(const void* s1, const void* s2) { int *np1, *np2; @@ -1476,10 +1473,10 @@ s_StateCmp(const void* s1, const void* s2) /*---------------------------------------------------------------(compon)---*/ -/** Calculates sequence composition array values. +/** Calculates sequence composition array values. * @param win the object to be analyzed [in] */ -static void +static void s_CompOn(SSequence* win) { @@ -1503,7 +1500,7 @@ s_CompOn(SSequence* win) letter = *seq++; if (!alphaflag[letter]) comp[alphaindex[letter]]++; - else + else win->bogus++; } @@ -1512,10 +1509,10 @@ s_CompOn(SSequence* win) /*--------------------------------------------------------------(stateon)---*/ -/** Calculates state array values +/** Calculates state array values * @param win the object to be analyzed [in] */ -static void +static void s_StateOn(SSequence* win) { @@ -1551,7 +1548,7 @@ s_StateOn(SSequence* win) * @param length Window length in parent [in] * @return Pointer to the resulting SSequence structure. */ -static SSequence* +static SSequence* s_OpenWin(SSequence* parent, Int4 start, Int4 length) { SSequence* win; @@ -1588,11 +1585,11 @@ s_OpenWin(SSequence* parent, Int4 start, Int4 length) /*--------------------------------------------------------------(s_Entropy)---*/ -/** Calculates entropy of an integer array +/** Calculates entropy of an integer array * @param sv array to be analyzed [in] * @return the entropy */ -static double +static double s_Entropy(Int4* sv) { double ent; @@ -1612,7 +1609,7 @@ s_Entropy(Int4* sv) { ent += ((double)sv[i])*log_win10[sv[i]]/NCBIMATH_LN2; } - + } else { @@ -1636,7 +1633,7 @@ s_Entropy(Int4* sv) * @param sv the array to be examined and decremented [in|out] * @param class criteria for decrementing an element [in] */ -static void +static void s_DecrementSV(Int4* sv, Int4 class) { @@ -1654,7 +1651,7 @@ s_DecrementSV(Int4* sv, Int4 class) * @param sv the array to be examined and incremented [in|out] * @param class criteria for incrementing an element [in] */ -static void +static void s_IncrementSV(Int4* sv, Int4 class) { @@ -1672,48 +1669,53 @@ s_IncrementSV(Int4* sv, Int4 class) * @return FALSE if nothing done, TRUE otherwise */ -static Boolean +static Boolean s_ShiftWin1(SSequence* win) { - Int4 j, length; - Int4* comp; - Int4* alphaindex; - unsigned char* alphaflag; + Uint4 j, length; + Int4* comp; + Int4* alphaindex; + unsigned char* alphaflag; - length = win->length; - comp = win->composition; - alphaindex = win->palpha->alphaindex; - alphaflag = win->palpha->alphaflag; + length = (Uint4) win->length; + comp = win->composition; + alphaindex = win->palpha->alphaindex; + alphaflag = win->palpha->alphaflag; - if ((++win->start + length) > win->parent->length) { - --win->start; - return FALSE; - } + if ((Uint1) win->seq[length] == FENCE_SENTRY) { + return FALSE; + } + if ((++win->start + length) > win->parent->length) { + --win->start; + return FALSE; + } + + j = (Uint1) win->seq[0]; /* prevent sign-extension */ - if (!alphaflag[j = win->seq[0]]) - s_DecrementSV(win->state, comp[alphaindex[j]]--); - else win->bogus--; + if (!alphaflag[j]) + s_DecrementSV(win->state, comp[alphaindex[j]]--); + else win->bogus--; - j = win->seq[length]; - ++win->seq; + j = (Uint1) win->seq[length]; /* prevent sign-extension */ + ++win->seq; - if (!alphaflag[j]) - s_IncrementSV(win->state, comp[alphaindex[j]]++); - else win->bogus++; + if (!alphaflag[j]) + s_IncrementSV(win->state, comp[alphaindex[j]]++); + else win->bogus++; - if (win->entropy > -2.) - win->entropy = s_Entropy(win->state); + if (win->entropy > -2.) + win->entropy = s_Entropy(win->state); - return TRUE; + return TRUE; } /*-------------------------------------------------------------(closewin)---*/ -/** Frees the SSequence structure corresponding to a sequence window +/** Frees the SSequence structure corresponding to a sequence window * Does not free palpha like s_SSequenceFree (two functions needed?). * @param win object to be freed */ -static void +static void s_CloseWin(SSequence* win) { if (win==NULL) return; @@ -1727,10 +1729,10 @@ s_CloseWin(SSequence* win) /*----------------------------------------------------------------(enton)---*/ -/** Calculates entropy of a sequence window +/** Calculates entropy of a sequence window * @param win object to be analyzed [in] */ -static void +static void s_EntropyOn(SSequence* win) { @@ -1742,13 +1744,13 @@ s_EntropyOn(SSequence* win) } /** Calculates entropy for a given sequence and window - * + * * @param seq Sequence to examine [in] * @param window amount of sequence to examine at once [in] * @param maxbogus limit on non-allowed (e.g., X) characters [in] * @return calculated entropy */ -static double* +static double* s_SeqEntropy(SSequence* seq, Int4 window, Int4 maxbogus) { SSequence* win; @@ -1861,8 +1863,8 @@ s_lnfact(Int4 n) { * @param sv state vector [in] * @param window_length length of window being examined * @return K2 - */ -static double + */ +static double s_LnPerm(const Int4* sv, Int4 window_length) { @@ -1871,7 +1873,7 @@ s_LnPerm(const Int4* sv, Int4 window_length) ans = s_lnfact(window_length); - for (i=0; sv[i]!=0; i++) + for (i=0; sv[i]!=0; i++) { ans -= s_lnfact(sv[i]); } @@ -1887,7 +1889,7 @@ s_LnPerm(const Int4* sv, Int4 window_length) * @param alphasize total letters in alphabet [in] * @return number of compositions as described above */ -static double +static double s_LnAss(const Int4* sv, Int4 alphasize) { @@ -1931,14 +1933,14 @@ s_LnAss(const Int4* sv, Int4 alphasize) } -/** This function calculates the natural log of the value P sub 0 from +/** This function calculates the natural log of the value P sub 0 from * equation 3 of Wootton and Federhen (Methods Enzymol. 1996;266:554-71). * @param sv state vector [in] * @param total window length of area examined [in] * @param palpha structure for alphabet information [in] * @return log of P sub 0 as mentioned above */ -static double +static double s_GetProb(const Int4* sv, Int4 total, const Alpha* palpha) { @@ -1968,7 +1970,7 @@ s_GetProb(const Int4* sv, Int4 total, const Alpha* palpha) * @param rightend right-most end of sequence [in|out] * @param sparamsp the SEG parameters [in] */ -static Int2 +static Int2 s_Trim(SSequence* seq, Int4* leftend, Int4* rightend, const SegParameters* sparamsp) { @@ -1983,7 +1985,7 @@ s_Trim(SSequence* seq, Int4* leftend, Int4* rightend, const SegParameters* spara rend = seq->length - 1; minlen = 1; maxtrim = sparamsp->maxtrim; - if ((seq->length-maxtrim)>minlen) + if ((seq->length-maxtrim)>minlen) minlen = seq->length-maxtrim; minprob = 1.; @@ -2015,16 +2017,16 @@ s_Trim(SSequence* seq, Int4* leftend, Int4* rightend, const SegParameters* spara return status; } -/** High-level function to perform calculations to find - * low-complexity segments. Thi function calls itself +/** High-level function to perform calculations to find + * low-complexity segments. Thi function calls itself * recursively - * + * * @param seq sequence to be checked [in] * @param sparamsp seg parameters [in] * @param segs low-complexity segments found [out] * @param offset offset of sequence passed in [in] */ -static Int2 +static Int2 s_SegSeq(SSequence* seq, SegParameters* sparamsp, SSeg **segs, Int4 offset) { @@ -2047,10 +2049,10 @@ s_SegSeq(SSequence* seq, SegParameters* sparamsp, SSeg **segs, hicut = sparamsp->hicut; downset = (window+1)/2 - 1; upset = window - downset; - + H = s_SeqEntropy(seq, window, sparamsp->maxbogus); - if (H == NULL) + if (H == NULL) return status; first = downset; @@ -2114,12 +2116,12 @@ s_SegSeq(SSequence* seq, SegParameters* sparamsp, SSeg **segs, } /*------------------------------------------------------------(mergesegs)---*/ -/** merge together overlapping segments, +/** merge together overlapping segments, * hilenmin also does something, but we need to ask Scott Federhen what? * @param seq information about sequence [in] * @param segs segment information [in] */ -static void +static void s_MergeSegs(SSequence* seq, SSeg* segs) { SSeg* seg,* nextseg; @@ -2129,7 +2131,7 @@ s_MergeSegs(SSequence* seq, SSeg* segs) if (segs==NULL) return; - if (seq->length -1 - segs->end < hilenmin) + if (seq->length -1 - segs->end < hilenmin) segs->end = seq->length -1; seg = segs; @@ -2159,7 +2161,7 @@ s_MergeSegs(SSequence* seq, SSeg* segs) * @param seg_locs the new BLAST specific representation [out] * @return 0 on success, -1 if memory allocation failed. */ -static Int2 +static Int2 s_SegsToBlastSeqLoc(SSeg* segs, Int4 offset, BlastSeqLoc** seg_locs) { for ( ; segs; segs = segs->next) { @@ -2170,7 +2172,7 @@ s_SegsToBlastSeqLoc(SSeg* segs, Int4 offset, BlastSeqLoc** seg_locs) loc->next = *seg_locs; *seg_locs = loc; } - /* If not all segs have been processed, it means that memory allocation + /* If not all segs have been processed, it means that memory allocation failed, hence return error status. */ if (segs) { *seg_locs = BlastSeqLocFree(*seg_locs); @@ -2180,10 +2182,10 @@ s_SegsToBlastSeqLoc(SSeg* segs, Int4 offset, BlastSeqLoc** seg_locs) return 0; } -/** Creats the Alphabet structure for standard protein alphabet. +/** Creats the Alphabet structure for standard protein alphabet. * @return pointer to the alphabet structure. */ -static Alpha* +static Alpha* s_AA20alphaStd (void) { Alpha* palpha; @@ -2205,8 +2207,8 @@ s_AA20alphaStd (void) for (c=0, i=0; c= 3 && c <= 20) || c == 22) { - alphaflag[c] = FALSE; - alphaindex[c] = i; + alphaflag[c] = FALSE; + alphaindex[c] = i; ++i; } else { alphaflag[c] = TRUE; alphaindex[c] = 20; @@ -2238,10 +2240,10 @@ SegParameters* SegParametersNewAa (void) return (sparamsp); } -/** Checks SeqParameter struct for proteins, sets default values if not set. +/** Checks SeqParameter struct for proteins, sets default values if not set. * @param sparamsp parameters to check [in] */ -static void +static void s_SegParametersCheck (SegParameters* sparamsp) { if (!sparamsp) return; @@ -2269,7 +2271,7 @@ s_SegParametersCheck (SegParameters* sparamsp) /* Comments in blast_seg.h */ void SegParametersFree(SegParameters* sparamsp) { - if (!sparamsp) + if (!sparamsp) return; sfree(sparamsp); return; @@ -2283,9 +2285,9 @@ Int2 SeqBufferSeg (Uint1* sequence, Int4 length, Int4 offset, SSeg* segs; Boolean params_allocated = FALSE; Int2 status = 0; - + s_SegParametersCheck (sparamsp); - + /* check seg parameters */ if (!sparamsp) { params_allocated = TRUE; @@ -2296,16 +2298,16 @@ Int2 SeqBufferSeg (Uint1* sequence, Int4 length, Int4 offset, } /* make an old-style genwin sequence window object */ - + seqwin = s_SSequenceNew(); seqwin->seq = (char*) sequence; seqwin->length = length; seqwin->palpha = s_AA20alphaStd(); *seg_locs = NULL; - + /* seg the sequence */ - + segs = (SSeg*) NULL; status = s_SegSeq (seqwin, sparamsp, &segs, 0); if (status < 0) @@ -2320,8 +2322,8 @@ Int2 SeqBufferSeg (Uint1* sequence, Int4 length, Int4 offset, s_MergeSegs(seqwin, segs); /* convert segs to seqlocs */ - s_SegsToBlastSeqLoc(segs, offset, seg_locs); - + s_SegsToBlastSeqLoc(segs, offset, seg_locs); + /* clean up & return */ seqwin->seq = NULL; s_SSequenceFree (seqwin); @@ -2329,7 +2331,7 @@ Int2 SeqBufferSeg (Uint1* sequence, Int4 length, Int4 offset, if(params_allocated) SegParametersFree(sparamsp); - + return 0; } diff --git a/c++/src/algo/blast/core/blast_seqsrc.c b/c++/src/algo/blast/core/blast_seqsrc.c index 0ae743e6..87677c00 100644 --- a/c++/src/algo/blast/core/blast_seqsrc.c +++ b/c++/src/algo/blast/core/blast_seqsrc.c @@ -1,4 +1,4 @@ -/* $Id: blast_seqsrc.c 461918 2015-03-13 16:38:36Z vasilche $ +/* $Id: blast_seqsrc.c 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -33,13 +33,6 @@ * low level details of the implementation of the BlastSeqSrc framework. */ -#ifndef SKIP_DOXYGEN_PROCESSING -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_seqsrc.c 461918 2015-03-13 16:38:36Z vasilche $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ -#endif - #include #include diff --git a/c++/src/algo/blast/core/blast_setup.c b/c++/src/algo/blast/core/blast_setup.c index 4b072cf3..f9ff3949 100644 --- a/c++/src/algo/blast/core/blast_setup.c +++ b/c++/src/algo/blast/core/blast_setup.c @@ -1,4 +1,4 @@ -/* $Id: blast_setup.c 496012 2016-03-23 11:30:57Z ivanov $ +/* $Id: blast_setup.c 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -32,11 +32,6 @@ */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_setup.c 496012 2016-03-23 11:30:57Z ivanov $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include @@ -118,7 +113,7 @@ Blast_ScoreBlkKbpGappedCalc(BlastScoreBlk * sbp, /* For right now, copy the contents from kbp_gap_std to * kbp_gap_psi (as in old code - BLASTSetUpSearchInternalByLoc) */ - if (program != eBlastTypeBlastn) { + if (program != eBlastTypeBlastn && program != eBlastTypeMapping) { sbp->kbp_gap_psi[index] = Blast_KarlinBlkNew(); Blast_KarlinBlkCopy(sbp->kbp_gap_psi[index], sbp->kbp_gap_std[index]); @@ -348,7 +343,8 @@ Blast_ScoreBlkMatrixInit(EBlastProgramType program_number, currently only turned on in RMBlastN -RMH- */ sbp->matrix_only_scoring = FALSE; - if (program_number == eBlastTypeBlastn) { + if (program_number == eBlastTypeBlastn || + program_number == eBlastTypeMapping) { BLAST_ScoreSetAmbigRes(sbp, 'N'); BLAST_ScoreSetAmbigRes(sbp, '-'); @@ -396,6 +392,66 @@ Blast_ScoreBlkMatrixInit(EBlastProgramType program_number, return status; } +static Int2 +s_JumperScoreBlkFill(BlastScoreBlk* sbp, const BlastQueryInfo* query_info, + Blast_Message** error_return) +{ + Int4 context; + Blast_KarlinBlk* kbp; + Int2 status; + + /* Create ungapped block */ + status = Blast_ScoreBlkKbpIdealCalc(sbp); + if (status) { + return status; + } + + for (context = query_info->first_context; + context <= query_info->last_context; ++context) { + + if (!query_info->contexts[context].is_valid) { + continue; + } + + sbp->sfp[context] = NULL; + sbp->kbp_std[context] = Blast_KarlinBlkNew(); + Blast_KarlinBlkCopy(sbp->kbp_std[context], sbp->kbp_ideal); + } + sbp->kbp = sbp->kbp_std; + + /* Create gapped block */ + context = query_info->first_context; + while (!query_info->contexts[context].is_valid) { + context++; + } + + sbp->kbp_gap_std[context] = kbp = Blast_KarlinBlkNew(); + status = Blast_KarlinBlkNuclGappedCalc(kbp, BLAST_GAP_OPEN_MEGABLAST, + BLAST_GAP_EXTN_MEGABLAST, + BLAST_REWARD, + BLAST_PENALTY, + sbp->kbp_std[context], + &(sbp->round_down), + error_return); + if (status){ + return status; + } + + for (++context;context <= query_info->last_context; ++context) { + + if (!query_info->contexts[context].is_valid) { + continue; + } + + sbp->kbp_gap_std[context] = Blast_KarlinBlkNew(); + Blast_KarlinBlkCopy(sbp->kbp_gap_std[context], kbp); + } + sbp->kbp_gap = sbp->kbp_gap_std; + + return status; +} + + Int2 BlastSetup_ScoreBlkInit(BLAST_SequenceBlk* query_blk, const BlastQueryInfo* query_info, @@ -413,7 +469,9 @@ BlastSetup_ScoreBlkInit(BLAST_SequenceBlk* query_blk, if (sbpp == NULL) return 1; - if (program_number == eBlastTypeBlastn) { + if (program_number == eBlastTypeBlastn || + program_number == eBlastTypeMapping) { + sbp = BlastScoreBlkNew(BLASTNA_SEQ_CODE, query_info->last_context + 1); /* disable new FSC rules for nucleotide case for now */ if (sbp && sbp->gbp) { @@ -446,6 +504,12 @@ BlastSetup_ScoreBlkInit(BLAST_SequenceBlk* query_blk, /* Fills in block for gapped blast. */ if (Blast_ProgramIsPhiBlast(program_number)) { status = s_PHIScoreBlkFill(sbp, scoring_options, blast_message, get_path); + } else if (Blast_ProgramIsMapping(program_number)) { + /* Create fake score blocks for each query without computing base + frequencies. We do not compute e-values for mapping, so the + KA statistics are not needed, but the data structures are checked + and used in BLAST engine. */ + status = s_JumperScoreBlkFill(sbp, query_info, blast_message); } else { status = Blast_ScoreBlkKbpUngappedCalc(program_number, sbp, query_blk->sequence, query_info, blast_message); @@ -675,6 +739,17 @@ Int2 BLAST_CalcEffLengths (EBlastProgramType program_number, else db_num_seqs = eff_len_params->real_num_seqs; + /* Mapping does not need length correction */ + if (Blast_ProgramIsMapping(program_number)) { + for (index = query_info->first_context; + index <= query_info->last_context; + index++) { + query_info->contexts[index].eff_searchsp = db_length; + } + + return 0; + } + /* PHI BLAST search space calculation is different. */ if (Blast_ProgramIsPhiBlast(program_number)) { diff --git a/c++/src/algo/blast/core/blast_stat.c b/c++/src/algo/blast/core/blast_stat.c index 771ca7a0..af37711c 100644 --- a/c++/src/algo/blast/core/blast_stat.c +++ b/c++/src/algo/blast/core/blast_stat.c @@ -1,4 +1,4 @@ -/* $Id: blast_stat.c 500367 2016-05-04 12:06:01Z ivanov $ +/* $Id: blast_stat.c 505944 2016-06-30 12:29:20Z madden $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -48,11 +48,6 @@ * */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_stat.c 500367 2016-05-04 12:06:01Z ivanov $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include "boost_erf.h" @@ -1431,7 +1426,6 @@ BlastScoreBlkProteinMatrixRead(BlastScoreBlk* sbp, FILE *fp) if ((lp = (char*)strtok(buf, kTokenStr)) == NULL) continue; ch = *lp; - cp = (char*) lp; if ((cp = strtok(NULL, kTokenStr)) == NULL) { return 2; } diff --git a/c++/src/algo/blast/core/blast_sw.c b/c++/src/algo/blast/core/blast_sw.c index 69e80bf3..0fde35b7 100644 --- a/c++/src/algo/blast/core/blast_sw.c +++ b/c++/src/algo/blast/core/blast_sw.c @@ -1,4 +1,4 @@ -/* $Id: blast_sw.c 148871 2009-01-05 16:51:12Z camacho $ +/* $Id: blast_sw.c 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -32,11 +32,6 @@ * @sa blast_sw.h */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_sw.c 148871 2009-01-05 16:51:12Z camacho $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include /* for NCBI2NA_UNPACK_BASE */ @@ -656,7 +651,8 @@ Int2 BLAST_SmithWatermanGetGappedScore (EBlastProgramType program_number, return 1; is_prot = (program_number != eBlastTypeBlastn && - program_number != eBlastTypePhiBlastn); + program_number != eBlastTypePhiBlastn && + program_number != eBlastTypeMapping); if (Blast_ProgramIsRpsBlast(program_number)) { Int4 rps_context = subject->oid; diff --git a/c++/src/algo/blast/core/blast_traceback.c b/c++/src/algo/blast/core/blast_traceback.c index 2c7299e3..ed75f6e5 100644 --- a/c++/src/algo/blast/core/blast_traceback.c +++ b/c++/src/algo/blast/core/blast_traceback.c @@ -1,4 +1,4 @@ -/* $Id: blast_traceback.c 500444 2016-05-04 17:46:06Z ivanov $ +/* $Id: blast_traceback.c 511802 2016-08-24 17:30:32Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -48,11 +48,6 @@ * */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_traceback.c 500444 2016-05-04 17:46:06Z ivanov $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include @@ -454,7 +449,8 @@ Blast_TracebackFromHSPList(EBlastProgramType program_number, optimization for OOF */ gap_align->subject_start = 0; gap_align->query_start = 0; - } else if (program_number == eBlastTypeBlastn) { + } else if (program_number == eBlastTypeBlastn || + program_number == eBlastTypeMapping) { /* Find the optimal starting offset */ BlastGetStartForGappedAlignmentNucl(query, subject, hsp); } @@ -1170,7 +1166,19 @@ Int2 s_RPSComputeTraceback(EBlastProgramType program_number, (if not a translated search) */ if (program_number == eBlastTypeRpsTblastn) { - sbp->psi_matrix->pssm->data = rpsblast_pssms + db_seq_start; + if (ext_params->options->compositionBasedStats > 0) { + const double* karlin_k = rps_info->aux_info.karlin_k; + + sbp->psi_matrix->pssm->data = (Int4**)_PSIAllocateMatrix( + seq_arg.seq->length, + BLASTAA_SIZE, + sizeof(Int4)); + sbp->kbp_gap[0]->K = RPS_K_MULT * karlin_k[hsp_list->oid]; + sbp->kbp_gap[0]->logK = log(RPS_K_MULT * karlin_k[hsp_list->oid]); + } + else { + sbp->psi_matrix->pssm->data = rpsblast_pssms + db_seq_start; + } } else { const double* karlin_k = rps_info->aux_info.karlin_k; @@ -1247,7 +1255,10 @@ Int2 s_RPSComputeTraceback(EBlastProgramType program_number, if (ext_params->options->compositionBasedStats > 0) { _PSIDeallocateMatrix((void**)sbp->psi_matrix->freq_ratios, seq_arg.seq->length); - + if (program_number == eBlastTypeRpsTblastn) { + _PSIDeallocateMatrix((void**)sbp->psi_matrix->pssm->data, + seq_arg.seq->length); + } } if (hsp_list->hspcnt == 0) { hsp_list = Blast_HSPListFree(hsp_list); diff --git a/c++/src/algo/blast/core/blast_traceback_mt_priv.c b/c++/src/algo/blast/core/blast_traceback_mt_priv.c index 571dec1d..bca2ad16 100644 --- a/c++/src/algo/blast/core/blast_traceback_mt_priv.c +++ b/c++/src/algo/blast/core/blast_traceback_mt_priv.c @@ -1,4 +1,4 @@ -/* $Id: blast_traceback_mt_priv.c 496008 2016-03-23 11:29:15Z ivanov $ +/* $Id: blast_traceback_mt_priv.c 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -30,11 +30,6 @@ * Private interface to support the multi-threaded traceback */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_traceback_mt_priv.c 496008 2016-03-23 11:29:15Z ivanov $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include "blast_traceback_mt_priv.h" #include "blast_hspstream_mt_utils.h" diff --git a/c++/src/algo/blast/core/blast_tune.c b/c++/src/algo/blast/core/blast_tune.c index 7ea5af54..af50ab58 100644 --- a/c++/src/algo/blast/core/blast_tune.c +++ b/c++/src/algo/blast/core/blast_tune.c @@ -1,4 +1,4 @@ -/* $Id: blast_tune.c 94064 2006-11-21 17:19:42Z papadopo $ +/* $Id: blast_tune.c 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -33,11 +33,6 @@ * percent identity. */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_tune.c 94064 2006-11-21 17:19:42Z papadopo $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include diff --git a/c++/src/algo/blast/core/blast_util.c b/c++/src/algo/blast/core/blast_util.c index d5027f5a..ae7ecd9f 100644 --- a/c++/src/algo/blast/core/blast_util.c +++ b/c++/src/algo/blast/core/blast_util.c @@ -1,4 +1,4 @@ -/* $Id: blast_util.c 473564 2015-07-21 15:29:04Z madden $ +/* $Id: blast_util.c 516334 2016-10-12 17:30:52Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -32,11 +32,6 @@ */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_util.c 473564 2015-07-21 15:29:04Z madden $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include @@ -308,6 +303,8 @@ Int2 BlastProgram2Number(const char *program, EBlastProgramType *number) *number = eBlastTypePhiBlastn; else if (strcasecmp("phiblastp", program) == 0) *number = eBlastTypePhiBlastp; + else if (strcasecmp("mapper", program) == 0) + *number = eBlastTypeMapping; return 0; } @@ -352,6 +349,9 @@ Int2 BlastNumber2Program(EBlastProgramType number, char* *program) case eBlastTypePhiBlastn: *program = strdup("phiblastn"); break; + case eBlastTypeMapping: + *program = strdup("mapper"); + break; default: *program = strdup("unknown"); break; @@ -811,8 +811,12 @@ Int2 GetReverseNuclSequence(const Uint1* sequence, Int4 length, Int4 index; /* Conversion table from forward to reverse strand residue in the blastna encoding */ - Uint1 conversion_table[17] = - { 0, 8, 4, 12, 2, 10, 9, 14, 1, 6, 5, 13, 3, 11, 7, 15 }; + Uint1 conversion_table[16] = { + 0, 8, 4, 12, + 2, 10, 6, 14, + 1, 9, 5, 13, + 3, 11, 7, 15 + }; if (!rev_sequence_ptr) return -1; @@ -836,7 +840,7 @@ Int1 BLAST_ContextToFrame(EBlastProgramType prog_number, Uint4 context_number) { Int1 frame = INT1_MAX; /* INT1_MAX is used to indicate error */ - if (prog_number == eBlastTypeBlastn) { + if (prog_number == eBlastTypeBlastn || prog_number == eBlastTypeMapping) { if (context_number % NUM_STRANDS == 0) frame = 1; else @@ -934,6 +938,8 @@ Int2 BLAST_CreateMixedFrameDNATranslation(BLAST_SequenceBlk* query_blk, /* Allocate 1 extra byte for a final sentinel. */ buffer = (Uint1*) malloc(total_length+1); + if (!buffer) + return -1; for (index = 0; index <= query_info->last_context; index += CODON_LENGTH) { int i; @@ -962,7 +968,8 @@ Int2 BLAST_CreateMixedFrameDNATranslation(BLAST_SequenceBlk* query_blk, } } /* Add a sentinel null byte at the end. */ - *seq = NULLB; + if (seq) + *seq = NULLB; /* The mixed-frame protein sequence buffer will be saved in 'sequence_start' */ diff --git a/c++/src/algo/blast/core/boost_erf.c b/c++/src/algo/blast/core/boost_erf.c index 7ddf0feb..36fae17d 100644 --- a/c++/src/algo/blast/core/boost_erf.c +++ b/c++/src/algo/blast/core/boost_erf.c @@ -1,4 +1,4 @@ -/* $Id: boost_erf.c 498724 2016-04-19 13:36:57Z ivanov $ +/* $Id: boost_erf.c 498248 2016-04-14 15:42:26Z boratyng $ * =========================================================================== * * This code is ported from the open source C++ library Boost, for which diff --git a/c++/src/algo/blast/core/boost_erf.h b/c++/src/algo/blast/core/boost_erf.h index 3b5f2ed5..8dd980b7 100644 --- a/c++/src/algo/blast/core/boost_erf.h +++ b/c++/src/algo/blast/core/boost_erf.h @@ -1,4 +1,4 @@ -/* $Id: boost_erf.h 498724 2016-04-19 13:36:57Z ivanov $ +/* $Id: boost_erf.h 498248 2016-04-14 15:42:26Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/algo/blast/core/gapinfo.c b/c++/src/algo/blast/core/gapinfo.c index 5f48210d..1ed2b0c0 100644 --- a/c++/src/algo/blast/core/gapinfo.c +++ b/c++/src/algo/blast/core/gapinfo.c @@ -1,4 +1,4 @@ -/* $Id: gapinfo.c 94064 2006-11-21 17:19:42Z papadopo $ +/* $Id: gapinfo.c 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -32,11 +32,6 @@ */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: gapinfo.c 94064 2006-11-21 17:19:42Z papadopo $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include diff --git a/c++/src/algo/blast/core/gencode_singleton.c b/c++/src/algo/blast/core/gencode_singleton.c index 3560fbd0..a4a11a33 100644 --- a/c++/src/algo/blast/core/gencode_singleton.c +++ b/c++/src/algo/blast/core/gencode_singleton.c @@ -1,4 +1,4 @@ -/* $Id: gencode_singleton.c 103491 2007-05-04 17:18:18Z kazimird $ +/* $Id: gencode_singleton.c 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -31,11 +31,6 @@ * Implementation of the genetic code singleton */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: gencode_singleton.c 103491 2007-05-04 17:18:18Z kazimird $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include "blast_dynarray.h" diff --git a/c++/src/algo/blast/core/greedy_align.c b/c++/src/algo/blast/core/greedy_align.c index 3ae44a15..7ccace38 100644 --- a/c++/src/algo/blast/core/greedy_align.c +++ b/c++/src/algo/blast/core/greedy_align.c @@ -1,4 +1,4 @@ -/* $Id: greedy_align.c 480534 2015-10-01 15:21:48Z madden $ +/* $Id: greedy_align.c 505944 2016-06-30 12:29:20Z madden $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -34,11 +34,6 @@ * Journal of Computational Biology vol 7 pp 203-214 */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: greedy_align.c 480534 2015-10-01 15:21:48Z madden $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include /* for NCBI2NA_UNPACK_BASE macros */ @@ -690,7 +685,6 @@ Int4 BLAST_GreedyAlign(const Uint1* seq1, Int4 len1, /* perform traceback */ d = best_dist; - seq1_index = *seq1_align_len; seq2_index = *seq2_align_len; /* for all positive distances */ diff --git a/c++/src/algo/blast/core/hspfilter_besthit.c b/c++/src/algo/blast/core/hspfilter_besthit.c index b1d89516..ddf02ad0 100644 --- a/c++/src/algo/blast/core/hspfilter_besthit.c +++ b/c++/src/algo/blast/core/hspfilter_besthit.c @@ -1,4 +1,4 @@ -/* $Id: hspfilter_besthit.c 458578 2015-02-06 15:11:29Z fongah2 $ +/* $Id: hspfilter_besthit.c 506193 2016-07-05 14:14:58Z madden $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -32,11 +32,6 @@ * a BLAST search, and subsequently return them in sorted order. */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: hspfilter_besthit.c 458578 2015-02-06 15:11:29Z fongah2 $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include @@ -70,10 +65,11 @@ typedef struct BlastHSPBestHitData { * @param results The HSP results to operate on [in] */ static int -s_BlastHSPBestHitInit(void* data, BlastHSPResults* results) +s_BlastHSPBestHitInit(void* data, void* hsp_results) { int i; BlastHSPBestHitData * bh_data = data; + BlastHSPResults* results = (BlastHSPResults*)hsp_results; bh_data->best_list = calloc(results->num_queries, sizeof(LinkedHSP_BH *)); bh_data->num_hsps = calloc(results->num_queries, sizeof(Int4)); bh_data->max_hsps = calloc(results->num_queries, sizeof(Int4)); @@ -196,10 +192,11 @@ s_ImportFromHitlist(int qid, * @param results The HSP results to propagate [in][out] */ static int -s_BlastHSPBestHitFinal(void* data, BlastHSPResults* results) +s_BlastHSPBestHitFinal(void* data, void* hsp_results) { int qid, sid; BlastHSPBestHitData *bh_data = data; + BlastHSPResults* results = (BlastHSPResults*)hsp_results; LinkedHSP_BH **best_list = bh_data->best_list; BlastHitList* hitlist; @@ -485,7 +482,8 @@ s_BlastHSPBestHitFree(BlastHSPWriter* writer) */ static BlastHSPWriter* -s_BlastHSPBestHitNew(void* params, BlastQueryInfo* query_info) +s_BlastHSPBestHitNew(void* params, BlastQueryInfo* query_info, + BLAST_SequenceBlk* sequence) { BlastHSPWriter * writer = NULL; BlastHSPBestHitData data; @@ -606,7 +604,7 @@ BlastHSPBestHitParamsNew(const BlastHitSavingOptions* hit_options, prelim_hitlist_size + 50); retval = (BlastHSPBestHitParams*) malloc(sizeof(BlastHSPBestHitParams)); - retval->prelim_hitlist_size = MAX(hit_options->hitlist_size, 10); + retval->prelim_hitlist_size = MAX(prelim_hitlist_size, 10); retval->hsp_num_max = BlastHspNumMax(gapped_calculation, hit_options); retval->program = hit_options->program_number; retval->overhang = best_hit_opts->overhang; diff --git a/c++/src/algo/blast/core/hspfilter_collector.c b/c++/src/algo/blast/core/hspfilter_collector.c index dc89a52b..2180c03c 100644 --- a/c++/src/algo/blast/core/hspfilter_collector.c +++ b/c++/src/algo/blast/core/hspfilter_collector.c @@ -1,4 +1,4 @@ -/* $Id: hspfilter_collector.c 443210 2014-08-12 13:55:24Z fongah2 $ +/* $Id: hspfilter_collector.c 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -32,11 +32,6 @@ * a BLAST search, and subsequently return them in sorted order. */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: hspfilter_collector.c 443210 2014-08-12 13:55:24Z fongah2 $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include @@ -56,9 +51,10 @@ typedef struct BlastHSPCollectorData { * @param results The HSP results to operate on [in] */ static int -s_BlastHSPCollectorInit(void* data, BlastHSPResults* results) +s_BlastHSPCollectorInit(void* data, void* hsp_results) { BlastHSPCollectorData * col_data = data; + BlastHSPResults* results = (BlastHSPResults*)hsp_results; /* grab the results as destination to store collected hsps */ col_data->results = results; return 0; @@ -69,7 +65,7 @@ s_BlastHSPCollectorInit(void* data, BlastHSPResults* results) * @param results The HSP results to propagate [in][out] */ static int -s_BlastHSPCollectorFinal(void* data, BlastHSPResults* results) +s_BlastHSPCollectorFinal(void* data, void* results) { BlastHSPCollectorData * col_data = data; /* results already stored during run, no action needed */ @@ -296,7 +292,8 @@ s_BlastHSPCollectorFree(BlastHSPWriter* writer) */ static BlastHSPWriter* -s_BlastHSPCollectorNew(void* params, BlastQueryInfo* query_info) +s_BlastHSPCollectorNew(void* params, BlastQueryInfo* query_info, + BLAST_SequenceBlk* sequence) { BlastHSPWriter * writer = NULL; BlastHSPCollectorData * data = NULL; diff --git a/c++/src/algo/blast/core/hspfilter_culling.c b/c++/src/algo/blast/core/hspfilter_culling.c index 114f9304..2912a962 100644 --- a/c++/src/algo/blast/core/hspfilter_culling.c +++ b/c++/src/algo/blast/core/hspfilter_culling.c @@ -1,4 +1,4 @@ -/* $Id: hspfilter_culling.c 429223 2014-03-12 17:13:31Z fongah2 $ +/* $Id: hspfilter_culling.c 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -39,11 +39,6 @@ * 10890403. */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: hspfilter_culling.c 429223 2014-03-12 17:13:31Z fongah2 $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include @@ -501,7 +496,7 @@ typedef struct BlastHSPCullingData { * @param results The HSP results to operate on [in] */ static int -s_BlastHSPCullingInit(void* data, BlastHSPResults* results) +s_BlastHSPCullingInit(void* data, void* results) { BlastHSPCullingData * cull_data = data; cull_data->c_tree = calloc(cull_data->num_contexts, sizeof(CTreeNode *)); @@ -513,10 +508,11 @@ s_BlastHSPCullingInit(void* data, BlastHSPResults* results) * @param results The HSP results to propagate [in][out] */ static int -s_BlastHSPCullingFinal(void* data, BlastHSPResults* results) +s_BlastHSPCullingFinal(void* data, void* hsp_results) { int cid, qid, sid, id, new_allocated; BlastHSPCullingData* cull_data = data; + BlastHSPResults* results = (BlastHSPResults*)hsp_results; BlastHSPCullingParams* params = cull_data->params; CTreeNode **c_tree = cull_data->c_tree; LinkedHSP *cull_list, *p; @@ -675,7 +671,8 @@ s_BlastHSPCullingFree(BlastHSPWriter* writer) */ static BlastHSPWriter* -s_BlastHSPCullingNew(void* params, BlastQueryInfo* query_info) +s_BlastHSPCullingNew(void* params, BlastQueryInfo* query_info, + BLAST_SequenceBlk* sequence) { BlastHSPWriter * writer = NULL; BlastHSPCullingData data; diff --git a/c++/src/algo/blast/core/hspfilter_mapper.c b/c++/src/algo/blast/core/hspfilter_mapper.c new file mode 100644 index 00000000..1eacbd33 --- /dev/null +++ b/c++/src/algo/blast/core/hspfilter_mapper.c @@ -0,0 +1,4353 @@ +/* $Id: hspfilter_mapper.c 517510 2016-10-25 17:24:24Z ivanov $ + * =========================================================================== + * + * PUBLIC DOMAIN NOTICE + * National Center for Biotechnology Information + * + * This software/database is a "United States Government Work" under the + * terms of the United States Copyright Act. It was written as part of + * the author's official duties as a United States Government employee and + * thus cannot be copyrighted. This software/database is freely available + * to the public for use. The National Library of Medicine and the U.S. + * Government have not placed any restriction on its use or reproduction. + * + * Although all reasonable efforts have been taken to ensure the accuracy + * and reliability of the software and data, the NLM and the U.S. + * Government do not and cannot warrant the performance or results that + * may be obtained by using this software or data. The NLM and the U.S. + * Government disclaim all warranties, express or implied, including + * warranties of performance, merchantability or fitness for any particular + * purpose. + * + * Please cite the author in any work or product based on this material. + * + * =========================================================================== + * + * Author: Greg Boratyn + * + */ + +/** @file hspfilter_mapper.c + * Implementation of the BlastHSPWriter interface to save only the best scoring * chains of HSPs for aligning RNA-Seq sequences to a genome. + */ + +#include +#include +#include +#include "jumper.h" + +/* Pair configurations, in the order of prefernece */ +#define PAIR_CONVERGENT 0 +#define PAIR_DIVERGENT 1 +#define PAIR_PARALLEL 2 +#define PAIR_NONE 3 + +/* A container to create a list of HSPs */ +typedef struct HSPContainer +{ + BlastHSP* hsp; + struct HSPContainer* next; +} HSPContainer; + + +/* Create HSPContainer and take ownership of the HSP */ +static HSPContainer* HSPContainerNew(BlastHSP** hsp) +{ + HSPContainer* retval = calloc(1, sizeof(HSPContainer)); + if (!retval) { + return NULL; + } + retval->hsp = *hsp; + /* take ownership of this HSP */ + *hsp = NULL; + + return retval; +} + +/* Free the list of HSPs, along with the stored HSPs */ +static HSPContainer* HSPContainerFree(HSPContainer* hc) +{ + HSPContainer* h = hc; + while (h) { + HSPContainer* next = h->next; + if (h->hsp) { + Blast_HSPFree(h->hsp); + } + + sfree(h); + h = next; + } + + return NULL; +} + +/* Clone a list of HSP containers */ +static HSPContainer* HSPContainerDup(HSPContainer* inh) +{ + HSPContainer* retval = NULL; + HSPContainer* hi = NULL, *ho = NULL; + BlastHSP* new_hsp = NULL; + + if (!inh || !inh->hsp) { + return NULL; + } + + new_hsp = Blast_HSPClone(inh->hsp); + if (!new_hsp) { + return NULL; + } + retval = HSPContainerNew(&new_hsp); + if (!retval) { + Blast_HSPFree(new_hsp); + return NULL; + } + + hi = inh->next; + ho = retval; + for (; hi; hi = hi->next, ho = ho->next) { + new_hsp = Blast_HSPClone(hi->hsp); + if (!new_hsp) { + Blast_HSPFree(new_hsp); + HSPContainerFree(retval); + return NULL; + } + ho->next = HSPContainerNew(&new_hsp); + if (!ho->next) { + Blast_HSPFree(new_hsp); + HSPContainerFree(retval); + return NULL; + } + } + + return retval; +} + +/* A chain of HSPs: gene transcript sequence aligned to exons */ +typedef struct HSPChain +{ + Int4 context; /* query context */ + Int4 oid; /* subject oid */ + Int4 score; /* score for the whole chain */ + HSPContainer* hsps; /* list of HSPs that belong to this chain */ + Int4 compartment; /* compartment number for the chain (needed + for reporting results) */ + + Int4 count; /* number of chains with the same or larger score found + for the same query */ + struct HSPChain* pair; /* pointer to the pair (for paired reads) */ + Uint1 pair_conf; /* pair configuration */ + + Int4 adapter; /* adapter start position */ + Int4 polyA; /* start of polyA tail */ + struct HSPChain* next; +} HSPChain; + + +static HSPChain* HSPChainFree(HSPChain* chain_list) +{ + HSPChain* chain = chain_list; + while (chain) { + HSPChain* next = chain->next; + if (chain->pair) { + chain->pair->pair = NULL; + } + ASSERT(chain->hsps); + chain->hsps = HSPContainerFree(chain->hsps); + sfree(chain); + chain = next; + } + + return NULL; +} + +static HSPChain* HSPChainNew(Int4 context) +{ + HSPChain* retval = calloc(1, sizeof(HSPChain)); + if (!retval) { + return NULL; + } + retval->context = context; + retval->compartment = -1; + retval->adapter = -1; + + return retval; +} + + +/* Insert a single chain into the list so that the list is sorted in decending + order of chain scores. */ +static Int4 s_HSPChainListInsertOne(HSPChain** list, HSPChain* chain, + Boolean check_for_duplicates) +{ + HSPChain* ch = NULL; + + if (!list || !chain) { + return -1; + } + ASSERT(!chain->next); + + if (!*list) { + *list = chain; + return 0; + } + + ch = *list; + if (ch->score < chain->score) { + chain->next = ch; + *list = chain; + return 0; + } + + /* check for duplicate chain: the new chains may be the same as already + saved; this may come from writing HSPs to HSP stream for each chunk */ + if (check_for_duplicates && + ch->oid == chain->oid && ch->score == chain->score && + ch->hsps->hsp->query.frame == chain->hsps->hsp->query.frame && + ch->hsps->hsp->subject.offset == + chain->hsps->hsp->subject.offset) { + + chain->next = NULL; + chain = HSPChainFree(chain); + return 0; + } + + while (ch->next && ch->next->score >= chain->score){ + + /* check for duplicate chain: the new chains may be the same as already + saved; this may come from writing HSPs to HSP stream for each chunk */ + if (check_for_duplicates && + ch->next->oid == chain->oid && ch->next->score == chain->score && + ch->next->hsps->hsp->query.frame == chain->hsps->hsp->query.frame && + ch->next->hsps->hsp->subject.offset == + chain->hsps->hsp->subject.offset) { + + chain->next = NULL; + chain = HSPChainFree(chain); + return 0; + } + + ch = ch->next; + } + ASSERT(ch); + chain->next = ch->next; + ch->next = chain; + + return 0; +} + +/* Insert chains into the list so that the list is sorted in descending order + of chain scores. If chain is a list, each element is added separately. The + list must be sorted before adding chain */ +static Int4 HSPChainListInsert(HSPChain** list, HSPChain* chain, + Boolean check_for_duplicates) +{ + HSPChain* ch = NULL; + Int4 status = 0; + + if (!list || !chain) { + return -1; + } + + ch = chain; + while (ch) { + HSPChain* next = ch->next; + ch->next = NULL; + status = s_HSPChainListInsertOne(list, ch, check_for_duplicates); + if (status) { + return status; + } + ch = next; + + } + + return 0; +} + +/* Remove from the list chains with scores lower than the best one by at least + the given margin. The list must be sorted in descending order of scores. */ +static Int4 HSPChainListTrim(HSPChain* list, Int4 margin) +{ + HSPChain* ch = NULL; + Int4 best_score; + + if (!list) { + return -1; + } + + best_score = list->score; + ch = list; + while (ch->next && best_score - ch->next->score <= margin) { + ASSERT(best_score - ch->next->score >= 0); + ch = ch->next; + } + ASSERT(ch); + + ch->next = HSPChainFree(ch->next); + + return 0; +} + + +/* Clone a single HSP chain */ +static HSPChain* s_CloneChain(const HSPChain* chain) +{ + HSPChain* retval = NULL; + + if (!chain) { + return NULL; + } + + retval = HSPChainNew(chain->context); + if (!retval) { + return NULL; + } + retval->hsps = HSPContainerDup(chain->hsps); + if (!retval->hsps) { + HSPChainFree(retval); + return NULL; + } + retval->oid = chain->oid; + retval->score = chain->score; + retval->adapter = chain->adapter; + retval->polyA = chain->polyA; + + return retval; +} + +/* Test that all pointers in the chain are set */ +static Boolean s_TestChains(HSPChain* chain) +{ + HSPContainer* hc; + + ASSERT(chain); + hc = chain->hsps; + ASSERT(hc); + ASSERT(hc->hsp); + ASSERT(hc->hsp->context == chain->context); + + ASSERT(hc->hsp->gap_info->size > 1 || + hc->hsp->query.end - hc->hsp->query.offset == + hc->hsp->subject.end - hc->hsp->subject.offset); + + hc = hc->next; + while (hc) { + ASSERT(hc->hsp); + ASSERT(hc->hsp->context == chain->context); + + ASSERT(hc->hsp->gap_info->size > 1 || + hc->hsp->query.end - hc->hsp->query.offset == + hc->hsp->subject.end - hc->hsp->subject.offset); + + if (hc->next) { + ASSERT(hc->hsp->query.offset < hc->next->hsp->query.offset); + ASSERT(hc->hsp->subject.offset < hc->next->hsp->subject.offset); + } + hc = hc->next; + } + + chain = chain->next; + while (chain) { + hc = chain->hsps; + ASSERT(hc); + ASSERT(hc->hsp); + ASSERT(hc->hsp->context == chain->context); + + ASSERT(hc->hsp->gap_info->size > 1 || + hc->hsp->query.end - hc->hsp->query.offset == + hc->hsp->subject.end - hc->hsp->subject.offset); + + hc = hc->next; + while (hc) { + ASSERT(hc); + ASSERT(hc->hsp); + ASSERT(hc->hsp->context == chain->context); + + ASSERT(hc->hsp->gap_info->size > 1 || + hc->hsp->query.end - hc->hsp->query.offset == + hc->hsp->subject.end - hc->hsp->subject.offset); + + if (hc->next) { + ASSERT(hc->hsp->query.offset < hc->next->hsp->query.offset); + ASSERT(hc->hsp->subject.offset < hc->next->hsp->subject.offset); + } + + hc = hc->next; + } + chain = chain->next; + } + + return TRUE; +} + +#if _DEBUG +static Boolean s_TestChainsSorted(HSPChain* chain) +{ + HSPChain* prev; + + s_TestChains(chain); + + prev = chain; + chain = chain->next; + for (; chain; chain = chain->next, prev = prev->next) { + ASSERT(prev->score >= chain->score); + } + + return TRUE; +} +#endif + +/** Data structure used by the writer */ +typedef struct BlastHSPMapperData { + BlastHSPMapperParams* params; /**< how many hits to save */ + BLAST_SequenceBlk* query; /**< query sequence */ + BlastQueryInfo* query_info; /**< information about queries */ + HSPChain** saved_chains; /**< HSP chains are stored here */ +} BlastHSPMapperData; + +/*************************************************************/ +/** The following are implementations for BlastHSPWriter ADT */ + +/** Perform pre-run stage-specific initialization + * @param data The internal data structure [in][out] + * @param results The HSP results to operate on [in] + */ +static int +s_BlastHSPMapperPairedInit(void* data, void* results) +{ + BlastHSPMapperData * spl_data = data; + BlastHSPResults* r = (BlastHSPResults*)results; + spl_data->saved_chains = calloc(r->num_queries, sizeof(HSPChain*)); + + return 0; +} + + +/* Get subject start position */ +static Int4 s_FindFragmentStart(HSPChain* chain) +{ + Int2 frame; + HSPContainer* hc = NULL; + ASSERT(chain); + ASSERT(chain->hsps); + ASSERT(chain->hsps->hsp); + + frame = chain->hsps->hsp->query.frame; + if (frame > 0) { + return chain->hsps->hsp->subject.offset; + } + + hc = chain->hsps; + while (hc->next) { + hc = hc->next; + } + ASSERT(hc); + + return hc->hsp->subject.end - 1; +} + + +/* Get subject end position */ +/* Not used +static Int4 s_FindFragmentEnd(HSPChain* chain) +{ + Int2 frame; + HSPContainer* hc = NULL; + ASSERT(chain); + ASSERT(chain->hsps); + ASSERT(chain->hsps->hsp); + + frame = chain->hsps->hsp->query.frame; + if (frame < 0) { + return chain->hsps->hsp->subject.offset; + } + + hc = chain->hsps; + while (hc->next) { + hc = hc->next; + } + ASSERT(hc); + + return hc->hsp->subject.end - 1; +} +*/ + +/* Compute HSP alignment score from Jumper edit script */ +static Int4 s_ComputeAlignmentScore(BlastHSP* hsp, Int4 mismatch_score, + Int4 gap_open_score, Int4 gap_extend_score) +{ + Int4 i; + Int4 last_pos = hsp->query.offset; + Int4 score = 0; + const Int4 kGap = 15; + + for (i = 0;i < hsp->map_info->edits->num_edits;i++) { + JumperEdit* e = &(hsp->map_info->edits->edits[i]); + Int4 num_matches = e->query_pos - last_pos; + ASSERT(num_matches >= 0); + last_pos = e->query_pos; + score += num_matches; + + if (e->query_base == kGap) { + ASSERT(e->subject_base != kGap); + if (num_matches > 0 || + (i > 0 && hsp->map_info->edits->edits[i - 1].query_base != + kGap)) { + + score += gap_open_score; + } + score += gap_extend_score; + } + else if (e->subject_base == kGap) { + if (num_matches > 0 || + (i > 0 && hsp->map_info->edits->edits[i - 1].subject_base != + kGap)) { + + score += gap_open_score; + } + score += gap_extend_score; + last_pos++; + } + else { + score += mismatch_score; + last_pos++; + } + } + + score += hsp->query.end - last_pos; + return score; +} + + +/* Find the cost of chain HSPs overlapping on the query, as the smaller score + of the overlapping region */ +static Int4 s_GetOverlapCost(const BlastHSP* a, const BlastHSP* b, + Int4 edit_penalty) +{ + Int4 i; + Int4 overlap_f, overlap_s; + const BlastHSP* f; + const BlastHSP* s; + + /* if one HSP in contained within the other on the query, return the + smaller score */ + if ((a->query.offset <= b->query.offset && a->query.end >= b->query.end) || + (a->query.offset >= b->query.offset && a->query.end <= b->query.end)) { + + return MIN(a->score, b->score); + } + + /* if the two HSPs are mutually exclusive on the query, there is no cost */ + if ((a->query.end < b->query.offset && a->query.offset < b->query.end) || + (b->query.end < a->query.offset && b->query.offset < a->query.end)) { + + return 0; + } + + /* otherwise the HSPs partially overlap; reurn the the smaller score for + the overlap region */ + + /* find which HSP precedes which on the query */ + if (a->query.offset <= b->query.offset) { + f = a; + s = b; + } + else { + f = b; + s = a; + } + + /* this is the overlap score assuming perfect matches in the overlap */ + overlap_f = overlap_s = f->query.end - s->query.offset; + ASSERT(overlap_f >= 0 && overlap_s >= 0); + /* subtract penalties for mismatches and gaps in the overlap region */ + for (i = 0;i < f->map_info->edits->num_edits;i++) { + if (f->map_info->edits->edits[i].query_pos >= s->query.offset) { + overlap_f -= edit_penalty; + } + } + for (i = 0;i < s->map_info->edits->num_edits;i++) { + if (s->map_info->edits->edits[i].query_pos < f->query.end) { + overlap_s -= edit_penalty; + } + } + + return MIN(overlap_f, overlap_s); +} + + +/* Compute chain score */ +static Int4 s_ComputeChainScore(HSPChain* chain, + const ScoringOptions* score_options, + Int4 query_len, + Boolean comp_hsp_score) +{ + Int4 retval; + HSPContainer* h = NULL; + HSPContainer* prev = NULL; + + if (!chain || !score_options) { + return -1; + } + + h = chain->hsps; + if (comp_hsp_score) { + h->hsp->score = s_ComputeAlignmentScore(h->hsp, score_options->penalty, + score_options->gap_open, + score_options->gap_extend); + } + retval = h->hsp->score; + if (h->hsp->query.offset > 0 && + (h->hsp->map_info->left_edge & MAPPER_SPLICE_SIGNAL) == 0) { + + retval += score_options->no_splice_signal; + } + if (h->hsp->query.end < query_len && + (h->hsp->map_info->right_edge & MAPPER_SPLICE_SIGNAL) == 0) { + + retval += score_options->no_splice_signal; + } + + prev = h; + h = h->next; + + for (; h; h = h->next, prev = prev->next) { + /* HSPs must be sorted by query positon */ + ASSERT(h->hsp->query.offset >= prev->hsp->query.offset); + + if (comp_hsp_score) { + + h->hsp->score = s_ComputeAlignmentScore(h->hsp, + score_options->penalty, + score_options->gap_open, + score_options->gap_extend); + } + retval += h->hsp->score; + + if (h->hsp->query.offset > 0 && + (h->hsp->map_info->left_edge & MAPPER_SPLICE_SIGNAL) == 0) { + + retval += score_options->no_splice_signal; + } + if (h->hsp->query.end < query_len && + (h->hsp->map_info->right_edge & MAPPER_SPLICE_SIGNAL) == 0) { + + retval += score_options->no_splice_signal; + } + } + + return retval; +} + +#if _DEBUG +static Boolean s_TestHSPRanges(const BlastHSP* hsp) +{ + Int4 i; + Int4 d = 0; + for (i=0;i < hsp->gap_info->size;i++) { + switch (hsp->gap_info->op_type[i]) { + case eGapAlignIns: + d -= hsp->gap_info->num[i]; + break; + + case eGapAlignDel: + d += hsp->gap_info->num[i]; + break; + + default: + break; + } + } + if (hsp->query.end - hsp->query.offset + d != + hsp->subject.end - hsp->subject.offset) { + + return FALSE; + } + + return TRUE; +} +#endif + +/* Trim HSP by a number of bases on query or subject, either from the start or + from the end */ +static Int4 s_TrimHSP(BlastHSP* hsp, Int4 num, Boolean is_query, + Boolean is_start, Int4 mismatch_score, + Int4 gap_open_score, Int4 gap_extend_score) +{ + Int4 num_left = num; + Int4 i = is_start ? 0 : hsp->gap_info->size - 1; + Int4 d = is_start ? 1 : -1; + Int4 end = is_start ? hsp->gap_info->size : -1; + Int4 delta_query = 0, delta_subject = 0; + Boolean is_subject = !is_query; + Boolean is_end = !is_start; + Int4 k; + + ASSERT(hsp /* */ && num > 0 /* */); + ASSERT((is_query && num <= hsp->query.end - hsp->query.offset) || + (!is_query && num <= hsp->subject.end - hsp->subject.offset)); + +#if _DEBUG + ASSERT(s_TestHSPRanges(hsp)); +#endif + + if (num == 0) { + return 0; + } + + + /* itereate over the edit script and remove the required number + of subject bases */ + while (i != end && num_left > 0) { + switch (hsp->gap_info->op_type[i]) { + case eGapAlignSub: + if (hsp->gap_info->num[i] > num_left) { + hsp->gap_info->num[i] -= num_left; + delta_query += num_left; + delta_subject += num_left; + num_left = 0; + } + else { + Int4 n = hsp->gap_info->num[i]; + + delta_query += n; + delta_subject += n; + num_left -= n; + i += d; + } + break; + + case eGapAlignDel: + if (is_subject) { + if (hsp->gap_info->num[i] > num_left) { + hsp->gap_info->num[i] -= num_left; + delta_subject += num_left; + num_left = 0; + } + else { + delta_subject += hsp->gap_info->num[i]; + num_left -= hsp->gap_info->num[i]; + i += d; + } + } + else { + delta_subject += hsp->gap_info->num[i]; + i += d; + } + break; + + case eGapAlignIns: + if (is_query) { + if (hsp->gap_info->num[i] > num_left) { + hsp->gap_info->num[i] -= num_left; + delta_query += num_left; + num_left = 0; + } + else { + delta_query += hsp->gap_info->num[i]; + num_left -= hsp->gap_info->num[i]; + i += d; + } + } + else { + delta_query += hsp->gap_info->num[i]; + i += d; + } + break; + + default: + ASSERT(0); + break; + } + } + + /* shift edit script elements to fill the removed ones */ + if (is_start && i > 0) { + for (k = 0;k < hsp->gap_info->size - i;k++) { + hsp->gap_info->op_type[k] = hsp->gap_info->op_type[k + i]; + hsp->gap_info->num[k] = hsp->gap_info->num[k + i]; + } + hsp->gap_info->size -= i; + } + + if (is_end) { + hsp->gap_info->size = i + 1; + } + + /* update the Jumper edit script */ + if (is_start) { + Int4 pos = hsp->query.offset + delta_query; + i = 0; + while (i < hsp->map_info->edits->num_edits && + hsp->map_info->edits->edits[i].query_pos < pos) { + i++; + } + if (i > 0) { + for (k = 0;k < hsp->map_info->edits->num_edits - i;k++) { + hsp->map_info->edits->edits[k] = + hsp->map_info->edits->edits[k + i]; + } + hsp->map_info->edits->num_edits -= i; + } + } + else { + Int4 pos = hsp->query.end - delta_query - 1; + i = hsp->map_info->edits->num_edits - 1; + while (i >= 0 && hsp->map_info->edits->edits[i].query_pos > pos) { + i--; + } + hsp->map_info->edits->num_edits = i + 1; + } + + /* update HSP start positions */ + if (is_start) { + hsp->query.offset += delta_query; + hsp->subject.offset += delta_subject; + } + else { + hsp->query.end -= delta_query; + hsp->subject.end -= delta_subject; + } + + /* update HSP score */ + hsp->score = s_ComputeAlignmentScore(hsp, mismatch_score, gap_open_score, + gap_extend_score); + +#if _DEBUG + ASSERT(s_TestHSPRanges(hsp)); +#endif + + return 0; +} + + +#define NUM_ADAPTERS 4 +#define MAX_ADAPTER_LEN 20 + +/* Find adapeter on the 5' end in a single sequence. The search will start + towards the end of the last HSP (from, to) */ +static Int4 s_FindAdapterInSequence(Int4 hsp_from, Int4 hsp_to, Uint1* query, + Int4 query_len) +{ + Uint1 adapters_tab[NUM_ADAPTERS][MAX_ADAPTER_LEN] = { + /* Contaminants from FastQC config file: + http://www.bioinformatics.babraham.ac.uk/projects/fastqc/ */ + /* Illumina universal adapter: AGATCGGAAGAG */ + {0, 2, 0, 3, 1, 2, 2, 0, 0, 2, 0, 2}, + /* Illumina small RNA adapter: ATGGAATTCTCG */ + {0, 3, 2, 2, 0, 0, 3, 3, 1, 3, 1, 2}, + /* Nextera transosase sequence: CTGTCTCTTATA */ + {1, 3, 2, 3, 1, 3, 1, 3, 3, 0, 3, 0}, + /* Illumina multiplexing adapter 1: GATCGGAAGAGCACACGTCT */ + {2, 0, 3, 1, 2, 2, 0, 0, 2, 0, 2, 1, 0, 1, 0, 1, 2, 3, 1, 3}}; + + int lengths[NUM_ADAPTERS] = {12, 12, 12, 20}; + Boolean found = FALSE; + Int4 adapter_start = -1; + int adptr_idx; + Int4 from = hsp_from, to = hsp_to; + const Int4 kMaxErrors = 1; /* max number of mismaches allowed for matching + the adapter sequence + 1*/ + + + if (!query) { + return -1; + } + + for (adptr_idx = 0;!found && adptr_idx < NUM_ADAPTERS;adptr_idx++) { + Uint1* adapter = adapters_tab[adptr_idx]; + Uint4 word = *(Uint4*)adapter; + Int4 q = MAX(to - lengths[adptr_idx], from); + int i = 0; + while (q < query_len - 4 && q + i < query_len && i < lengths[adptr_idx]) { + while (q < query_len - 4 && *(Uint4*)(query + q) != word) { + q++; + } + if (q < query_len - 4) { + Int4 errors = kMaxErrors + 1; + i = 0; + while (q + i < query_len && i < lengths[adptr_idx] && + errors) { + + if (query[q + i] != adapter[i]) { + errors--; + } + i++; + } + if (q + i == query_len || i == lengths[adptr_idx]) { + adapter_start = q; + found = TRUE; + break; + } + + q++; + } + } + } + + ASSERT(adapter_start <= query_len); + return adapter_start; +} + + +/* Set adapter position in the chain and trim alignments that span beyond + adapter start position */ +static Int2 s_SetAdapter(HSPChain** chains_ptr, Int4 adapter_pos, + Int4 query_len, const ScoringOptions* scores) +{ + HSPChain* head = NULL; + HSPChain* chain = NULL; + const Int4 kMinAdapterLen = 3; + + if (!chains_ptr || !*chains_ptr || adapter_pos < 0) { + return -1; + } + + head = *chains_ptr; + chain = *chains_ptr; + /* iterate over chains */ + while (chain) { + BlastHSP* hsp = chain->hsps->hsp; + + /* check the 3' alignment extent on the query and skip this chain + if the query is covered almost to the end */ + if (hsp->query.frame > 0) { + /* for positive strand, check the last query position */ + HSPContainer* h = chain->hsps; + while (h->next) { + h = h->next; + } + ASSERT(h); + if (query_len - h->hsp->query.end < kMinAdapterLen) { + chain = chain->next; + continue; + } + } + else { + /* for negative strand, check the first query position */ + ASSERT(hsp); + if (hsp->query.offset < kMinAdapterLen) { + chain = chain->next; + continue; + } + } + + /* set adapter start position in the chain */ + chain->adapter = adapter_pos; + + /* Trim alignment that covers part of the adapter */ + /* for query on the positive strand */ + if (hsp->query.frame > 0) { + HSPContainer* h = chain->hsps; + + /* if all HSPs are behind the adapter, delete this chain; + we require that HSP without adapter is at least 5 bases long */ + if (h->hsp->query.offset >= adapter_pos - 5) { + HSPChain* prev = head; + HSPChain* next = chain->next; + while (prev && prev->next != chain) { + prev =prev->next; + } + + chain->next = NULL; + HSPChainFree(chain); + chain = next; + if (prev) { + prev->next = next; + } + else { + head = chain; + } + + continue; + } + + /* find the first HSP with end position after adapter */ + while (h && h->hsp->query.end <= adapter_pos) { + h = h->next; + } + + /* if one is found */ + if (h) { + HSPContainer* hh = NULL; + hsp = h->hsp; + + /* if adapter is with in the HSP trim the HSP */ + if (hsp->query.offset < adapter_pos ) { + Int4 old_score = hsp->score; + ASSERT(hsp->query.end - adapter_pos > 0); + s_TrimHSP(hsp, hsp->query.end - adapter_pos, TRUE, + FALSE, scores->penalty, scores->gap_open, + scores->gap_extend); + chain->score += hsp->score - old_score; + + /* remove HSPs after h as they are past the adapter */ + if (h->next) { + h->next = HSPContainerFree(h->next); + } + } + else { + /* otherwise delete h and everything after it */ + hh = chain->hsps; + while (hh && hh->next != h) { + hh = hh->next; + } + ASSERT(hh); + hh->next = HSPContainerFree(hh->next); + } + + /* compute the new chain score */ + chain->score = s_ComputeChainScore(chain, scores, query_len, + FALSE); + } + + /* mark adapter in the HSPs */ + h = chain->hsps; + while (h->next) { + h = h->next; + } + h->hsp->map_info->right_edge |= MAPPER_ADAPTER; + h->hsp->map_info->right_edge |= MAPPER_EXON; + } + else { + /* negative strand: adapter is in the beginning of the chain */ + Int4 pos_minus = query_len - adapter_pos - 1; + HSPContainer* h = chain->hsps; + + /* find the first HSP with end position after adapter; + we require that HSP without adapter is at least 5 bases long */ + while (h && h->hsp->query.end <= pos_minus + 5) { + h = h->next; + } + + /* if all HSPs are before the adapter, delete this chain */ + if (!h) { + /* remove chain */ + HSPChain* prev = head; + HSPChain* next = chain->next; + while (prev && prev->next != chain) { + prev =prev->next; + } + + chain->next = NULL; + HSPChainFree(chain); + chain = next; + if (prev) { + prev->next = next; + } + else { + head = chain; + } + + continue; + } + + /* if h is not the first HSP in the chain, remove all HSPs before + h */ + if (h != chain->hsps) { + HSPContainer* hh = chain->hsps; + while (hh && hh->next != h) { + hh = hh->next; + } + ASSERT(hh); + hh->next = NULL; + HSPContainerFree(chain->hsps); + chain->hsps = h; + + /* compute new chain score */ + chain->score = s_ComputeChainScore(chain, scores, query_len, + FALSE); + } + ASSERT(h); + + /* set adapter information */ + hsp = chain->hsps->hsp; + hsp->map_info->left_edge |= MAPPER_ADAPTER; + hsp->map_info->left_edge |= MAPPER_EXON; + + /* trim HSP if necessary */ + if (pos_minus >= hsp->query.offset) { + Int4 old_score = hsp->score; + ASSERT(pos_minus - hsp->query.offset + 1 > 0); + s_TrimHSP(hsp, pos_minus - hsp->query.offset + 1, + TRUE, TRUE, scores->penalty, scores->gap_open, + scores->gap_extend); + chain->score += hsp->score - old_score; + } + } + + chain = chain->next; + } + + ASSERT(!head || s_TestChains(head)); + *chains_ptr = head; + + return 0; +} + + +static Int4 s_FindAdapters(HSPChain** saved, + const BLAST_SequenceBlk* query_blk, + const BlastQueryInfo* query_info, + const ScoringOptions* score_opts) +{ + Int4 query_idx; + + for (query_idx = 0;query_idx < query_info->num_queries;query_idx++) { + HSPChain* chain = NULL; + HSPChain* ch = NULL; + Uint1* query = NULL; + Int4 query_len; + Int4 from = -1, to = -1; + BlastHSP* hsp = NULL; + Int4 overhang = 0; + Int4 adapter_pos = -1; + + if (!saved[query_idx]) { + continue; + } + + /* we search for adapters and only in the plus strand of the query */ + query = query_blk->sequence + + query_info->contexts[query_idx * NUM_STRANDS].query_offset; + ASSERT(query); + query_len = query_info->contexts[query_idx * NUM_STRANDS].query_length; + + /* find the best scoring chain */ + chain = saved[query_idx]; + ch = chain->next; + for (; ch; ch = ch->next) { + if (ch->score > chain->score) { + chain = ch; + } + } + ASSERT(chain); + + /* find query coverage by the whole chain */ + if (chain->hsps->hsp->query.frame > 0) { + HSPContainer* h = chain->hsps; + from = h->hsp->query.offset; + while (h->next) { + h = h->next; + } + to = h->hsp->query.end; + } + else { + HSPContainer* h = chain->hsps; + to = query_len - h->hsp->query.offset; + while (h->next) { + h = h->next; + } + from = query_len - h->hsp->query.end; + } + ASSERT(from >= 0 && to >= 0); + + /* do not search for adapters if the query is mostly covered by the + best scoring chain */ + if (from < 20 && to > query_len - 3) { + continue; + } + + /* find the chain with the longest overhang */ + chain = saved[query_idx]; + ch = chain->next; + for (; ch; ch = ch->next) { + HSPContainer* h = ch->hsps; + if (h->hsp->query.frame > 0) { + while (h->next) { + h = h->next; + } + if (query_len - h->hsp->query.end > overhang) { + overhang = query_len - h->hsp->query.end; + chain = ch; + } + } + else { + if (h->hsp->query.offset + 1 > overhang) { + overhang = h->hsp->query.offset + 1; + chain = ch; + } + } + } + ASSERT(chain); + + /* find location from where to search for the adapter */ + hsp = chain->hsps->hsp; + if (hsp->query.frame > 0) { + HSPContainer* h = chain->hsps; + while (h->next) { + h = h->next; + } + hsp = h->hsp; + } + ASSERT(hsp); + + if (hsp->query.frame > 0) { + from = hsp->query.offset; + to = hsp->query.end; + } + else { + from = query_len - hsp->query.end; + to = query_len - hsp->query.offset; + } + + /* do not search for adapters if the read aligns almost to the end */ + if (to >= query_len - 3) { + continue; + } + + /* search for adapters */ + adapter_pos = s_FindAdapterInSequence(from, to, query, query_len); + + /* set adapter information in all chains and trim HSPs that extend + into the adapter */ + if (adapter_pos >= 0) { + s_SetAdapter(&(saved[query_idx]), adapter_pos, query_len, + score_opts); + } + } + + return 0; +} + + +/* Search for polyA tail at the end of a sequence and return the start position */ +static Int4 s_FindPolyAInSequence(Uint1* sequence, Int4 length) +{ + Int4 i; + const Uint1 kBaseA = 0; + Int4 num_a = 0; + Int4 err = 0; + const Int4 kMaxErrors = 3; + + if (!sequence) { + return -1; + } + + /* iterate over positions untile kMaxErrors non A bases are found */ + i = length - 1; + while (i >= 0 && err < kMaxErrors) { + if (sequence[i] != kBaseA) { + err++; + } + + i--; + } + i++; + + /* find the beginnig of the string of As */ + while (i < length - 1 && + (sequence[i] != kBaseA || sequence[i + 1] != kBaseA)) { + + if (sequence[i] != kBaseA) { + err--; + } + i++; + } + + num_a = length - i - err; + + /* short tails must have no errors */ + if (num_a < 3 || (num_a < 5 && err > 0)) { + return -1; + } + + return i; +} + + +/* Set PolyA information in HSP chains */ +static Int4 s_SetPolyATail(HSPChain* chains, Int4 positive_start, + Int4 negative_start, Int4 query_len) +{ + HSPChain* ch = NULL; + + if (!chains) { + return -1; + } + + for (ch = chains; ch; ch = ch->next) { + HSPContainer* h = ch->hsps; + while (h->next) { + h = h->next; + } + + if (query_len - h->hsp->query.end < 5) { + continue; + } + + if ((h->hsp->query.frame < 0 && negative_start >= 0) || + (h->hsp->query.frame > 0 && positive_start >= 0)) { + + h->hsp->map_info->right_edge |= MAPPER_POLY_A; + h->hsp->map_info->right_edge |= MAPPER_EXON; + + if (h->hsp->query.frame > 0) { + ch->polyA = MAX(positive_start, h->hsp->query.end); + } + else { + ch->polyA = MAX(negative_start, h->hsp->query.end); + } + } + } + + return 0; +} + + +static Int4 s_FindPolyATails(HSPChain** saved, + const BLAST_SequenceBlk* query_blk, + const BlastQueryInfo* query_info) +{ + Int4 query_idx; + + /* for each query */ + for (query_idx = 0;query_idx < query_info->num_queries;query_idx++) { + HSPChain* chain = NULL; + HSPChain* ch = NULL; + Uint1* query = NULL; + Int4 query_len; + Int4 from = -1, to = -1; + Int4 positive_start, negative_start; + + /* skip queries with no results and those with adapters */ + if (!saved[query_idx] || saved[query_idx]->adapter >= 0) { + continue; + } + + query_len = query_info->contexts[query_idx * NUM_STRANDS].query_length; + + /* find the best scoring chain */ + chain = saved[query_idx]; + ch = chain->next; + for (; ch; ch = ch->next) { + if (ch->score > chain->score) { + chain = ch; + } + } + ASSERT(chain); + + /* find query coverage by the whole chain */ + if (chain->hsps->hsp->query.frame > 0) { + HSPContainer* h = chain->hsps; + from = h->hsp->query.offset; + while (h->next) { + h = h->next; + } + to = h->hsp->query.end; + } + else { + HSPContainer* h = chain->hsps; + to = query_len - h->hsp->query.offset; + while (h->next) { + h = h->next; + } + from = query_len - h->hsp->query.end; + } + ASSERT(from >= 0 && to >= 0); + + /* do not search for polyA tails if the query is mostly covered by the + best scoring chain */ + if (from < 4 && to > query_len - 3) { + continue; + } + + /* search for polyA tail on the positive strand */ + query = query_blk->sequence + + query_info->contexts[query_idx * NUM_STRANDS].query_offset; + positive_start = s_FindPolyAInSequence(query, query_len); + + /* search for the polyA tail on the negative strand */ + query = query_blk->sequence + + query_info->contexts[query_idx * NUM_STRANDS + 1].query_offset; + negative_start = s_FindPolyAInSequence(query, query_len); + + /* set polyA start positions and HSP flags in the saved chains */ + if (positive_start >= 0 || negative_start >= 0) { + s_SetPolyATail(saved[query_idx], positive_start, negative_start, + query_len); + } + } + + return 0; +} + + +/* Merge two HSPs into one. The two HSPs may only be separated by at most + one gap or mismatch. Function returns NULL is the HSPs cannon be merged */ +static BlastHSP* s_MergeHSPs(const BlastHSP* first, const BlastHSP* second, + const Uint1* query, + const ScoringOptions* score_opts) +{ + BlastHSP* merged_hsp = NULL; /* this will be the result */ + const BlastHSP* hsp = second; + Int4 query_gap; + Int4 subject_gap; + Int4 mismatches = 0; + Int4 gap_info_size; + Int4 edits_size; + Int4 k; + + if (!first || !second || !query || !score_opts) { + return NULL; + } + + merged_hsp = Blast_HSPClone(first); + if (!merged_hsp) { + return NULL; + } + + query_gap = second->query.offset - first->query.end; + subject_gap = second->subject.offset - first->subject.end; + + if (query_gap < 0 || subject_gap < 0 || query_gap > 1 || + query_gap != subject_gap) { + + return NULL; + } + + gap_info_size = first->gap_info->size + second->gap_info->size + + MAX(query_gap, subject_gap); + + edits_size = first->map_info->edits->num_edits + + second->map_info->edits->num_edits + MAX(query_gap, subject_gap); + + /* FIXME: should be done through an API */ + /* reallocate memory for edit scripts */ + merged_hsp->gap_info->op_type = realloc(merged_hsp->gap_info->op_type, + gap_info_size * + sizeof(EGapAlignOpType)); + + merged_hsp->gap_info->num = realloc(merged_hsp->gap_info->num, + gap_info_size * + sizeof(Int4)); + + merged_hsp->map_info->edits->edits = realloc( + merged_hsp->map_info->edits->edits, + edits_size * sizeof(JumperEdit)); + + if (!merged_hsp->gap_info->op_type || + !merged_hsp->gap_info->num || + !merged_hsp->map_info->edits->edits) { + + Blast_HSPFree(merged_hsp); + return NULL; + } + + if (query_gap == subject_gap) { + mismatches = query_gap; + } + + /* add mismatches to gap_info */ + if (mismatches > 0) { + if (merged_hsp->gap_info->op_type[merged_hsp->gap_info->size - 1] + == eGapAlignSub) { + merged_hsp->gap_info->num[merged_hsp->gap_info->size - 1] += + mismatches; + } + else { + merged_hsp->gap_info->op_type[merged_hsp->gap_info->size] = + eGapAlignSub; + merged_hsp->gap_info->num[merged_hsp->gap_info->size] = + mismatches; + merged_hsp->gap_info->size++; + } + ASSERT(merged_hsp->gap_info->size <= gap_info_size); + } + + /* merge gap_info */ + for (k = 0;k < hsp->gap_info->size;k++) { + + if (merged_hsp->gap_info->op_type[merged_hsp->gap_info->size - 1] + == hsp->gap_info->op_type[k]) { + + merged_hsp->gap_info->num[merged_hsp->gap_info->size - 1] += + hsp->gap_info->num[k]; + } + else { + merged_hsp->gap_info->op_type[merged_hsp->gap_info->size] + = hsp->gap_info->op_type[k]; + + merged_hsp->gap_info->num[merged_hsp->gap_info->size++] + = hsp->gap_info->num[k]; + } + ASSERT(merged_hsp->gap_info->size <= gap_info_size); + } + + /* add mismatches to jumper edits */ + if (mismatches > 0) { + JumperEdit* edit = merged_hsp->map_info->edits->edits + + merged_hsp->map_info->edits->num_edits++; + edit->query_pos = merged_hsp->query.end; + /* FIXME: Mismatch bases cannot be currently set because there is + no access to query or subject sequence in this function. */ + edit->query_base = query[edit->query_pos]; + edit->subject_base = edit->query_base; + + ASSERT(merged_hsp->map_info->edits->num_edits <= edits_size); + } + + /* merge jumper edits */ + if (hsp->map_info->edits->num_edits) { + JumperEdit* edit = merged_hsp->map_info->edits->edits + + merged_hsp->map_info->edits->num_edits; + + ASSERT(merged_hsp->map_info->edits->num_edits + + hsp->map_info->edits->num_edits <= edits_size); + + memcpy(edit, hsp->map_info->edits->edits, + hsp->map_info->edits->num_edits * sizeof(JumperEdit)); + + merged_hsp->map_info->edits->num_edits += + hsp->map_info->edits->num_edits; + } + + /* update alignment extents, scores, etc */ + merged_hsp->query.end = hsp->query.end; + merged_hsp->subject.end = hsp->subject.end; + merged_hsp->score = s_ComputeAlignmentScore(merged_hsp, + score_opts->penalty, + score_opts->gap_open, + score_opts->gap_extend); + merged_hsp->num_ident += hsp->num_ident; + + merged_hsp->map_info->right_edge = hsp->map_info->right_edge; + if (!merged_hsp->map_info->subject_overhangs) { + return merged_hsp; + } + + if (!hsp->map_info->subject_overhangs || + !hsp->map_info->subject_overhangs->right_len || + !hsp->map_info->subject_overhangs->right) { + + merged_hsp->map_info->subject_overhangs->right_len = 0; + if (merged_hsp->map_info->subject_overhangs->right) { + sfree(merged_hsp->map_info->subject_overhangs->right); + merged_hsp->map_info->subject_overhangs->right = NULL; + } + } + else { + Int4 new_right_len = hsp->map_info->subject_overhangs->right_len; + if (merged_hsp->map_info->subject_overhangs->right_len < + new_right_len) { + + merged_hsp->map_info->subject_overhangs->right = + realloc(merged_hsp->map_info->subject_overhangs->right, + new_right_len * sizeof(Uint1)); + } + memcpy(merged_hsp->map_info->subject_overhangs->right, + hsp->map_info->subject_overhangs->right, + new_right_len * sizeof(Uint1)); + } + + return merged_hsp; +} + + +/* Find paired reads mapped to different database sequences */ +static int s_FindRearrangedPairs(HSPChain** saved, + const BlastQueryInfo* query_info) +{ + Int4 query_idx; + + /* iterate over single reads from each pair */ + for (query_idx = 0;query_idx + 1 < query_info->num_queries; query_idx++) { + HSPChain* chain = saved[query_idx]; + HSPChain* thepair = saved[query_idx + 1]; + + /* skip queries with no results */ + if (!chain || !thepair) { + continue; + } + + /* skip queries that do not have pairs */ + if (query_info->contexts[query_idx * NUM_STRANDS].segment_flags != + eFirstSegment) { + + continue; + } + + /* skip queries with more than one saved chain and ones that already + have a pair */ + if (chain->next || chain->pair || thepair->next) { + continue; + } + + /* skip chains aligned to the same subject; these are taken care of + elsewhere */ + if (chain->oid == thepair->oid) { + continue; + } + + /* skip HSP chains aligned on the same strands */ + if (SIGN(chain->hsps->hsp->query.frame) == + SIGN(thepair->hsps->hsp->query.frame)) { + continue; + } + + /* mark the pair */ + chain->pair = thepair; + thepair->pair = chain; + + chain->pair_conf = PAIR_PARALLEL; + thepair->pair_conf = PAIR_PARALLEL; + } + + return 0; +} + + +/* Sort chains by score in descending order */ +static int s_CompareChainsByScore(const void* cha, const void* chb) +{ + const HSPChain* a = *((HSPChain**)cha); + const HSPChain* b = *((HSPChain**)chb); + + if (a->score < b->score) { + return 1; + } + else if (a->score > b->score) { + return -1; + } + else { + return 0; + } +} + +/* Remove chains with scores below the these of the best ones considering + score bonus for pairs and count the number of chains with same of better + score for each chain */ +static int s_PruneChains(HSPChain** saved, Int4 num_queries, Int4 pair_bonus) + +{ + Int4 query_idx; + Int4 array_size = 10; + HSPChain** array = calloc(array_size, sizeof(HSPChain*)); + + /* Prunning is done in two passes: first considering single chains, + then considering pairs. The first pass breaks pairs where there is much + better chain with no pair. The second pass selects the best scoring + chains giving preference to pairs. Pairs are preferable, so they get + additional score. Two passes are requires, because we compare single + chains with single chains and pairs with pairs. This is to avoid + breaking pairs in situations with two pairs with one high scoring + chain. */ + + /* first pass: for each query remove poor scoring chains that may split + pairs */ + for (query_idx = 0; query_idx < num_queries; query_idx++) { + HSPChain* chain = saved[query_idx]; + HSPChain* prev = NULL; + Int4 best_score = 0; + + if (!chain || !chain->next) { + continue; + } + + /* find the best single chain score */ + for (chain = saved[query_idx]; chain; chain = chain->next) { + if (chain->score > best_score) { + best_score = chain->score; + } + } + + /* remove chains with poor scores, considering pair bonus */ + chain = saved[query_idx]; + while (chain) { + Int4 score = (chain->pair ? chain->score + pair_bonus : chain->score); + + if (score < best_score) { + HSPChain* next = chain->next; + + chain->next = NULL; + HSPChainFree(chain); + chain = next; + + if (prev) { + prev->next = next; + } + else { + saved[query_idx] = next; + } + } + else { + prev = chain; + chain = chain->next; + } + } + + } + + /* second pass: for each query remove chains scoring poorer than the best + ones considering pair bonus */ + for (query_idx = 0; query_idx < num_queries; query_idx++) { + HSPChain* chain = saved[query_idx]; + HSPChain* prev = NULL; + Int4 best_score = 0; + Int4 best_pair_score = 0; + Int4 i; + Int4 count = 0; + Int4 num_chains = 0; + + if (!chain) { + continue; + } + + if (!chain->next) { + chain->count = 1; + continue; + } + + /* find the best scores for single chains and pairs */ + for (chain = saved[query_idx]; chain; chain = chain->next) { + Int4 score = (chain->pair ? chain->score + pair_bonus : chain->score); + if (score >= best_score) { + best_score = score; + } + + if (chain->pair && + chain->score + chain->pair->score >= best_pair_score) { + + best_pair_score = chain->score + chain->pair->score; + } + + /* collect chains in the array */ + if (num_chains >= array_size) { + array_size *= 2; + array = realloc(array, array_size * sizeof(HSPChain*)); + if (!array) { + return -1; + } + } + array[num_chains++] = chain; + } + + /* sort chains by scores in descending order */ + ASSERT(num_chains > 1); + qsort(array, num_chains, sizeof(HSPChain*), s_CompareChainsByScore); + + /* find multiplicity for each chain: number of chains with same or + larger score */ + /* Note that multiplicity is currently not reported. Only the number + of returned hits for each query is reported */ + for (i = 0;i < num_chains; i++) { + Int4 k; + + count++; + /* check for chains with the same score */ + k = i + 1; + while (k < num_chains && array[k]->score == array[i]->score) { + k++; + count++; + } + + /* save multiplicity */ + for (;i < k;i++) { + array[i]->count = count; + } + i--; + } + + + /* remove chains with poor score and count chains with equal or better + score to the minimum pair one */ + chain = saved[query_idx]; + while (chain) { + Int4 score = (chain->pair ? chain->score + pair_bonus : chain->score); + + /* We compare single chains with single chains and pairs with + pairs. There may be pairs with one strong and one weak hit. + Comparing single chain scores we can be left with single chains + from different pairs. This comparison aviods that. The first + pass ensures that pairs with poor scoring chains are removed, + so we do not have to compare singles with pairs. */ + if ((!chain->pair && score < best_score) || + (chain->pair && chain->score + chain->pair->score < + best_pair_score)) { + + HSPChain* next = chain->next; + + chain->next = NULL; + HSPChainFree(chain); + chain = next; + + if (prev) { + prev->next = next; + } + else { + saved[query_idx] = next; + } + } + else { + prev = chain; + chain = chain->next; + } + } + } + + if (array) { + sfree(array); + } + + return 0; +} + + +/* Compare chains by subject oid and offfset */ +static int s_CompareChainsByOid(const void* cha, const void* chb) +{ + const HSPChain* a = *((HSPChain**)cha); + const HSPChain* b = *((HSPChain**)chb); + + if (a->oid > b->oid) { + return 1; + } + else if (a->oid < b->oid) { + return -1; + } + else if (a->hsps->hsp->subject.offset > b->hsps->hsp->subject.offset) { + return 1; + } + else if (a->hsps->hsp->subject.offset < b->hsps->hsp->subject.offset) { + return -1; + } + + return 0; +} + +/* Sort chains by subject oid and position and HSPs in the chains by query and + subject positions */ +static Int4 s_SortChains(HSPChain** saved, Int4 num_queries, + int(*comp)(const void*, const void*)) +{ + Int4 i; + Int4 array_size = 50; + HSPChain** chain_array = NULL; + + if (!saved || num_queries < 0) { + return -1; + } + + chain_array = calloc(array_size, sizeof(HSPChain*)); + if (!chain_array) { + return -1; + } + + /* for each query */ + for (i = 0;i < num_queries;i++) { + HSPChain* chain = saved[i]; + Int4 num_chains = 0; + Int4 k; + + if (!chain) { + continue; + } + + /* create an array of pointer to chains */ + for (; chain; chain = chain->next) { + if (num_chains >= array_size) { + array_size *= 2; + chain_array = realloc(chain_array, array_size * + sizeof(HSPChain*)); + + ASSERT(chain_array); + if (!chain_array) { + return -1; + } + } + chain_array[num_chains++] = chain; + } + + if (num_chains > 1) { + /* sort chains */ + qsort(chain_array, num_chains, sizeof(HSPChain*), comp); + + /* create the list of chains in the new order */ + for (k = 0;k < num_chains - 1;k++) { + chain_array[k]->next = chain_array[k + 1]; + } + chain_array[num_chains - 1]->next = NULL; + + saved[i] = chain_array[0]; + ASSERT(saved[i]); + } + } + + if (chain_array) { + free(chain_array); + } + + return 0; +} + +/* Convert internal HSPChain structure to BlastHSPChain used to report results */ +static BlastHSPChain* s_HSPChainToBlastHSPChain(HSPChain* chain) +{ + BlastHSPChain* new_chain = NULL; + HSPContainer* h = NULL; + Int4 num_hsps = 0; + Int4 index = 0; + + if (!chain || !chain->hsps) { + return NULL; + } + + new_chain = Blast_HSPChainNew(); + if (!new_chain) { + return NULL; + } + + new_chain->query_index = chain->context / NUM_STRANDS; + new_chain->oid = chain->oid; + new_chain->score = chain->score; + new_chain->adapter = chain->adapter; + new_chain->polyA = chain->polyA; + + /* move hsps */ + for (h = chain->hsps; h; h = h->next) { + num_hsps++; + } + new_chain->num_hsps = num_hsps; + new_chain->hsp_array = calloc(num_hsps, sizeof(BlastHSP*)); + if (!new_chain->hsp_array) { + return NULL; + } + for (h = chain->hsps; h; h = h->next) { + new_chain->hsp_array[index++] = h->hsp; + h->hsp = NULL; + } + + return new_chain; +} + +/* Separate HSPs that overlap on the query to different chains (most output + formats do not support query overlaps) */ +static int s_RemoveOverlaps(HSPChain* chain, const ScoringOptions* score_opts, + Int4 query_len) +{ + HSPContainer* h = NULL; + HSPContainer* prev = NULL; + HSPChain* tail = chain->next; + HSPChain* head = chain; + Boolean rescore = FALSE; + + if (!chain) { + return -1; + } + + /* current and previous HSP */ + h = chain->hsps->next; + prev = chain->hsps; + + for (; h; h = h->next) { + + /* if HSPs overlap on the query */ + if (prev->hsp->query.end > h->hsp->query.offset) { + /* do a flat copy of the chain */ + HSPChain* new_chain = HSPChainNew(chain->context); + memcpy(new_chain, chain, sizeof(HSPChain)); + new_chain->pair = NULL; + new_chain->next = NULL; + + /* new chain starts with h */ + new_chain->hsps = h; + + /* the original chain ends on the previous HSP */ + prev->next = NULL; + + /* add new chain to the list */ + head->next = new_chain; + head = new_chain; + + rescore = TRUE; + } + prev = h; + } + + /* compute chains scores */ + if (rescore) { + for (; chain; chain = chain->next) { + chain->score = s_ComputeChainScore(chain, score_opts, query_len, + FALSE); + } + } + + /* re-attach other chains to the list */ + head->next = tail; + + return 0; +} + +/* Populate HSP data and save final results */ +static int s_Finalize(HSPChain** saved, BlastMappingResults* results, + const BlastQueryInfo* query_info, + const BLAST_SequenceBlk* query_blk, + const ScoringOptions* score_opts, + Boolean is_paired) +{ + Int4 query_idx; + Int4 num_results = 0; + Int4 num = 0; + const Int4 kPairBonus = 21; + Int4* num_unique_chains = NULL; + + /* remove poor scoring chains and find chain multiplicity */ + if (!getenv("MAPPER_NO_PRUNNING")) { + s_PruneChains(saved, query_info->num_queries, kPairBonus); + } + + /* find adapters in query sequences */ + s_FindAdapters(saved, query_blk, query_info, score_opts); + + /* find polyA tails in query sequences */ + s_FindPolyATails(saved, query_blk, query_info); + + /* find pairs of chains aligned to different subjects */ + s_FindRearrangedPairs(saved, query_info); + + /* sort chains by subject oid to ensure stable results for multithreaded + runs; sorting must be done here so that compartment numbers are stable */ + /* FIXME: this may not be needed */ + s_SortChains(saved, query_info->num_queries, s_CompareChainsByOid); + + /* Compute number of results to store, and number of unique mappings for + each query (some chains may be copied to create pairs) */ + + num_unique_chains = calloc(query_info->num_queries, sizeof(Int4)); + if (!num_unique_chains) { + return -1; + } + + /* count number of unique mappings */ + for (query_idx = 0; query_idx < query_info->num_queries; query_idx++) { + HSPChain* chain = saved[query_idx]; + HSPChain* prev = chain; + + if (!chain) { + continue; + } + + num_unique_chains[query_idx]++; + + chain = chain->next; + for (; chain; chain = chain->next, prev = prev->next) { + if (prev->oid != chain->oid || + s_FindFragmentStart(prev) != s_FindFragmentStart(chain)) { + + num_unique_chains[query_idx]++; + } + } + } + + /* separate HSPs that overlap on the query into different chains */ + if (getenv("MAPPER_NO_OVERLAPPED_HSP_MERGE")) { + for (query_idx = 0; query_idx < query_info->num_queries; query_idx++) { + HSPChain* chain = saved[query_idx]; + Int4 query_len; + + if (!chain) { + continue; + } + + query_len = query_info->contexts[chain->context].query_length; + for (; chain; chain = chain->next) { + s_RemoveOverlaps(chain, score_opts, query_len); + } + + } + } + + /* count number of chains to report */ + for (query_idx = 0; query_idx < query_info->num_queries; query_idx++) { + HSPChain* chain = saved[query_idx]; + + for (; chain; chain = chain->next) { + num_results++; + } + } + + results->chain_array = calloc(num_results, sizeof(BlastHSPChain*)); + if (!results->chain_array) { + if (num_unique_chains) { + free(num_unique_chains); + } + return -1; + } + results->num_results = num_results; + + /* iterate over queries */ + for (query_idx = 0;query_idx < query_info->num_queries;query_idx++) { + HSPChain* chain = saved[query_idx]; + + /* skip queries for which there are no saved results */ + if (!chain) { + continue; + } + + for (; chain; chain = chain->next) { + BlastHSPChain* new_chain = NULL; + BlastHSPChain* pair = NULL; + + /* pairs are processed together so that we can store their pointers + so a chain whose pair's context is smaller was already processed + */ + if (chain->pair && chain->context > chain->pair->context) { + continue; + } + + new_chain = s_HSPChainToBlastHSPChain(chain); + ASSERT(new_chain); + if (!new_chain) { + return -1; + } + new_chain->multiplicity = num_unique_chains[new_chain->query_index]; + + results->chain_array[num++] = new_chain; + + if (chain->pair) { + pair = s_HSPChainToBlastHSPChain(chain->pair); + chain->pair->compartment = -1; + + new_chain->pair = pair; + pair->pair = new_chain; + pair->multiplicity = num_unique_chains[pair->query_index]; + results->chain_array[num++] = pair; + } + } + + } + ASSERT(num == results->num_results); + + for (query_idx = 0; query_idx < query_info->num_queries; query_idx++) { + saved[query_idx] = HSPChainFree(saved[query_idx]); + } + + if (num_unique_chains) { + sfree(num_unique_chains); + } + + return 0; +} + +/** Perform post-run clean-ups + * @param data The buffered data structure [in] + * @param results The HSP results to propagate [in][out] + */ +static int +s_BlastHSPMapperFinal(void* data, void* mapping_results) +{ + BlastHSPMapperData* spl_data = data; + BlastHSPMapperParams* params = spl_data->params; + BlastMappingResults* results = (BlastMappingResults*)mapping_results; + + if (spl_data->saved_chains) { + s_Finalize(spl_data->saved_chains, results, spl_data->query_info, + spl_data->query, ¶ms->scoring_options, params->paired); + } + + if (spl_data->saved_chains) { + sfree(spl_data->saved_chains); + } + + return 0; +} + + +/* A node representing an HSP for finding the best chain of HSPs for RNA-seq */ +typedef struct HSPNode { + BlastHSP** hsp; /* pointer to the entry in hsp_list */ + Int4 best_score; /* score for path that starts at this node */ + struct HSPNode* path_next; /* next node in the path */ +} HSPNode; + + +/* Copy a array of HSP nodes */ +static int s_HSPNodeArrayCopy(HSPNode* dest, HSPNode* source, Int4 num) +{ + int i; + + if (!dest || !source) { + return -1; + } + + for (i = 0;i < num;i++) { + dest[i] = source[i]; + if (source[i].path_next) { + dest[i].path_next = dest + (source[i].path_next - source); + } + } + + return 0; +} + + +/* Maximum number of top scoring HSP chains to report for a single read and + strand */ +#define MAX_NUM_HSP_PATHS 40 + +/* A chain of HSPs aligning a spliced RNA-Seq read to a genome */ +typedef struct HSPPath { + HSPNode** start; /* array of chain starting nodes */ + int num_paths; /* number of chains */ + Int4 score; /* all chains in start have this cumulative score */ +} HSPPath; + + +static HSPPath* HSPPathFree(HSPPath* path) +{ + if (path) { + if (path->start) { + free(path->start); + } + free(path); + } + + return NULL; +} + +static HSPPath* HSPPathNew(void) +{ + HSPPath* retval = calloc(1, sizeof(HSPPath)); + if (!retval) { + return NULL; + } + + retval->start = calloc(MAX_NUM_HSP_PATHS, sizeof(HSPNode*)); + if (!retval->start) { + free(retval); + return NULL; + } + + return retval; +} + + +#define NUM_SIGNALS 14 + +/* Find a split for HSPs overlapping on the query by finding splice signals in + the subject sequence. The first HSP must have smaller query offset than the + second one. Subject is recreated from the query sequence and information + in an HSP. + @param first HSP with smaller query offset [in|out] + @param second HSP with larger query offset [in|out] + @param query Query sequence [in] + @return Status + */ +static Int4 +s_FindSpliceJunctionsForOverlaps(BlastHSP* first, BlastHSP* second, + Uint1* query, Int4 query_len) +{ + Int4 i, k; + /* splice signal pairs from PMC3167048 and spline output */ + Uint1 signals[NUM_SIGNALS] = {0xb2, /* GTAG */ + 0x71, /* CTAC (reverse complement) */ + 0x72, /* CTAG */ + 0x92, /* GCAG */ + 0x9e, /* GCTG */ + 0x90, /* GCAA */ + 0x9a, /* GCGG */ + 0xbe, /* GTTG */ + 0xb0, /* GTAA */ + 0x31, /* ATAC */ + 0x30, /* ATAA */ + 0x32, /* ATAG */ + 0x33, /* ATAT */ + + /*0x45, */ /* CACC */ + 0x1f /* ACTT */}; + Boolean found = FALSE; + Uint1* subject = NULL; + Int4 overlap_len; + const Uint1 kGap = 15; + + /* HSPs must be sorted and must overlap only on the query */ + ASSERT(first->query.offset < second->query.offset); + ASSERT(second->query.offset <= first->query.end); + ASSERT(first->subject.offset < second->subject.offset); + + + /* if there are edits within the overlap region, then try to maximize + the chain score by assigning a part of the overlap region to the + HSP that has fewer edits in the overlap */ + if ((first->map_info->edits->num_edits > 0 && + first->map_info->edits->edits[ + first->map_info->edits->num_edits - 1].query_pos >= + second->query.offset) + || (second->map_info->edits->num_edits > 0 && + second->map_info->edits->edits[0].query_pos <= first->query.end)) { + + /* find nummer of edits in both HSPs within the overlap and assign + overlap to the HSP that has fewer edits */ + Int4 num_first = 0; + Int4 num_second = 0; + + /* find number of edits */ + for (i = first->map_info->edits->num_edits - 1;i >= 0;i--) { + JumperEdit* edits = first->map_info->edits->edits; + if (edits[i].query_pos < second->query.offset) { + break; + } + num_first++; + } + + for (i = 0;i < second->map_info->edits->num_edits;i++) { + JumperEdit* edits = second->map_info->edits->edits; + if (edits[i].query_pos >= first->query.end) { + break; + } + num_second++; + } + + if (num_first > num_second) { + while (first->map_info->edits->num_edits > 0 && + first->map_info->edits->edits[ + first->map_info->edits->num_edits - 1].query_pos >= + second->query.offset) { + + JumperEdit* edits = first->map_info->edits->edits; + Uint1 edge = first->map_info->right_edge; + Int4 num_edits = first->map_info->edits->num_edits; + Int4 trim_by; + + if (edits[num_edits - 1].query_pos == query_len - 1) { + edge >>= 2; + edge |= edits[num_edits - 1].subject_base << 2; + } + else { + edge = (edits[num_edits - 1].subject_base << 2) | + query[edits[num_edits - 1].query_pos + 1]; + } + + trim_by = first->query.end - edits[ + first->map_info->edits->num_edits - 1].query_pos; + /* if the edit is an insert in the genome, count genome bases + when trimming the HSP */ + if (edits[num_edits - 1].query_base == kGap) { + trim_by++; + /* FIXME: use proper scores here */ + s_TrimHSP(first, trim_by, FALSE, FALSE, -4, -4, -4); + } + else { + s_TrimHSP(first, trim_by, TRUE, FALSE, -4, -4, -4); + } + first->map_info->right_edge = edge; + } + } + else if (num_second > num_first) { + while (second->map_info->edits->num_edits > 0 && + second->map_info->edits->edits[0].query_pos < + first->query.end) { + + JumperEdit* edits = second->map_info->edits->edits; + Uint1 edge = second->map_info->left_edge; + Int4 trim_by; + + if (edits[0].query_pos == 0) { + edge <<= 2; + edge |= edits[0].subject_base; + } + else { + edge = (query[edits[0].query_pos - 1] << 2) | + edits[0].subject_base; + } + + trim_by = edits[0].query_pos - second->query.offset + 1; + /* if the edit is an insert in the genome, count genome bases + when trimming the HSP */ + if (edits[0].query_base == kGap) { + trim_by++; + /* FIXME: use proper scores here */ + s_TrimHSP(second, + edits[0].query_pos - second->query.offset + 1, + FALSE, TRUE, -4, -4, -4); + } + else { + s_TrimHSP(second, + edits[0].query_pos - second->query.offset + 1, + TRUE, TRUE, -4, -4, -4); + } + second->map_info->left_edge = edge; + } + } + else { + /* if the number of edits is the same we do not know how to + divide the overlap */ + return 0; + } + } + + /* give up if there are gaps in the alignments or mismatches still left in + the overlapping parts */ + if ((first->map_info->edits->num_edits > 0 && + first->map_info->edits->edits[ + first->map_info->edits->num_edits - 1].query_pos >= + second->query.offset) + || (second->map_info->edits->num_edits > 0 && + second->map_info->edits->edits[0].query_pos <= first->query.end)) { + + return 0; + } + + /* recreate the subject sequence plus two bases on each side */ + overlap_len = first->query.end - second->query.offset; + subject = calloc(overlap_len + 4, sizeof(Uint1)); + if (!subject) { + return -1; + } + + /* FIXME: lef_edge and right_edge should be changed to subject_overhangs */ + subject[0] = (second->map_info->left_edge & 0xf) >> 2; + subject[1] = second->map_info->left_edge & 3; + memcpy(subject + 2, query + second->query.offset, + overlap_len * sizeof(Uint1)); + + subject[2 + overlap_len] = (first->map_info->right_edge & 0xf) >> 2; + subject[2 + overlap_len + 1] = first->map_info->right_edge & 3; + + /* search for matching splice signals in the subject sequence */ + for (k = 0;k < NUM_SIGNALS;k++) { + + for (i = 0;i <= overlap_len && !found;i++) { + + Uint1 seq = (subject[i] << 2) | subject[i + 1] | + (subject[i + 2] << 6) | (subject[i + 3] << 4); + + /* if a splice signals are found, update HSPs */ + if (seq == signals[k]) { + Int4 d = first->query.end - (second->query.offset + i); + first->query.end -= d; + first->subject.end -= d; + first->gap_info->num[first->gap_info->size - 1] -= d; + first->score -= d; + first->map_info->right_edge = (seq & 0xf0) >> 4; + first->map_info->right_edge |= MAPPER_SPLICE_SIGNAL; + + d = i; + second->query.offset += d; + second->subject.offset += d; + second->gap_info->num[0] -= d; + second->score -= d; + second->map_info->left_edge = seq & 0xf; + second->map_info->left_edge |= MAPPER_SPLICE_SIGNAL; + + ASSERT(first->gap_info->size > 1 || + first->query.end - first->query.offset == + first->subject.end - first->subject.offset); + + ASSERT(second->gap_info->size > 1 || + second->query.end - second->query.offset == + second->subject.end - second->subject.offset); + + found = TRUE; + break; + } + } + } + + if (!found) { + first->map_info->right_edge &= ~MAPPER_SPLICE_SIGNAL; + second->map_info->left_edge &= ~MAPPER_SPLICE_SIGNAL; + } + + if (subject) { + sfree(subject); + } + + ASSERT(first->query.offset < first->query.end); + ASSERT(second->query.offset < second->query.end); + + return 0; +} + +static void s_ExtendAlignmentCleanup(Uint1* subject, + BlastGapAlignStruct* gap_align, + GapEditScript* edit_script, + JumperEditsBlock* edits) +{ + if (subject) { + free(subject); + } + + BLAST_GapAlignStructFree(gap_align); + GapEditScriptDelete(edit_script); + JumperEditsBlockFree(edits); +} + +/* Extend alignment on one side of an HSP up to a given point (a splice site) +*/ +static Int4 s_ExtendAlignment(BlastHSP* hsp, const Uint1* query, + Int4 query_from, Int4 query_to, + Int4 subject_from, Int4 subject_to, + const ScoringOptions* score_options, + Boolean is_left) +{ + Int4 o_len; + Uint1* o_seq = NULL; + Uint1* subject = NULL; + BlastGapAlignStruct* gap_align = NULL; + GapEditScript* edit_script = NULL; + JumperEditsBlock* edits = NULL; + Int4 i, k, s; + /* number of query bases to align */ + Int4 query_gap = query_to - query_from + 1; + /* number of subject bases to align */ + Int4 subject_gap = subject_to - subject_from + 1; + Int4 num_identical; + Int4 query_ext_len, subject_ext_len; + Int4 ungapped_ext_len; + + JUMP* jumper_table = NULL; + + JUMP jumper_mismatch[] = {{1, 1, 0, 0}}; + + JUMP jumper_insertion[] = {{1, 1, 2, 0}, + {1, 0, 1, 0}, + {1, 1, 0, 0}}; + + JUMP jumper_deletion[] = {{1, 1, 2, 0}, + {0, 1, 1, 0}, + {1, 1, 0, 0}}; + + if (!hsp || !query || !hsp->map_info || + !hsp->map_info->subject_overhangs) { + return -1; + } + + /* length of the subject overgang sequence saved in the HSP */ + o_len = is_left ? hsp->map_info->subject_overhangs->left_len : + hsp->map_info->subject_overhangs->right_len; + /* subject sequence */ + o_seq = is_left ? hsp->map_info->subject_overhangs->left : + hsp->map_info->subject_overhangs->right; + ASSERT(o_seq); + + /* compressed subject sequence (needed for computig jumper edits) */ + subject = calloc(o_len / 4 + 1, sizeof(Uint1)); + if (!subject) { + return -1; + } + + /* compress subject sequence */ + k = 6; + s = 0; + for (i = 0;i < o_len;i++, k-=2) { + subject[s] |= o_seq[i] << k; + if (k == 0) { + s++; + k = 8; + } + } + + /* gap_align is needed in jumper alignment API calls, we only allocate + fields that will be needed in these calls */ + gap_align = calloc(1, sizeof(BlastGapAlignStruct)); + if (!gap_align) { + s_ExtendAlignmentCleanup(subject, NULL, edit_script, edits); + return -1; + } + gap_align->jumper = JumperGapAlignNew(o_len * 2); + if (!gap_align->jumper) { + s_ExtendAlignmentCleanup(subject, gap_align, edit_script, edits); + return -1; + } + + /* select jumper table based on the number of expected indels; we allow + only insertions or only deletions */ + switch (SIGN(query_gap - subject_gap)) { + case 0: jumper_table = jumper_mismatch; + break; + + case -1: jumper_table = jumper_deletion; + break; + + case 1: jumper_table = jumper_insertion; + break; + + default: + ASSERT(0); + s_ExtendAlignmentCleanup(subject, gap_align, edit_script, edits); + return -1; + }; + + /* Compute alignment. We always do right extension as this is typically + a short alignment. This is global alignment, hence the large max number + of errors and no penalties for mismatches or gaps. The jumper table + specifies costs for alignment errors. The penalty socres specify + required number of macthes at the ends of the alignment. */ + JumperExtendRightWithTraceback(query + query_from, o_seq + subject_from, + query_gap, subject_gap, + 1, 0, 0, 0, + 20, 20, + &query_ext_len, &subject_ext_len, + gap_align->jumper->right_prelim_block, + &num_identical, + FALSE, + &ungapped_ext_len, + jumper_table); + + ASSERT(query_ext_len <= query_gap); + ASSERT(subject_ext_len <= subject_gap); + + /* Because this is a global alignment a gap may exist after the last query + or subject base which causes jumper extension to stop prematurely. If + this is the case, add the missing indel */ + while (query_ext_len < query_gap) { + JumperPrelimEditBlockAdd(gap_align->jumper->right_prelim_block, + JUMPER_INSERTION); + + query_ext_len++; + } + + while (subject_ext_len < subject_gap) { + JumperPrelimEditBlockAdd(gap_align->jumper->right_prelim_block, + JUMPER_DELETION); + + subject_ext_len++; + } + ASSERT(query_ext_len == query_gap); + ASSERT(subject_ext_len == subject_gap); + + /* update gap info in the HSP */ + edit_script = JumperPrelimEditBlockToGapEditScript( + gap_align->jumper->left_prelim_block, + gap_align->jumper->right_prelim_block); + if (!edit_script) { + s_ExtendAlignmentCleanup(subject, gap_align, edit_script, edits); + return -1; + } + + if (is_left) { + hsp->gap_info = GapEditScriptCombine(&edit_script, &hsp->gap_info); + } + else { + hsp->gap_info = GapEditScriptCombine(&hsp->gap_info, &edit_script); + ASSERT(!edit_script); + } + ASSERT(hsp->gap_info); + if (!hsp->gap_info) { + s_ExtendAlignmentCleanup(subject, gap_align, edit_script, edits); + return -1; + } + + /* update jumper edits */ + gap_align->query_start = query_from; + gap_align->query_stop = query_from + query_ext_len; + gap_align->subject_start = subject_from; + gap_align->subject_stop = subject_from + subject_ext_len; + edits = JumperFindEdits(query, subject, gap_align); + ASSERT(edits); + if (!edits) { + s_ExtendAlignmentCleanup(subject, gap_align, NULL, edits); + return -1; + } + + if (is_left) { + hsp->map_info->edits = JumperEditsBlockCombine(&edits, + &hsp->map_info->edits); + } + else { + hsp->map_info->edits = JumperEditsBlockCombine( + &hsp->map_info->edits, + &edits); + ASSERT(!edits); + } + ASSERT(hsp->map_info->edits); + if (!hsp->map_info->edits) { + s_ExtendAlignmentCleanup(subject, gap_align, NULL, edits); + return -1; + } + + if (is_left) { + hsp->query.offset -= query_ext_len; + hsp->subject.offset -= subject_ext_len; + } + else { + hsp->query.end += query_ext_len; + hsp->subject.end += subject_ext_len; + } + + /* compute new HSP score */ + hsp->score = s_ComputeAlignmentScore(hsp, score_options->penalty, + score_options->gap_open, + score_options->gap_extend); + + ASSERT(hsp->gap_info); + ASSERT(hsp->map_info->edits); + + ASSERT(subject); + + + if (subject) { + free(subject); + } + BLAST_GapAlignStructFree(gap_align); + + return 0; +} + +#define NUM_SIGNALS_CONSENSUS 2 + +/* Find splcie junctions and extend HSP alignment if there are unaligned query + bases in the middle of a chain. +*/ +static Int4 +s_FindSpliceJunctionsForGap(BlastHSP* first, BlastHSP* second, + Uint1* query, Int4 query_len, + const ScoringOptions* score_options) +{ + Int4 query_gap; + Int4 first_len, second_len; + Boolean found = FALSE; + Int4 k; + Int4 q; + Uint1 signal = 0; + /* use only cannonical splice signals here */ + Uint1 signals[NUM_SIGNALS_CONSENSUS] = {0xb2, /* GTAG */ + 0x71 /* CTAC */}; + + if (!first || !second) { + return -1; + } + + if (!first->map_info->subject_overhangs || + !first->map_info->subject_overhangs->right || + !second->map_info->subject_overhangs || + !second->map_info->subject_overhangs->left) { + return -1; + } + + /* number of query bases that fall between the HSPs */ + query_gap = second->query.offset - first->query.end; + + /* we do not have enough subject sequence saved */ + if (query_gap > first->map_info->subject_overhangs->right_len || + query_gap > second->map_info->subject_overhangs->left_len) { + return 0; + } + + first_len = first->map_info->subject_overhangs->right_len; + second_len = second->map_info->subject_overhangs->left_len; + + /* assume that the begining of intron was found, search for the splice + signal at the end of the first HSP */ + for (q = 0; !found && q < 4;q++) { + + if (first->query.end - q <= first->query.offset) { + break; + } + + for (k = 0;k < NUM_SIGNALS_CONSENSUS && !found;k++) { + Int4 i; + Int4 status = 0; + Int4 start; + Uint1 seq; + + if (q == 0) { + seq = (first->map_info->subject_overhangs->right[0] << 6) | + (first->map_info->subject_overhangs->right[1] << 4); + } + else if (q == 1) { + seq = (query[first->query.end - 1] << 6) | + (first->map_info->subject_overhangs->right[0] << 4); + } + else if (q > 1) { + seq = (query[first->query.end - q] << 6) | + (query[first->query.end - q + 1] << 4); + } + else { + return -1; + } + + if (seq != (signals[k] & 0xf0)) { + continue; + } + + /* location of the splice signa in subject overhang if there are no + indels */ + start = second->map_info->subject_overhangs->left_len - 1 - + query_gap - 2 - q; + + /* search for the splice signal at the end of intron; + allow for up to 1 indel */ + for (i = MAX(start - 1, 0);i <= MIN(start + 1, second_len);i++) { + seq &= 0xf0; + seq |= (second->map_info->subject_overhangs->left[i] << 2) | + second->map_info->subject_overhangs->left[i + 1]; + + /* if the splice signal found extend the alignment */ + if (seq == signals[k]) { + Int4 subject_gap = second_len - (i + 2) + q; + if (query_gap - subject_gap < -1 || + query_gap - subject_gap > 1) { + + continue; + } + + found = TRUE; + if (q > 0) { + s_TrimHSP(first, q, TRUE, FALSE, + score_options->penalty, + score_options->gap_open, + score_options->gap_extend); + } + + status = s_ExtendAlignment(second, query, + first->query.end, + second->query.offset - 1, + i + 2, + second->map_info->subject_overhangs->left_len - 1, + score_options, + TRUE); + + ASSERT(status == 0); + if (status) { + return status; + } + + signal = seq; + break; + } + } + } + } + + /* assume that end of the intron was found, search for the splice signal + at the beginning of the intron */ + for (q = 0; !found && q < 4;q++) { + + if (second->query.offset + q >= second->query.end) { + break; + } + + for (k = 0;k < NUM_SIGNALS_CONSENSUS && !found;k++) { + Int4 i; + Int4 end; + Uint1 seq; + if (q == 0) { + seq = + (second->map_info->subject_overhangs->left[second_len - 2] << 2) | + second->map_info->subject_overhangs->left[second_len - 1]; + } + else if (q == 1) { + seq = (second->map_info->subject_overhangs->left[second_len - 1] << 2) | query[second->query.offset]; + + + } + else if (q > 1) { + + if (second->map_info->edits->num_edits > 0 && + second->map_info->edits->edits[0].query_pos < q - 2) { + + break; + } + + seq = (query[second->query.offset + q - 2] << 2) | + query[second->query.offset + q + 1 - 2]; + } + else { + return -1; + } + + if (seq != (signals[k] & 0xf)) { + continue; + } + + /* location of the splice signal in the subject overhang if there are + no indels */ + end = query_gap + q; + + /* allow for up to 1 indel */ + for (i = MAX(end - 1, 0);i <= MIN(end + 1, first_len);i++) { + seq &= 0xf; + seq |= (first->map_info->subject_overhangs->right[i] << 6) | + (first->map_info->subject_overhangs->right[i + 1] << 4); + + if (seq == signals[k]) { + Int4 status = 0; + Int4 subject_gap = i - q; + if (query_gap - subject_gap < -1 || + query_gap - subject_gap > 1) { + + continue; + } + + found = TRUE; + if (q > 0) { + s_TrimHSP(second, q, TRUE, TRUE, + score_options->penalty, + score_options->gap_open, + score_options->gap_extend); + } + + status = s_ExtendAlignment(first, query, + first->query.end, + second->query.offset - 1, + 0, i - 1, + score_options, + FALSE); + ASSERT(status == 0); + if (status) { + return status; + } + + signal = seq; + break; + } + } + } + } + + if (found) { + first->map_info->right_edge = (signal & 0xf0) >> 4; + first->map_info->right_edge |= MAPPER_SPLICE_SIGNAL; + second->map_info->left_edge = signal & 0xf; + second->map_info->left_edge |= MAPPER_SPLICE_SIGNAL; + + ASSERT(first->gap_info->size > 1 || + first->query.end - first->query.offset == + first->subject.end - first->subject.offset); + + ASSERT(second->gap_info->size > 1 || + second->query.end - second->query.offset == + second->subject.end - second->subject.offset); + } + else { + first->map_info->right_edge &= ~MAPPER_SPLICE_SIGNAL; + second->map_info->left_edge &= ~MAPPER_SPLICE_SIGNAL; + } + + return 0; +} + + +#define NUM_SINGLE_SIGNALS 8 + +/* Record subject bases pre and post alignment in HSP as possible splice + signals and set a flag for recognized signals */ +static Int4 s_FindSpliceSignals(BlastHSP* hsp, Uint1* query, Int4 query_len) +{ + SequenceOverhangs* overhangs = NULL; + /* splice signals in the order of preference */ + Uint1 signals[NUM_SINGLE_SIGNALS] = {2, /* AG */ + 11, /* GT */ + 13, /* TC */ + 7, /* CT */ + 1, /* AC */ + 4, /* CA */ + 8, /* GA */ + 14 /* TG */}; + + if (!hsp || !query) { + return -1; + } + + overhangs = hsp->map_info->subject_overhangs; + ASSERT(overhangs); + + if (!overhangs) { + return -1; + } + + /* FIXME: check for polyA and adapters */ + + /* search for a splice signal on the left edge, unless the query is aligned + from the beginning */ + if (hsp->query.offset == 0) { + hsp->map_info->left_edge = MAPPER_EXON; + } + else { + int k, i; + Boolean found = FALSE; + + if (overhangs->left_len >= 2) { + Uint1 signal = (overhangs->left[overhangs->left_len - 2] << 2) | + overhangs->left[overhangs->left_len - 1]; + + for (k = 0;k < NUM_SINGLE_SIGNALS;k++) { + if (signal == signals[k]) { + hsp->map_info->left_edge = signal; + hsp->map_info->left_edge |= MAPPER_SPLICE_SIGNAL; + + found = TRUE; + break; + } + } + } + + if (!found && overhangs->left_len >= 1) { + Uint1 signal = (overhangs->left[overhangs->left_len - 1] << 2) | + query[hsp->query.offset]; + + for (k = 0;k < NUM_SINGLE_SIGNALS;k++) { + if (signal == signals[k]) { + hsp->map_info->left_edge = signal; + hsp->map_info->left_edge |= MAPPER_SPLICE_SIGNAL; + + /* trim alignment */ + s_TrimHSP(hsp, 1, TRUE, TRUE, -8, 0, -8); + + /* update score at some point */ + found = TRUE; + break; + } + } + } + + for (i = hsp->query.offset;!found && i < 4;i++) { + Uint1 signal = (query[i] << 2) | query[i + 1]; + for (k = 0;k < NUM_SINGLE_SIGNALS;k++) { + if (signal == signals[k]) { + hsp->map_info->left_edge = signal; + hsp->map_info->left_edge |= MAPPER_SPLICE_SIGNAL; + + /* trim alignment */ + s_TrimHSP(hsp, i + 2, TRUE, TRUE, -8, 0, -8); + + found = TRUE; + break; + } + } + } + } + + /* search for the splice signal on the right edge, unless the query is + aligned to the end */ + if (hsp->query.end == query_len) { + hsp->map_info->right_edge = MAPPER_EXON; + } + else { + int k, i; + Boolean found = FALSE; + + if (overhangs->right_len >= 2) { + Uint1 signal = (overhangs->right[0] << 2) | overhangs->right[1]; + for (k = 0;k < NUM_SINGLE_SIGNALS;k++) { + if (signal == signals[k]) { + hsp->map_info->right_edge = signal; + hsp->map_info->right_edge |= MAPPER_SPLICE_SIGNAL; + + found = TRUE; + break; + } + } + + } + + if (!found && overhangs->right_len >= 1) { + Uint1 signal = (query[hsp->query.end - 1] << 2) | + overhangs->right[0]; + + for (k = 0;k < NUM_SINGLE_SIGNALS;k++) { + if (signal == signals[k]) { + hsp->map_info->right_edge = signal; + hsp->map_info->right_edge |= MAPPER_SPLICE_SIGNAL; + + /* update HSP */ + s_TrimHSP(hsp, 1, TRUE, FALSE, -8, 0, -8); + + /* update score at some point */ + found = TRUE; + break; + } + } + + } + + for (i = hsp->query.end - 2;!found && i > hsp->query.end - 2 - 4;i--) { + Uint1 signal = (query[i] << 2) | query[i + 1]; + for (k = 0;k < NUM_SINGLE_SIGNALS;k++) { + if (signal == signals[k]) { + hsp->map_info->right_edge = signal; + hsp->map_info->right_edge |= MAPPER_SPLICE_SIGNAL; + + /* update HSP */ + s_TrimHSP(hsp, hsp->query.end - i, TRUE, FALSE, -8, 0, -8); + + found = TRUE; + break; + } + } + } + } + + return 0; +} + + +/* Search for splice signals between two HSPs in a chain. The HSPs in the + chain must be sorted by query position in asceding order. +*/ +static Int4 +s_FindSpliceJunctions(HSPChain* chains, + const BLAST_SequenceBlk* query_blk, + const BlastQueryInfo* query_info, + const ScoringOptions* scoring_opts) +{ + HSPChain* ch = NULL; + + if (!chains || !query_blk || !query_info || !scoring_opts) { + return -1; + } + + /* iterate over HSPs in the chain */ + for (ch = chains; ch; ch = ch->next) { + HSPContainer* h = ch->hsps; + Boolean searched = FALSE; + Uint1* query = NULL; + Int4 context; + Int4 query_len; + ASSERT(h); + + context = h->hsp->context; + query = query_blk->sequence + + query_info->contexts[context].query_offset; + query_len = query_info->contexts[context].query_length; + + + /* FIXME: check the overhangs of the first and last HSP and try finding + splice signal within a few bases in the HSP */ + if (!h->next) { + + s_FindSpliceSignals(h->hsp, query, query_len); + searched = TRUE; + } + + while (h->next) { + HSPContainer* next = h->next; + ASSERT(next); + + /* process overlap if found */ + if (next->hsp->query.offset <= h->hsp->query.end && + next->hsp->query.offset > h->hsp->query.offset) { + + s_FindSpliceJunctionsForOverlaps(h->hsp, next->hsp, query, + query_len); + searched = TRUE; + h = h->next; + } + /* if not a spliced alignment */ + else if (next->hsp->query.offset - h->hsp->query.end < 10 && + next->hsp->query.offset - h->hsp->query.end == + next->hsp->subject.offset - h->hsp->subject.end) { + + /* save pointer to hsps after next */ + HSPContainer* following = h->next->next; + BlastHSP* new_hsp = NULL; + + /* duplicate HSPContainer with the two HSPs */ + h->next->next = NULL; + + /* extend the first HSP to cover the gap between HSPs */ + if (next->hsp->query.offset - h->hsp->query.end > 1) { + BlastHSP* first = h->hsp; + BlastHSP* second = h->next->hsp; + + s_ExtendAlignment(first, query, first->query.end, + second->query.offset - 1, 0, + second->subject.offset - 1 - first->subject.end, + scoring_opts, FALSE); + } + + /* merge HSPs */ + new_hsp = s_MergeHSPs(h->hsp, h->next->hsp, query, + scoring_opts); + + if (new_hsp) { + + /* replace the two processed HSPs with the combined one */ + Blast_HSPFree(h->hsp); + HSPContainerFree(h->next); + h->hsp = new_hsp; + h->next = following; + } + else { + /* something went wrong with merging, use the initial + HSPs */ + h->next->next = following; + h = h->next; + } + } + else if (next->hsp->query.offset - h->hsp->query.end > 0) { + s_FindSpliceJunctionsForGap(h->hsp, next->hsp, query, + query_len, scoring_opts); + searched = TRUE; + h = h->next; + } + else { + h = h->next; + } + + /* FIXME: if a splice junction cannot be found, we can try looking + for the split between perfect matches */ + } + + /* Remove HSPs that have the same start position on the query or + subject within a chain. They may arise from modified HSP extents. */ + h = ch->hsps; + while (h->next) { + if (h->hsp->query.offset >= h->next->hsp->query.offset || + h->hsp->subject.offset >= h->next->hsp->subject.offset) { + + if (h->hsp->score >= h->next->hsp->score) { + HSPContainer* remove = h->next; + h->next = h->next->next; + remove->next = NULL; + HSPContainerFree(remove); + } + else { + HSPContainer* remove = h; + HSPContainer* prev = ch->hsps; + if (remove == ch->hsps) { + ch->hsps = remove->next; + h = ch->hsps; + } + else { + while (prev->next && prev->next != h) { + prev = prev->next; + } + ASSERT(prev->next && prev->next == remove); + + prev->next = remove->next; + h = prev; + } + remove->next = NULL; + HSPContainerFree(remove); + } + + continue; + + } + h = h->next; + } + + /* recalculated chain score if splice sites were searched */ + if (searched) { + ch->score = s_ComputeChainScore(ch, scoring_opts, query_len, FALSE); + } + } + + s_TestChains(chains); + + return 0; +} + + +/* Find the best scoring chain of HSPs for aligning a single RNA-Seq read to + a genome on a single strand, returns all top scoring chains */ +static HSPChain* s_FindBestPath(HSPNode* nodes, Int4 num, HSPPath* path, + Int4 oid, Boolean is_spliced, + const BLAST_SequenceBlk* query_blk, + const BlastQueryInfo* query_info, + const ScoringOptions* scoring_opts) +{ + int i, k; + Int4 best_score = 0; + const Int4 kMaxIntronLength = 900000; + /* FIXME: use mismatch and/or gap extend penalty here */ + HSPChain* retval = NULL; + + if (!path || !nodes || !num) { + return NULL; + } + path->num_paths = 0; + path->score = 0; + + for (i = num - 1;i >= 0;i--) { + + BlastHSP* hsp = *(nodes[i].hsp); + int self_score = nodes[i].best_score; + /* FIXME: the is_spliced condition is a hack */ + for (k = i + 1;k < num && is_spliced;k++) { + + BlastHSP* newhsp = *(nodes[k].hsp); + Int4 new_score = nodes[k].best_score + self_score - + s_GetOverlapCost(newhsp, *(nodes[i].hsp), 4); + + /* FIXME: some of the conditions double others */ + const Int4 hsp_len = hsp->query.end - hsp->query.offset; + const Int4 newhsp_len = newhsp->query.end - newhsp->query.offset; + const Int4 overlap_len = MAX(MIN(hsp->query.end, newhsp->query.end) - + MAX(hsp->query.offset, newhsp->query.offset), 0); + + /* add next HSP to the path only if there is fewer than 10 query + bases unaligned between HSPs, newhsp is not contained within + hsp, newhsp aligns to the subject behind hsp, and score improves */ + /* FIXME: there should be a penalty if new hsp->query.offset > + hsp->query.end */ + if (newhsp->query.offset - hsp->query.end < 10 && + newhsp->query.offset > hsp->query.offset && + newhsp->query.end > hsp->query.end && + newhsp->subject.offset - hsp->subject.end >= + /* the difference on query may be smaller than zero, + this will let as combine HSPs of which extension stopped + too soon (not real introns) */ + newhsp->query.offset - hsp->query.end && + newhsp->subject.offset - hsp->subject.end < kMaxIntronLength && + (double)overlap_len / hsp_len < 0.75 && + (double)overlap_len / newhsp_len < 0.75 && + new_score > nodes[i].best_score) { + + /* prefer paths with identified splice sites to those without + ones */ + /* FIXME: add min intron length to the condition below */ + if (newhsp->subject.offset - hsp->subject.end > 1) { + /* FIXME: The function that finds splice signals modifies + HSPs, so we need to clone HSPs here. */ + BlastHSP* hsp_copy = Blast_HSPClone(hsp); + BlastHSP* newhsp_copy = Blast_HSPClone(newhsp); + + HSPChain* chain = HSPChainNew(hsp->context); + chain->hsps = HSPContainerNew(&hsp_copy); + chain->hsps->next = HSPContainerNew(&newhsp_copy); + + s_FindSpliceJunctions(chain, query_blk, query_info, + scoring_opts); + + if ((chain->hsps->hsp->map_info->right_edge & + MAPPER_SPLICE_SIGNAL) == 0) { + +/* new_score += scoring_opts->no_splice_signal; */ + /* FIXME: temporarely, do not create chains if splice + signals are not found */ + new_score = 0; + } + + chain = HSPChainFree(chain); + } + else if (newhsp->query.offset - hsp->query.end == 1) { + /* FIXME: this is a temporary hack, we need to increase + the score of combining two HSP into one with a + mismatch so that it is scored the same as the one with + splice signal */ + new_score++; + } + else { + new_score = 0; + } + + if (new_score > nodes[i].best_score) { + nodes[i].best_score = new_score; + nodes[i].path_next = &(nodes[k]); + } + } + } + + /* we want to return all top scoring hits, so we save all paths with + top score */ + if (nodes[i].best_score == best_score) { + if (path->num_paths < MAX_NUM_HSP_PATHS) { + path->start[path->num_paths++] = &(nodes[i]); + } + } + else if (nodes[i].best_score > best_score) { + best_score = nodes[i].best_score; + path->start[0] = &(nodes[i]); + path->num_paths = 1; + } + } + ASSERT(path->num_paths); + path->score = path->start[0]->best_score; + + /* Find if any paths share an HSP and remove the one with the larger index. + Doing this at the end ensures that we find optimal path in terms of + score and/or HSP positions. */ + for (i = 0;i < path->num_paths - 1;i++) { + if (!path->start[i]) { + continue; + } + for (k = i + 1;k < path->num_paths;k++) { + HSPNode* node_i = path->start[i]; + if (!path->start[k]) { + continue; + } + + while (node_i) { + HSPNode* node_k = path->start[k]; + while (node_k) { + if (node_i->hsp[0] == node_k->hsp[0]) { + path->start[k] = NULL; + break; + } + node_k = node_k->path_next; + } + node_i = node_i->path_next; + } + + } + } + + ASSERT(path->num_paths > 0); + ASSERT(path->start[0]); + + /* conver from HSPPath to HSPChain structure */ + if (path->num_paths > 0) { + HSPChain* ch = NULL; + HSPContainer* hc = NULL; + HSPNode* node = path->start[0]; + + retval = HSPChainNew((*node->hsp)->context); + if (!retval) { + return NULL; + } + retval->oid = oid; + retval->score = path->score; + retval->hsps = hc = HSPContainerNew(node->hsp); + node = node->path_next; + while (node) { + hc->next = HSPContainerNew(node->hsp); + if (!hc->next) { + HSPChainFree(retval); + return NULL; + } + hc = hc->next; + node = node->path_next; + } + ASSERT(retval->hsps); + + ch = retval; + for (i = 1;i < path->num_paths;i++) { + node = path->start[i]; + if (!node) { + continue; + } + ch->next = HSPChainNew((*node->hsp)->context); + ASSERT(ch->next); + if (!ch->next) { + HSPChainFree(retval); + return NULL; + } + ch->next->oid = oid; + ch->next->score = path->score; + ch->next->hsps = hc = HSPContainerNew(node->hsp); + node = node->path_next; + while (node) { + hc->next = HSPContainerNew(node->hsp); + ASSERT(hc->next); + if (!hc->next) { + HSPChainFree(retval); + return NULL; + } + hc = hc->next; + node = node->path_next; + } + ch = ch->next; + ASSERT(ch->hsps); + } + } + + ASSERT(path->num_paths == 0 || s_TestChains(retval)); + + return retval; +} + +/* Compare HSPs by context (accending), and score (descending). */ +static int +s_CompareHSPsByContextScore(const void* v1, const void* v2) +{ + BlastHSP* h1,* h2; + BlastHSP** hp1,** hp2; + + hp1 = (BlastHSP**) v1; + hp2 = (BlastHSP**) v2; + h1 = *hp1; + h2 = *hp2; + + if (!h1 && !h2) + return 0; + else if (!h1) + return -1; + else if (!h2) + return 1; + + if (h1->context < h2->context) + return -1; + if (h1->context > h2->context) + return 1; + + if (h1->score < h2->score) + return 1; + if (h1->score > h2->score) + return -1; + + return 0; +} + +static int +s_CompareHSPsByContextSubjectOffset(const void* v1, const void* v2) +{ + BlastHSP* h1,* h2; + BlastHSP** hp1,** hp2; + + hp1 = (BlastHSP**) v1; + hp2 = (BlastHSP**) v2; + h1 = *hp1; + h2 = *hp2; + + if (!h1 && !h2) + return 0; + else if (!h1) + return 1; + else if (!h2) + return -1; + + /* If these are from different contexts, don't compare offsets */ + if (h1->context < h2->context) + return -1; + if (h1->context > h2->context) + return 1; + + if (h1->subject.offset < h2->subject.offset) + return -1; + if (h1->subject.offset > h2->subject.offset) + return 1; + + if (h1->query.offset < h2->query.offset) + return -1; + if (h1->query.offset > h2->query.offset) + return 1; + + /* tie breakers: sort by decreasing score, then + by increasing size of query range, then by + increasing subject range. */ + + if (h1->score < h2->score) + return 1; + if (h1->score > h2->score) + return -1; + + if (h1->query.end < h2->query.end) + return 1; + if (h1->query.end > h2->query.end) + return -1; + + if (h1->subject.end < h2->subject.end) + return 1; + if (h1->subject.end > h2->subject.end) + return -1; + + return 0; +} + + +/* Pair data, used for selecting optimal pairs of aligned chains */ +typedef struct Pairinfo +{ + HSPChain* first; + HSPChain* second; + Int4 distance; + Int4 conf; + Int4 score; + Int4 trim_first; // when a chain overextends past beginning of the pair + Int4 trim_second; // it needs to be trimmed + Boolean valid_pair; +} Pairinfo; + + +static void s_BlastHSPMapperSplicedRunCleanUp(HSPPath* path, + HSPNode* nodes, + Pairinfo* pair_data) +{ + HSPPathFree(path); + + if (nodes) { + sfree(nodes); + } + + if (pair_data) { + sfree(pair_data); + } +} + + +/* Compare two HSP chain pairs aligned for the same query and subject + by score and distance */ +static int +s_ComparePairs(const void* v1, const void* v2) +{ + Pairinfo* a = (Pairinfo*)v1; + Pairinfo* b = (Pairinfo*)v2; + + if (a->score > b->score) { + return -1; + } + if (a->score < b->score) { + return 1; + } + + if (a->conf < b->conf) { + return -1; + } + if (a->conf > b->conf) { + return 1; + } + + if (a->distance < b->distance) { + return -1; + } + if (a->distance > b->distance) { + return 1; + } + + return 0; +} + + +/* Trim beginning of a chain alignment up to the given subject position */ +static Int4 s_TrimChainStartToSubjPos(HSPChain* chain, Int4 subj_pos, + Int4 mismatch_score, + Int4 gap_open_score, + Int4 gap_extend_score) +{ + HSPContainer* h = NULL; + BlastHSP* hsp = NULL; + BlastHSP* next_hsp = NULL; + Int4 num_left; + Int4 old_score; + + ASSERT(chain); + ASSERT(subj_pos >= 0); + if (!chain || subj_pos < 0) { + return 0; + } + + /* first remove HSPs that are fully below the subject position */ + h = chain->hsps; + while (h && h->hsp->subject.end < subj_pos) { + HSPContainer* tmp = h; + ASSERT(tmp); + h = h->next; + tmp->next = NULL; + chain->score -= tmp->hsp->score; + HSPContainerFree(tmp); + } + ASSERT(h); + chain->hsps = h; + if (!h) { + return -1; + } + + /* if all remaning HSPs are above the subject position, then exit */ + if (h->hsp->subject.offset >= subj_pos) { + return 0; + } + + /* otherwise move HSP start positions */ + hsp = h->hsp; + num_left = subj_pos - hsp->subject.offset; + ASSERT(num_left > 0 && num_left <= hsp->subject.end - hsp->subject.offset); + + old_score = hsp->score; + s_TrimHSP(hsp, num_left, FALSE, TRUE, mismatch_score, gap_open_score, + gap_extend_score); + + /* update chain score */ + chain->score -= old_score - hsp->score; + + /* remove splice signals and exon flags */ + hsp->map_info->left_edge &= 0xff ^ MAPPER_SPLICE_SIGNAL; + hsp->map_info->left_edge &= 0xff ^ MAPPER_EXON; + + /* check whether the HSP is contained within the next one and remove it + if it is */ + next_hsp = NULL; + if (chain->hsps->next) { + next_hsp = chain->hsps->next->hsp; + } + if (next_hsp && hsp->query.offset >= next_hsp->query.offset) { + chain->hsps = h->next; + h->next = NULL; + HSPContainerFree(h); + } + + return 0; +} + +/* Trim chain alignment end up the the given subject position */ +static Int4 s_TrimChainEndToSubjPos(HSPChain* chain, Int4 subj_pos, + Int4 mismatch_score, + Int4 gap_open_score, Int4 gap_extend_score) +{ + HSPContainer* h = NULL; + BlastHSP* hsp = NULL; + Int4 num_left; + Int4 old_score; + + ASSERT(chain); + ASSERT(subj_pos >= 0); + if (!chain || subj_pos <= 0) { + return -1; + } + + /* first remove HSPs that are full above the subject position */ + h = chain->hsps; + while (h->next && h->next->hsp->subject.end < subj_pos) { + h = h->next; + } + + if (h->next) { + HSPContainer* hc = NULL; + if (h->next->hsp->subject.offset < subj_pos) { + h = h->next; + } + + /* update chain score */ + for (hc = h->next;hc != NULL;hc = hc->next) { + chain->score -= hc->hsp->score; + } + + HSPContainerFree(h->next); + h->next = NULL; + } + + /* if all remaning HSPs are below the subject position, exit */ + if (h->hsp->subject.end <= subj_pos) { + return 0; + } + + /* otheriwse move HSP end positions */ + hsp = h->hsp; + num_left = hsp->subject.end - subj_pos; + ASSERT(num_left > 0 && num_left <= hsp->subject.end - hsp->subject.offset); + + old_score = hsp->score; + s_TrimHSP(hsp, num_left, FALSE, FALSE, mismatch_score, gap_open_score, + gap_extend_score); + + /* update chain score */ + chain->score -= old_score - hsp->score; + + /* remove splice signals and exon flags */ + hsp->map_info->right_edge &= 0xff ^ MAPPER_SPLICE_SIGNAL; + hsp->map_info->right_edge &= 0xff ^ MAPPER_EXON; + + /* check whether the HSP is contained within the next one and remove it + if it is */ + if (chain->hsps != h) { + HSPContainer* hc = chain->hsps; + while (hc && hc->next != h) { + hc = hc->next; + } + ASSERT(hc && hc->next == h); + if (hc->hsp->query.end >= h->hsp->query.end) { + chain->score -= h->hsp->score; + HSPContainerFree(h); + hc->next = NULL; + } + } + + return 0; +} + + +/* Find optimal pairs */ +static Boolean s_FindBestPairs(HSPChain** first_list, + HSPChain** second_list, + Int4 min_score, + Pairinfo** pair_info_ptr, + Int4* max_num_pairs, + const ScoringOptions* scoring_options) +{ + HSPChain* first; + HSPChain* second; + Pairinfo* pair_info = *pair_info_ptr; + Int4 conv_bonus = 0; + Int4 num_pairs = 0; + Boolean found = FALSE; + + /* iterate over all pairs of HSP chains for the first and second read of + the pair and collect pair information */ + for (first = *first_list; first; first = first->next) { + for (second = *second_list; second; second = second->next) { + Int2 first_frame = first->hsps->hsp->query.frame; + Int2 second_frame = second->hsps->hsp->query.frame; + + /* reallocate pair info array if necessary */ + if (num_pairs >= *max_num_pairs) { + *max_num_pairs *= 2; + Pairinfo* new_pair_info = + realloc(pair_info, *max_num_pairs * sizeof(Pairinfo)); + if (!new_pair_info) { + return -1; + } + pair_info = new_pair_info; + *pair_info_ptr = new_pair_info; + } + + /* collect pair information */ + pair_info[num_pairs].first = first; + pair_info[num_pairs].second = second; + pair_info[num_pairs].score = first->score + second->score; + pair_info[num_pairs].trim_first = 0; + pair_info[num_pairs].trim_second = 0; + pair_info[num_pairs].valid_pair = 0; + + /* if the chains align on the opposite strands */ + ASSERT(first_frame != 0 && second_frame != 0); + if (SIGN(first_frame) != SIGN(second_frame)) { + HSPChain* plus = NULL, *minus = NULL; + Int4 plus_start, minus_start; + HSPContainer* hsp = NULL; + Int4 distance = 0; + + /* find which query aligns to plus and which to minus strand + on the subject */ + if (first_frame > 0) { + plus = first; + } + else { + minus = first; + } + if (second_frame > 0) { + plus = second; + } + else { + minus = second; + } + ASSERT(plus && minus); + + /* find start positions on the subject, for the minus strand we + are interested subject start position on the minus strand, + but the HSP has subject on plus and query on the minus + strand, so we need to flip the query */ + plus_start = plus->hsps->hsp->subject.offset; + hsp = minus->hsps; + while (hsp->next) { + hsp = hsp->next; + } + ASSERT(hsp); + minus_start = hsp->hsp->subject.end; + + /* this is also fragment length */ + distance = minus_start - plus_start; + pair_info[num_pairs].distance = distance; + + /* distance > 0 indicates a convergent pair (typical) */ + if (distance > 0) { + Int4 plus_end, minus_end; + hsp = plus->hsps; + while (hsp->next) { + hsp = hsp->next; + } + ASSERT(hsp); + plus_end = hsp->hsp->subject.end; + minus_end = minus->hsps->hsp->subject.offset; + + /* HSP chain end going past the beginning of the chain + for the pair, indicates that the this end of the + query may be aligned to an adapater instead of a real + sequence and needs to be trimmed */ + if (plus_end > minus_start || minus_end < plus_start) { + ASSERT(plus && minus); + + /* check the 3' (right) side of the fragment */ + if (plus_end > minus_start) { + ASSERT(plus_end - minus_start > 0); + + /* decrease the score by the trimmed portion; we + assume here that the trimmed part aligns + perfectly, which may not be the case, but this + score is only used for comparison with different + pairs */ + pair_info[num_pairs].score -= + plus_end - minus_start; + + /* Mark which chain and up to what subject location + needs to be trimmed. We cannot trim here, + because pair_info holds poiners to chains that + may be part of better pairs */ + if (plus == pair_info[num_pairs].first) { + pair_info[num_pairs].trim_first = minus_start; + } + else { + pair_info[num_pairs].trim_second = minus_start; + } + } + + /* check the 5' (left) side doe the fragment */ + if (minus_end < plus_start) { + ASSERT(plus_start - minus_end > 0); + + pair_info[num_pairs].score -= + plus_start - minus_end; + + if (minus == pair_info[num_pairs].first) { + pair_info[num_pairs].trim_first = plus_start; + } + else { + pair_info[num_pairs].trim_second = plus_start; + } + } + } + + pair_info[num_pairs].conf = PAIR_CONVERGENT; + + /* add a bonus for convergent pairs; because they are more + common we prefer them over different configurations + with a sligntly better score */ + pair_info[num_pairs].score += conv_bonus; + } + else { + pair_info[num_pairs].conf = PAIR_DIVERGENT; + } + + /* skip pairs with a score smaller than one found for a + different subject */ + if (pair_info[num_pairs].score < min_score) { + continue; + } + + num_pairs++; + } + else { + /* for read pairs aligned in the same direction */ + pair_info[num_pairs].conf = PAIR_PARALLEL; + pair_info[num_pairs].score -= 1; + num_pairs++; + } + } + } + + if (num_pairs > 0) { + Int4 i; + Int4 best_score = pair_info[0].score; + Int4 margin = 5; + HSPChain* ch = NULL; + + /* sort pair information by score, configuration distance */ + qsort(pair_info, num_pairs, sizeof(Pairinfo), s_ComparePairs); + + /* iterate over pair information and collect pairs */ + for (i=0;i < num_pairs;i++) { + HSPChain* f = pair_info[i].first; + HSPChain* s = pair_info[i].second; + + /* skip pairs with chains already used in other pairs */ + if (pair_info[i].first->pair || pair_info[i].second->pair) { + continue; + } + + /* skip pairs with scores significantly smaller than the best one + found */ + if (best_score - pair_info[i].score > margin) { + break; + } + + /* link chains as a pair */ + f->pair = s; + s->pair = f; + f->pair_conf = s->pair_conf = pair_info[i].conf; + pair_info[i].valid_pair = TRUE; + found = TRUE; + } + + /* for chains that pair with already paired chains, clone the paired + chain */ + for (ch = *first_list; ch; ch = ch->next) { + HSPChain* pair = NULL; + + if (ch->pair) { + continue; + } + + i = 0; + while (i < num_pairs && + (pair_info[i].first != ch || !pair_info[i].second->pair || + pair_info[i].conf != PAIR_CONVERGENT || + best_score - pair_info[i].score > margin)) { + i++; + } + if (i >= num_pairs) { + continue; + } + ASSERT(pair_info[i].second->pair); + + pair = s_CloneChain(pair_info[i].second); + ASSERT(pair); + ASSERT(s_TestChains(pair)); + pair_info[i].second = pair; + ch->pair = pair; + pair->pair = ch; + ch->pair_conf = pair->pair_conf = pair_info[i].conf; + pair_info[i].valid_pair = TRUE; + HSPChainListInsert(second_list, pair, FALSE); + } + + for (ch = *second_list; ch; ch = ch->next) { + HSPChain* pair = NULL; + + if (ch->pair) { + continue; + } + + i = 0; + while (i < num_pairs && + (pair_info[i].second != ch || !pair_info[i].first->pair || + pair_info[i].conf != PAIR_CONVERGENT || + best_score - pair_info[i].score > margin)) { + i++; + } + if (i >= num_pairs) { + continue; + } + ASSERT(pair_info[i].first->pair); + + pair = s_CloneChain(pair_info[i].first); + ASSERT(pair); + ASSERT(s_TestChains(pair)); + pair_info[i].first = pair; + ch->pair = pair; + pair->pair = ch; + ch->pair_conf = pair->pair_conf = pair_info[i].conf; + pair_info[i].valid_pair = TRUE; + HSPChainListInsert(first_list, pair, FALSE); + } + + /* trim the alignments that overextend beyond the pair */ + for (i = 0;i < num_pairs;i++) { + if (!pair_info[i].valid_pair || + !pair_info[i].first->pair || !pair_info[i].second->pair) { + continue; + } + + /* trim the first chain if its end goes beyond the start of + second on the subject */ + if (pair_info[i].trim_first > 0) { + if (pair_info[i].first->hsps->hsp->query.frame > 0) { + s_TrimChainEndToSubjPos(pair_info[i].first, + pair_info[i].trim_first, + scoring_options->penalty, + scoring_options->gap_open, + scoring_options->gap_extend); + } + else { + /* minus strand of the qurey is represented by another + (reverse complemented) sequence aligned like the plus + strand, so the end of the chain is really the beginnig + by query coordinates */ + s_TrimChainStartToSubjPos(pair_info[i].first, + pair_info[i].trim_first, + scoring_options->penalty, + scoring_options->gap_open, + scoring_options->gap_extend); + } + } + + /* trim the second chain if its end goes beyond the start of the + first on the subject */ + if (pair_info[i].trim_second > 0) { + if (pair_info[i].second->hsps->hsp->query.frame > 0) { + s_TrimChainEndToSubjPos(pair_info[i].second, + pair_info[i].trim_second, + scoring_options->penalty, + scoring_options->gap_open, + scoring_options->gap_extend); + } + else { + s_TrimChainStartToSubjPos(pair_info[i].second, + pair_info[i].trim_second, + scoring_options->penalty, + scoring_options->gap_open, + scoring_options->gap_extend); + } + } + + } + } + + return found; +} + + +/** Perform writing task for paired reads + * ownership of the HSP list and sets the dereferenced pointer to NULL. + * @param data To store results to [in][out] + * @param hsp_list Pointer to the HSP list to save in the collector. [in] + */ +static int +s_BlastHSPMapperSplicedPairedRun(void* data, BlastHSPList* hsp_list) +{ + BlastHSPMapperData* spl_data = data; + BlastHSPMapperParams* params = spl_data->params; + const ScoringOptions* scoring_opts = ¶ms->scoring_options; + Boolean is_spliced = params->splice; + BLAST_SequenceBlk* query_blk = spl_data->query; + BlastQueryInfo* query_info = spl_data->query_info; + const Int4 kDefaultMaxHsps = 1000; + Int4 max_hsps = kDefaultMaxHsps; + HSPNode* nodes = calloc(max_hsps, sizeof(HSPNode)); + HSPPath* path = NULL; + BlastHSP** hsp_array; + Int4 num_hsps = 0; + Int4 i; + + HSPChain** saved_chains = spl_data->saved_chains; + HSPChain* chain_array[2]; + HSPChain* first = NULL, *second = NULL; + Int4 workspace_size = 40; + Pairinfo* pair_workspace = calloc(workspace_size, sizeof(Pairinfo)); + /* the score bonus needs to include exon pars that were to short to be + aligned (at either end of the chain) */ + const Int4 kPairBonus = is_spliced ? 21 : 5; + + if (!hsp_list) { + s_BlastHSPMapperSplicedRunCleanUp(path, nodes, pair_workspace); + return 0; + } + + if (!params || !nodes) { + s_BlastHSPMapperSplicedRunCleanUp(path, nodes, pair_workspace); + return -1; + } + + hsp_array = hsp_list->hsp_array; + + path = HSPPathNew(); + + /* sort HSPs by query context and subject position for spliced aligments */ + if (is_spliced) { + qsort(hsp_array, hsp_list->hspcnt, sizeof(BlastHSP*), + s_CompareHSPsByContextSubjectOffset); + } + else { + /* for non spliced alignments, sort HSPs by query context and score */ + qsort(hsp_array, hsp_list->hspcnt, sizeof(BlastHSP*), + s_CompareHSPsByContextScore); + } + + i = 0; + chain_array[0] = NULL; + chain_array[1] = NULL; + while (i < hsp_list->hspcnt) { + + Int4 context = hsp_array[i]->context; + /* is this query the first segment of a pair */ + Boolean has_pair = (query_info->contexts[context].segment_flags == + eFirstSegment); + Int4 query_idx = context / NUM_STRANDS; + Int4 first_context = query_idx * NUM_STRANDS; + Int4 context_next_fragment = has_pair ? (query_idx + 2) * NUM_STRANDS : + (query_idx + 1) * NUM_STRANDS; + + HSPChain* new_chains = NULL; + + /* iterate over contexts that belong to a read pair */ + while (i < hsp_list->hspcnt && + hsp_array[i]->context < context_next_fragment) { + + memset(nodes, 0, num_hsps * sizeof(HSPNode)); + num_hsps = 0; + context = hsp_array[i]->context; + + /* collect HSPs for the current context */ + while (i < hsp_list->hspcnt && hsp_array[i]->context == context) { + + /* Overlapping portions of two consecutive subject chunks + may produce two HSPs representing the same alignment. We + drop one of them here (assuming the HSPs for the same + context are sorted by score or subject position). */ + BlastHSP* h = (num_hsps == 0 ? NULL : *nodes[num_hsps - 1].hsp); + if (!h || hsp_array[i]->context != h->context || + hsp_array[i]->subject.offset != h->subject.offset || + hsp_array[i]->score != h->score) { + + /* reallocate node array if necessary */ + if (num_hsps >= max_hsps) { + HSPNode* new_nodes = NULL; + + /* For non-spliced mapping we are only interested in + the best scoring whole HSPs. HSPs are sorted by + score and those that map to many places are not good + so the node array does not need to be extended. */ + if (!is_spliced) { + break; + } + + max_hsps *= 2; + new_nodes = calloc(max_hsps, sizeof(HSPNode)); + if (!nodes) { + s_BlastHSPMapperSplicedRunCleanUp(path, nodes, + pair_workspace); + return -1; + } + s_HSPNodeArrayCopy(new_nodes, nodes, num_hsps); + free(nodes); + nodes = new_nodes; + } + + nodes[num_hsps].hsp = &(hsp_array[i]); + nodes[num_hsps].best_score = hsp_array[i]->score; + + num_hsps++; + } + i++; + } + + /* find the best scoring chain of HSPs that align to exons + parts of the query and the subject */ + new_chains = s_FindBestPath(nodes, num_hsps, path, + hsp_list->oid, is_spliced, + query_blk, query_info, scoring_opts); + + ASSERT(new_chains); + HSPChainListInsert(&chain_array[(context - first_context) / + NUM_STRANDS], + new_chains, FALSE); + + /* skip HSPs for the same context if there are more then max + allowed per context */ + while (i < hsp_list->hspcnt && hsp_array[i]->context == context) { + i++; + } + } + +#if _DEBUG + ASSERT(!chain_array[0] || s_TestChainsSorted(chain_array[0])); + ASSERT(!chain_array[1] || s_TestChainsSorted(chain_array[1])); +#endif + + if (is_spliced && chain_array[0]) { + s_FindSpliceJunctions(chain_array[0], query_blk, query_info, + scoring_opts); + } + + if (is_spliced && chain_array[1]) { + s_FindSpliceJunctions(chain_array[1], query_blk, query_info, + scoring_opts); + } + + first = chain_array[0]; + second = chain_array[1]; + + /* If the chains provide sufficient score check for pairs. + The score bonus is added to prefer a pair with a slightly smaller + score to single chains with a better one. */ + if (first && second) { + + s_FindBestPairs(&first, &second, 0, &pair_workspace, + &workspace_size, scoring_opts); + + ASSERT(s_TestChains(first)); + ASSERT(s_TestChains(second)); + } + + /* save all chains and remove ones with scores lower than + best score - kPairBonus */ + if (first) { + HSPChainListInsert(&saved_chains[query_idx], first, TRUE); + HSPChainListTrim(saved_chains[query_idx], kPairBonus); + } + if (second) { + HSPChainListInsert(&saved_chains[query_idx + 1], second, TRUE); + HSPChainListTrim(saved_chains[query_idx + 1], kPairBonus); + } + +#if _DEBUG + ASSERT(!chain_array[0] || s_TestChainsSorted(saved_chains[query_idx])); + ASSERT(!chain_array[1] || s_TestChainsSorted(saved_chains[query_idx + 1])); +#endif + + /* make temporary lists empty */ + chain_array[0] = chain_array[1] = NULL; + } + + /* delete HSPs that were not saved in results */ + hsp_list = Blast_HSPListFree(hsp_list); + + s_BlastHSPMapperSplicedRunCleanUp(path, nodes, pair_workspace); + + return 0; +} + + +/** Free the writer + * @param writer The writer to free [in] + * @return NULL. + */ +static +BlastHSPWriter* +s_BlastHSPMapperFree(BlastHSPWriter* writer) +{ + BlastHSPMapperData *data = writer->data; + sfree(data->params); + sfree(writer->data); + sfree(writer); + return NULL; +} + +/** create the writer + * @param params Pointer to the hit paramters [in] + * @param query_info BlastQueryInfo (not used) [in] + * @return writer + */ +static +BlastHSPWriter* +s_BlastHSPMapperPairedNew(void* params, BlastQueryInfo* query_info, + BLAST_SequenceBlk* query) +{ + BlastHSPWriter* writer = NULL; + BlastHSPMapperData* data = NULL; +/* BlastHSPMapperParams * spl_param = params; */ + + /* allocate space for writer */ + writer = malloc(sizeof(BlastHSPWriter)); + + /* fill up the function pointers */ + writer->InitFnPtr = &s_BlastHSPMapperPairedInit; + writer->FinalFnPtr = &s_BlastHSPMapperFinal; + writer->FreeFnPtr = &s_BlastHSPMapperFree; + writer->RunFnPtr = &s_BlastHSPMapperSplicedPairedRun; + + /* allocate for data structure */ + writer->data = calloc(1, sizeof(BlastHSPMapperData)); + data = writer->data; + data->params = params; + data->query_info = query_info; + data->query = query; + + return writer; +} + + +/*************************************************************/ +/** The following are exported functions to be used by APP */ + +BlastHSPMapperParams* +BlastHSPMapperParamsNew(const BlastHitSavingOptions* hit_options, + const BlastScoringOptions* scoring_options) +{ + BlastHSPMapperParams* retval = NULL; + + if (hit_options == NULL) + return NULL; + + retval = (BlastHSPMapperParams*)malloc(sizeof(BlastHSPMapperParams)); + retval->hitlist_size = MAX(hit_options->hitlist_size, 10); + retval->paired = hit_options->paired; + retval->splice = hit_options->splice; + retval->program = hit_options->program_number; + retval->scoring_options.reward = scoring_options->reward; + retval->scoring_options.penalty = scoring_options->penalty; + retval->scoring_options.gap_open = -scoring_options->gap_open; + retval->scoring_options.gap_extend = -scoring_options->gap_extend; + retval->scoring_options.no_splice_signal = -2; + return retval; +} + +BlastHSPMapperParams* +BlastHSPMapperParamsFree(BlastHSPMapperParams* opts) +{ + if ( !opts ) + return NULL; + sfree(opts); + return NULL; +} + +BlastHSPWriterInfo* +BlastHSPMapperInfoNew(BlastHSPMapperParams* params) { + BlastHSPWriterInfo * writer_info = + malloc(sizeof(BlastHSPWriterInfo)); + + writer_info->NewFnPtr = &s_BlastHSPMapperPairedNew; + + writer_info->params = params; + return writer_info; +} diff --git a/c++/src/algo/blast/core/jumper.c b/c++/src/algo/blast/core/jumper.c new file mode 100644 index 00000000..7c47e74a --- /dev/null +++ b/c++/src/algo/blast/core/jumper.c @@ -0,0 +1,4025 @@ +/* $Id $ + * =========================================================================== + * + * PUBLIC DOMAIN NOTICE + * National Center for Biotechnology Information + * + * This software/database is a "United States Government Work" under the + * terms of the United States Copyright Act. It was written as part of + * the author's official duties as a United States Government employee and + * thus cannot be copyrighted. This software/database is freely available + * to the public for use. The National Library of Medicine and the U.S. + * Government have not placed any restriction on its use or reproduction. + * + * Although all reasonable efforts have been taken to ensure the accuracy + * and reliability of the software and data, the NLM and the U.S. + * Government do not and cannot warrant the performance or results that + * may be obtained by using this software or data. The NLM and the U.S. + * Government disclaim all warranties, express or implied, including + * warranties of performance, merchantability or fitness for any particular + * purpose. + * + * Please cite the author in any work or product based on this material. + * + * =========================================================================== + * + * Author: Greg Boratyn + * + * Implementaion of Jumper alignment + * + */ + +#include "blast_gapalign_priv.h" + +#include +#include + +#include "jumper.h" + + +JUMP jumper_default [] = { + {1, 1, 9, 0}, /* this was added for illumina */ + {2, 2, 10, 0}, /* try double mismatch before indels */ + {1, 0, 10, 0}, /* insert in 1 */ + {0, 1, 10, 0}, /* deletion in 1 */ + {1, 1, 6, 0}, + {1, 0, 7, 0}, + {0, 1, 7, 0}, + {1, 0, 10, 2}, + {0, 1, 10, 2}, + {2, 0, 10, 2}, + {0, 2, 10, 2}, + {3, 0, 13, 2}, + {0, 3, 13, 2}, +/* removed for illumina + {4, 0, 15, 3}, + {0, 4, 15, 3}, + {5, 0, 15, 3}, + {0, 5, 15, 3}, + {6, 0, 15, 3}, + {0, 6, 15, 3}, + {7, 0, 15, 3}, + {0, 7, 15, 3}, + {8, 0, 15, 3}, + {0, 8, 15, 3}, + {9, 0, 15, 3}, + {0, 9, 15, 3}, + {10, 0, 15, 3}, + {0, 10, 15, 3}, +*/ + {1, 1, 0, 0} /* default is punctual */ +} ; + +JUMP jumper_edge [] = { + {1, 0, 6, 0}, + {0, 1, 6, 0}, + {1, 0, 2, 0}, + {0, 1, 2, 0}, + {1, 1, 0, 0} +}; + + +JUMP jumper_ungapped [] = { + {1, 1, 0, 0} /* default is punctual */ +}; + + +#define GET_BASE(seq, pos, compressed) (compressed ? NCBI2NA_UNPACK_BASE(seq[pos >> 2], 3 - (pos & 3)) : seq[pos]) + + +#define UNPACK_BASE_OLD(seq, pos) ((((seq)[(pos) >> 2] << (2 * ((pos) & 3))) & 0xC0) >> 6) + + +#define UNPACK_BASE(seq, pos) (NCBI2NA_UNPACK_BASE((seq)[(pos) / 4], 3 - ((pos) & 3))) + + +#define JUMPER_EDIT_BLOCK_ADD(block, op) ((block)->edit_ops[(block)->num_ops++] = op) + + +/* convert jumper edit op type to BLAST op type */ +#define JOP_TO_OP(op) (op >= 0 ? eGapAlignSub : (op == JUMPER_INSERTION ? eGapAlignIns : eGapAlignDel)) + +/* get number of ops */ +#define JOP_TO_NUM(op) (op > 0 ? op : 1) + + +static JumperPrelimEditBlock* JumperPrelimEditBlockNew(Int4 size) +{ + JumperPrelimEditBlock* retval = calloc(1, sizeof(JumperPrelimEditBlock)); + if (!retval) { + return NULL; + } + + retval->edit_ops = calloc(size, sizeof(JumperOpType)); + if (!retval->edit_ops) { + free(retval); + return NULL; + } + + retval->num_allocated = size; + return retval; +} + +static JumperPrelimEditBlock* JumperPrelimEditBlockFree( + JumperPrelimEditBlock* block) +{ + if (block) { + if (block->edit_ops) { + free(block->edit_ops); + } + + free(block); + } + + return NULL; +} + +Int4 JumperPrelimEditBlockAdd(JumperPrelimEditBlock* block, JumperOpType op) +{ + if (block->num_ops >= block->num_allocated) { + block->edit_ops = realloc(block->edit_ops, + block->num_allocated * sizeof(JumperOpType) * 2); + + if (!block->edit_ops) { + return -1; + } + block->num_allocated *= 2; + } + + if (block->num_ops > 0 && block->edit_ops[block->num_ops - 1] > 0 && + op > 0) { + + block->edit_ops[block->num_ops - 1] += op; + } + else { + block->edit_ops[block->num_ops++] = op; + } + + return 0; +} + + +static void s_CreateTable(Uint4* table) +{ + int i, k; + for (i = 0; i < 256; i++) { + table[i] = 0; + for (k = 0;k < 4; k++) { + Uint4 cell = ((i >> (2 * k)) & 3); + switch (k) { + case 0: table[i] += cell << 3 * 8; break; + case 1: table[i] += cell << 2 * 8; break; + case 2: table[i] += cell << 1 * 8; break; + case 3: table[i] += cell; break; + default: ASSERT(0); + } + } + } +} + + +JumperGapAlign* JumperGapAlignFree(JumperGapAlign* jgap_align) +{ + if (!jgap_align) { + return NULL; + } + + JumperPrelimEditBlockFree(jgap_align->left_prelim_block); + JumperPrelimEditBlockFree(jgap_align->right_prelim_block); + if (jgap_align->table) { + free(jgap_align->table); + } + sfree(jgap_align); + return NULL; +} + + +JumperGapAlign* JumperGapAlignNew(Int4 size) +{ + JumperGapAlign* retval = (JumperGapAlign*)calloc(1, sizeof(JumperGapAlign)); + if (!retval) { + return NULL; + } + + retval->left_prelim_block = JumperPrelimEditBlockNew(size); + if (!retval->left_prelim_block) { + JumperGapAlignFree(retval); + return NULL; + } + + retval->right_prelim_block = JumperPrelimEditBlockNew(size); + if (!retval->right_prelim_block) { + JumperGapAlignFree(retval); + return NULL; + } + + retval->table = calloc(256, sizeof(Uint4)); + if (!retval->table) { + JumperGapAlignFree(retval); + return NULL; + } + s_CreateTable(retval->table); + + return retval; +} + +/* Reset prelim edit blocks so that they can be used for a new alignment */ +static void s_ResetJumperPrelimEditBlocks(JumperPrelimEditBlock* left, + JumperPrelimEditBlock* right) +{ + if (!left || !right) { + return; + } + + left->num_ops = 0; + right->num_ops = 0; +} + + +/* Get query and subject position at the edit_index element of the edit script. + The jumper edit script must be going forwadr (from right extension) and + *query_pos and *subject_pos must be initialized to start positions of + the HSP. The resulting positions will be in *query_pos and *subject_pos. */ +static int s_GetSeqPositions(JumperPrelimEditBlock* edit_script, + Int4 edit_index, + Int4* query_pos, Int4* subject_pos) +{ + Int4 j; + + ASSERT(edit_script); + ASSERT(query_pos); + ASSERT(subject_pos); + ASSERT(edit_index < edit_script->num_ops); + + if (!edit_script || !query_pos || !subject_pos) { + return -1; + } + + for (j = 0;j < edit_index;j++) { + ASSERT(j < edit_script->num_ops); + + if (edit_script->edit_ops[j] == JUMPER_MISMATCH) { + (*query_pos)++; + (*subject_pos)++; + } + else if (edit_script->edit_ops[j] == JUMPER_INSERTION) { + (*query_pos)++; + } + else if (edit_script->edit_ops[j] == JUMPER_DELETION) { + (*subject_pos)++; + } + else { + *query_pos += edit_script->edit_ops[j]; + *subject_pos += edit_script->edit_ops[j]; + } + } + + return 0; +} + + +/* Shift gaps to the right using the forward edit script (right extension). + Alignment score and number of matches may improve if input the alignment + is not optimal */ +static int s_ShiftGapsRight(JumperPrelimEditBlock* edit_script, + const Uint1* query, const Uint1* subject, + Int4 query_offset, Int4 subject_offset, + Int4 query_length, Int4 subject_length, + Int4* score, Int4 err_score, Int4* num_identical) +{ + Int4 i; + Int4 q_pos; + Int4 s_pos; + + ASSERT(score && num_identical); + + /* iterate over edit script elements */ + for (i = 0;i < edit_script->num_ops;i++) { + + /* if insertion or deltion */ + if (edit_script->edit_ops[i] < 0) { + + /* find the end of the gap; gap start will be marked with i and + k will be right after gap end */ + Int4 k = i + 1; + while (k < edit_script->num_ops && + edit_script->edit_ops[k] == edit_script->edit_ops[i]) { + k++; + } + + /* iterate over the next script elements and see if any can switch + sides with the indel */ + for (;k < edit_script->num_ops;k++) { + ASSERT(edit_script->edit_ops[i] < 0); + + /* if a deletion follows insertion (or the other way around), + change it into a mismatch, it is one error instead of two */ + if (edit_script->edit_ops[k] < 0 && + edit_script->edit_ops[k] != edit_script->edit_ops[i]) { + Int4 j; + + /* remove one indel */ + for (j = k;j < edit_script->num_ops - 1;j++) { + edit_script->edit_ops[j] = + edit_script->edit_ops[j + 1]; + } + edit_script->num_ops--; + /* change the leftmost indel to a mismatch */ + edit_script->edit_ops[i] = JUMPER_MISMATCH; + /* update poiner to the beginning of the gap */ + i++; + + /* update score */ + (*score) -= err_score; + + /* if there a no indels left, search for a new gap */ + if (i >= 0) { + break; + } + } + + /* if a mismatch follows an indel, move the mismatch to the + left; it will result in a different mismatch or a macth, + so alignment score will not decrease */ + if (edit_script->edit_ops[k] == JUMPER_MISMATCH) { + /* shift the mismatch to the left by swapping ops */ + JumperOpType tmp = edit_script->edit_ops[i]; + edit_script->edit_ops[i] = edit_script->edit_ops[k]; + edit_script->edit_ops[k] = tmp; + i++; + + /* check if mismatch did not change to a match and update + scores and identity if it did */ + q_pos = query_offset; + s_pos = subject_offset; + s_GetSeqPositions(edit_script, i - 1, &q_pos, &s_pos); + if (query[q_pos] == UNPACK_BASE(subject, s_pos)) { + edit_script->edit_ops[i - 1] = 1; + (*score) -= err_score; + (*score)++; + (*num_identical)++; + } + } + + /* if matches follow an indel, check if bases to the right + of the indel match bases to the left and move the matches + if they do */ + if (edit_script->edit_ops[k] > 0) { + + Int4 num_matches = (Int4)edit_script->edit_ops[k]; + Int4 /*j, */ b = 0; + + q_pos = query_offset; + s_pos = subject_offset; + s_GetSeqPositions(edit_script, i, &q_pos, &s_pos); + + /* find how many bases match */ + while (b < edit_script->edit_ops[k] && + query[q_pos] == UNPACK_BASE(subject, s_pos)) { + + b++; + q_pos++; + s_pos++; + ASSERT(q_pos <= query_length); + ASSERT(s_pos <= subject_length); + } + + /* if none, look for a new indel */ + if (b == 0) { + break; + } + + /* otherwise shift the gap to the right */ + ASSERT(i > 0); + /* if there are no matches preceding the indel, add a new + script element */ + if (edit_script->edit_ops[i - 1] <= 0) { + Int4 j; + /* make space */ + JumperPrelimEditBlockAdd(edit_script, JUMPER_MISMATCH); + for (j = edit_script->num_ops - 1;j > i;j--) { + edit_script->edit_ops[j] = + edit_script->edit_ops[j - 1]; + } + k++; + i++; + /* new matches will be here */ + edit_script->edit_ops[i - 1] = 0; + } + /* move matching bases to the left */ + edit_script->edit_ops[i - 1] += b; + edit_script->edit_ops[k] -= b; + + /* if not all matches were moved, search for a new indel */ + if (b < num_matches) { + break; + } + else { + /* otherwise remove the script element that held the + moved matches */ + Int4 j; + ASSERT(edit_script->edit_ops[k] == 0); + for (j = k;j < edit_script->num_ops - 1;j++) { + edit_script->edit_ops[j] = + edit_script->edit_ops[j + 1]; + } + edit_script->num_ops--; + ASSERT(edit_script->num_ops > 0); + k--; + } + } + } + + /* move indel pointer to the end of the indel, to find a new one */ + i = k - 1; + } + } + + + return 0; +} + + +/* Shift gaps to the right and update scores and identities */ +static int s_ShiftGaps(BlastGapAlignStruct* gap_align, + const Uint1* query, const Uint1* subject, + Int4 query_length, Int4 subject_length, + Int4 err_score, Int4* num_identical) +{ + Int4 i; + JumperPrelimEditBlock* left = gap_align->jumper->left_prelim_block; + JumperPrelimEditBlock* right = gap_align->jumper->right_prelim_block; + JumperPrelimEditBlock* combined = JumperPrelimEditBlockNew( + right->num_allocated); + /* create a single forward edit script from the scripts for the left + and right extensions */ + for (i = left->num_ops - 1;i >=0;i--) { + JUMPER_EDIT_BLOCK_ADD(combined, left->edit_ops[i]); + } + + for (i = 0;i < right->num_ops;i++) { + JUMPER_EDIT_BLOCK_ADD(combined, right->edit_ops[i]); + } + + for (i = 1;i < combined->num_ops;i++) { + if (combined->edit_ops[i - 1] > 0 && combined->edit_ops[i] > 0) { + Int4 k; + combined->edit_ops[i - 1] += combined->edit_ops[i]; + for (k = i + 1;k < combined->num_ops;k++) { + combined->edit_ops[k - 1] = combined->edit_ops[k]; + } + combined->num_ops--; + } + } + + /* shift gaps */ + s_ShiftGapsRight(combined, query, subject, gap_align->query_start, + gap_align->subject_start, query_length, + subject_length, &gap_align->score, + err_score, num_identical); + + /* trim flanking gaps */ + while (combined->num_ops > 0 && + combined->edit_ops[combined->num_ops - 1] < 0) { + + if (combined->edit_ops[combined->num_ops - 1] == JUMPER_DELETION) { + gap_align->subject_stop--; + } + else { + gap_align->query_stop--; + } + combined->num_ops--; + gap_align->score -= err_score; + } + + /* replace edit scripts with the new ones in gap_align */ + left->num_ops = 0; + JumperPrelimEditBlockFree(right); + gap_align->jumper->right_prelim_block = combined; + + return 0; +} + + +/* trimm the extension so that there is at least -mismatch penalty matches + after the last mismatch */ +static void s_TrimExtension(JumperPrelimEditBlock* jops, int margin, + const Uint1** cp, Int4* cq, Int4* num_identical, + Boolean is_right_ext) +{ + + Int4 num_matches = 0; + Int4 index = jops->num_ops - 1; + + if (jops->num_ops == 0 || margin == 0) { + return; + } + + /* no trimming if mismatches do not cost anything */ + if (margin == 0) { + return; + } + + /* find number of local matches + Consequitive match operations are not guaranteed to be combined in the + preliminary block. This is to facilitate faster extensions */ + + while (index >= 1 && jops->edit_ops[index] > 0) { + num_matches += jops->edit_ops[index]; + index--; + } + + /* we do not remove the last op; thanks to word hit there will be enough + matches, but extension starting at word hit edge may not have enugh + matches */ + while (jops->num_ops > 1 && num_matches < margin) { + + JumperOpType op = jops->edit_ops[jops->num_ops - 1]; + switch (JOP_TO_OP(op)) { + case eGapAlignSub: + if (op > 0) { + (*cp) += (is_right_ext ? -op : op); + (*cq) += (is_right_ext ? -op : op); + *num_identical -= op; + } + else if (is_right_ext) { + (*cp)--; + (*cq)--; + } + else { + (*cp)++; + (*cq)++; + } + break; + + case eGapAlignIns: + if (is_right_ext) { + (*cp)--; + } + else { + (*cp)++; + } + break; + + case eGapAlignDel: + if (is_right_ext) { + (*cq)--; + } + else { + (*cq)++; + } + break; + + default: + ASSERT(0); + } + jops->num_ops--; + + if (index >= jops->num_ops) { + num_matches = 0; + index = jops->num_ops - 1; + while (index >= 1 && jops->edit_ops[index] > 0) { + num_matches += jops->edit_ops[index]; + index--; + } + } + } + ASSERT(jops->num_ops > 0); + /* remove the last op (closest to the word match) only if it is different + than match */ + if (jops->num_ops == 1 && jops->edit_ops[0] <= 0) { + jops->num_ops--; + } + ASSERT(jops->num_ops == 0 || jops->edit_ops[jops->num_ops - 1] > 0); +} + +/* Create BLAST edit script from jumper scripts for left and right extensions */ +GapEditScript* JumperPrelimEditBlockToGapEditScript( + JumperPrelimEditBlock* rev_prelim_block, + JumperPrelimEditBlock* fwd_prelim_block) +{ + Int4 size = 0; + Int4 i; + Int4 index; + GapEditScript* retval; + EGapAlignOpType last_op; + + if (rev_prelim_block->num_ops == 0 && fwd_prelim_block->num_ops == 0) { + return NULL; + } + + /* find the size of the resulting edit scrtipt */ + size = 1; + last_op = rev_prelim_block->num_ops > 0 ? + JOP_TO_OP(rev_prelim_block->edit_ops[rev_prelim_block->num_ops - 1]) + : JOP_TO_OP(fwd_prelim_block->edit_ops[0]); + + for (i = rev_prelim_block->num_ops - 2;i >= 0;i--) { + if (last_op != JOP_TO_OP(rev_prelim_block->edit_ops[i])) { + size++; + last_op = JOP_TO_OP(rev_prelim_block->edit_ops[i]); + } + } + for (i = 0;i < fwd_prelim_block->num_ops;i++) { + if (last_op != JOP_TO_OP(fwd_prelim_block->edit_ops[i])) { + size++; + last_op = JOP_TO_OP(fwd_prelim_block->edit_ops[i]); + } + } + + retval = GapEditScriptNew(size); + + /* rev_prelim_block needs to be reveresed, because left extension edit + operations are collected backwards */ + index = 0; + if (rev_prelim_block->num_ops > 0) { + i = rev_prelim_block->num_ops - 1; + retval->op_type[index] = JOP_TO_OP(rev_prelim_block->edit_ops[i]); + retval->num[index] = JOP_TO_NUM(rev_prelim_block->edit_ops[i]); + last_op = retval->op_type[index]; + i--; + for (;i >= 0;i--) { + EGapAlignOpType current_op = JOP_TO_OP(rev_prelim_block->edit_ops[i]); + if (current_op == last_op) { + retval->num[index] += JOP_TO_NUM(rev_prelim_block->edit_ops[i]); + } + else { + index++; + retval->op_type[index] = JOP_TO_OP(rev_prelim_block->edit_ops[i]); + retval->num[index] = JOP_TO_NUM(rev_prelim_block->edit_ops[i]); + last_op = current_op; + } + } + } + + i = 0; + if (index == 0 && retval->num[index] == 0) { + retval->op_type[index] = JOP_TO_OP(fwd_prelim_block->edit_ops[i]); + retval->num[index] = JOP_TO_NUM(fwd_prelim_block->edit_ops[i]); + last_op = retval->op_type[index]; + i++; + } + for (;i < fwd_prelim_block->num_ops;i++) { + EGapAlignOpType current_op = JOP_TO_OP(fwd_prelim_block->edit_ops[i]); + if (current_op == last_op) { + retval->num[index] += JOP_TO_NUM(fwd_prelim_block->edit_ops[i]); + } + else { + index++; + retval->op_type[index] = JOP_TO_OP(fwd_prelim_block->edit_ops[i]); + retval->num[index] = JOP_TO_NUM(fwd_prelim_block->edit_ops[i]); + last_op = current_op; + } + } + + return retval; +} + + +/* Compute a score for an extension */ +static Int4 s_ComputeExtensionScore(JumperPrelimEditBlock* edit_script, + Int4 match_score, Int4 mismatch_score, + Int4 gap_open_score, Int4 gap_extend_score) +{ + Int4 score = 0; + Int4 i; + + for (i = 0;i < edit_script->num_ops;i++) { + Int4 op = edit_script->edit_ops[i]; + +/* indel penalty is the same as mismatch penalty + if (op < 0) { + continue; + } +*/ + + if (op > 0) { + score += op * match_score; + } + else if (op == 0) { + score += mismatch_score; + } + else { + score += gap_open_score; + while (i < edit_script->num_ops && edit_script->edit_ops[i] == op) { + score += gap_extend_score; + i++; + } + i--; + } + } + + return score; +} + + + +/* query is one base per byte, subject is 2NA, we assume that initial seed is + at byte edge */ + + +Int4 JumperExtendRightCompressed(const Uint1* query, const Uint1* subject, + int query_length, int subject_length, + Int4 match_score, Int4 mismatch_score, + Int4 gap_open_score, Int4 gap_extend_score, + int max_mismatches, int window, Uint4* table, + Int4* query_ext_len, Int4* subject_ext_len, + Int4* num_identical, + Int4* ungapped_ext_len) +{ + const Uint1 *cp, *cp1, *cpmax, *cpmax4, *cpstop = NULL; + Int4 cq, cq1, cqmax, cqmax4, cqstop = 0; + int i, n; + JUMP *jp; + int num_mismatches = 0; + int new_matches = 0; + Uint4 trace = 0; + Uint4 trace_mask = (1 << max_mismatches) - 1; + Int4 score = 0, best_score = 0; + Boolean is_ungapped = TRUE; + JUMP* jumper = jumper_default; + + if (!query || ! subject) { + return -1; + } + + cp = query; + cpmax = cp + query_length; + + /* or assume matches up to byte edge */ + cq = 0; + cqmax = subject_length; + + cpmax4 = cpmax - 4; + cqmax4 = cqmax - 4; + + /* skip the first pair as it is compared by the left extension */ + cp++; + cq++; + + while (cp < cpmax && cq < cqmax && num_mismatches < max_mismatches) { + + if (!(cq & 3) && cp < cpmax4 && cq < cqmax4) { + if (table[subject[cq / 4]] == *(Uint4*)(cp)) { + cp += 4; + cq += 4; + new_matches += 4; + continue; + } + } + + if (*cp == UNPACK_BASE(subject, cq)) { + cp++; + cq++; + new_matches++; + continue; + } + + jp = jumper; + jp-- ; + while (jp++) { /* 1, 1, 0, 0 = last always accepted */ + + if (!jp->lng) { + break; + } + + n = 0; + i = jp->ok; + cp1 = cp + jp->dcp; + cq1 = cq + jp->dcq; + while (i--) { + if (cp1 >= cpmax || cq1 >= cqmax + || *cp1++ != UNPACK_BASE(subject, cq1)) { + + goto next_jp; + } + cq1++; + } + + n = 0; + i = jp->lng; + cp1 = cp + jp->dcp; + cq1 = cq + jp->dcq; + if (i + cp1 >= cpmax || i + cq1 >= cqmax) { + continue; + } + while (i--) { + if (cp1 >= cpmax || cq1 >= cqmax) { + goto next_jp; + } + if (*cp1++ != UNPACK_BASE(subject, cq1)) { + if (++n > jp->ok) { + goto next_jp; + } + } + cq1++; + } + /* current jumper row works */ + break; + +next_jp: + continue; + } + + if (new_matches) { + if (trace) { + if (new_matches < window) { + trace <<= new_matches; + } + else { + trace = 0; + } + } + *num_identical += new_matches; + score += new_matches * match_score; + new_matches = 0; + } + + /* update recent errors and score */ + if (jp->dcp == jp->dcq) { + score += mismatch_score * jp->dcp; + if (trace & trace_mask) { + num_mismatches += jp->dcp; + trace <<= jp->dcp; + trace |= (1 << jp->dcp) - 1; + } + else { + num_mismatches = jp->dcp; + trace = (1 << jp->dcp) - 1; + } + } + /* note that we are not penalizing gaps */ + + /* save the length of the ungapped extension */ + if (is_ungapped && jp->dcp != jp->dcq) { + *ungapped_ext_len = cp - query - 1; + is_ungapped = FALSE; + } + + /* update cp and cq */ + cp += jp->dcp; + cq += jp->dcq; + + /* we have already checked that these are matches */ + if (jp->ok == 0 && jp->lng) { + cp += jp->lng; + cq += jp->lng; + trace <<= jp->lng; + *num_identical += jp->lng; + score += jp->lng * match_score; + } + + /* update optimal alignment extent */ + if (score >= best_score) { + cpstop = cp; + cqstop = cq; + best_score = score; + } + } + + /* if matches all the way to the end of a sequence */ + if (new_matches) { + *num_identical += new_matches; + score += new_matches * match_score; + if (score >= best_score) { + cpstop = cp; + cqstop = cq; + } + } + + *query_ext_len = cpstop - query; + *subject_ext_len = cqstop; + + if (is_ungapped) { + *ungapped_ext_len = *query_ext_len; + } + + return best_score; +} /* JumperExtendRightCompressed */ + + + +Int4 JumperExtendRightCompressedWithTraceback( + const Uint1* query, const Uint1* subject, + int query_length, int subject_length, + Int4 match_score, Int4 mismatch_score, + Int4 gap_open_score, Int4 gap_extend_score, + int max_mismatches, int window, Uint4* table, + Int4* query_ext_len, Int4* subject_ext_len, + JumperPrelimEditBlock* edit_script, + Int4* num_identical, + Boolean left_extension, + Int4* ungapped_ext_len, + JUMP* jumper) +{ + const Uint1 *cp, *cp1, *cpmax, *cpmax4; + Int4 cq, cq1, cqmax, cqmax4; + int i, n; + JUMP *jp; + int num_mismatches = 0; + int new_matches = 0; + Uint4 trace = 0; + Uint4 trace_mask = (1 << max_mismatches) - 1; + Boolean is_ungapped = TRUE; + + if (!query || ! subject) { + return -1; + } + + cp = query; + cpmax = cp + query_length; + + /* or assume matches up to byte edge */ + cq = 0; + cqmax = subject_length; + + cpmax4 = cpmax - 4; + cqmax4 = cqmax - 4; + + /* skip the first pair as it is compared by the left extension */ + cp++; + cq++; + if (!left_extension) { + new_matches++; + } + + while (cp < cpmax && cq < cqmax && num_mismatches < max_mismatches) { + + if (!(cq & 3) && cp < cpmax4 && cq < cqmax4) { + if (table[subject[cq / 4]] == *(Uint4*)(cp)) { + cp += 4; + cq += 4; + new_matches += 4; + continue; + } + } + + if (*cp == UNPACK_BASE(subject, cq)) { + cp++; + cq++; + new_matches++; + continue; + } + + jp = jumper; + jp-- ; + while (jp++) { /* 1, 1, 0, 0 = last always accepted */ + + if (!jp->lng) { + break; + } + + n = 0; + i = jp->ok; + cp1 = cp + jp->dcp; + cq1 = cq + jp->dcq; + while (i--) { + if (cp1 >= cpmax || cq1 >= cqmax + || *cp1++ != UNPACK_BASE(subject, cq1)) { + + goto next_jp; + } + cq1++; + } + + n = 0; + i = jp->lng; + cp1 = cp + jp->dcp; + cq1 = cq + jp->dcq; + if (i + cp1 >= cpmax || i + cq1 >= cqmax) { + continue; + } + while (i--) { + if (cp1 >= cpmax || cq1 >= cqmax) { + goto next_jp; + } + if (*cp1++ != UNPACK_BASE(subject, cq1)) { + if (++n > jp->ok) { + goto next_jp; + } + } + cq1++; + } + /* current jumper row works */ + break; + +next_jp: + continue; + } + + if (new_matches) { + ASSERT(edit_script->num_ops < edit_script->num_allocated); + JUMPER_EDIT_BLOCK_ADD(edit_script, new_matches); + if (trace) { + if (new_matches < window) { + trace <<= new_matches; + } + else { + trace = 0; + } + } + *num_identical += new_matches; + new_matches = 0; + } + + /* update recent errors */ + if (jp->dcp == jp->dcq) { + if (trace & trace_mask) { + num_mismatches += jp->dcp; + trace <<= jp->dcp; + trace |= (1 << jp->dcp) - 1; + } + else { + num_mismatches = jp->dcp; + trace = (1 << jp->dcp) - 1; + } + for (i = 0;i < jp->dcp;i++) { + ASSERT(edit_script->num_ops < edit_script->num_allocated); + JUMPER_EDIT_BLOCK_ADD(edit_script, JUMPER_MISMATCH); + } + } else if (jp->dcp > jp->dcq) { + for (i = 0;i < jp->dcp - jp->dcq;i++) { + ASSERT(edit_script->num_ops < edit_script->num_allocated); + JUMPER_EDIT_BLOCK_ADD(edit_script, JUMPER_INSERTION); + } + if (jp->dcq) { + /* either jp->dcp r jp->dcq must be zero or jp->dcp == jp->dcq + otherwise number of mismatches must be updated here */ + ASSERT(0); + } + } + else { + for (i = 0;i < jp->dcq - jp->dcp;i++) { + ASSERT(edit_script->num_ops < edit_script->num_allocated); + JUMPER_EDIT_BLOCK_ADD(edit_script, JUMPER_DELETION); + } + if (jp->dcp) { + /* either jp->dcp r jp->dcq must be zero or jp->dcp == jp->dcq + otherwise number of mismatches must be updated here */ + ASSERT(0); + } + } + + /* save the length of the ungapped extension */ + if (is_ungapped && jp->dcp != jp->dcq) { + *ungapped_ext_len = cp - query - 1; + is_ungapped = FALSE; + } + + /* update cp and cq */ + cp += jp->dcp; + cq += jp->dcq; + + /* we have already checked that these are matches */ + if (jp->ok == 0 && jp->lng) { + cp += jp->lng; + cq += jp->lng; + ASSERT(edit_script->num_ops < edit_script->num_allocated); + JUMPER_EDIT_BLOCK_ADD(edit_script, jp->lng); + trace <<= jp->lng; + *num_identical += jp->lng; + /* reset number of mismatches (we assume that error window is + smaller than jp->lng) */ + num_mismatches = 0; + } + } + + /* if matches all the way to the end of a sequence */ + if (new_matches) { + ASSERT(edit_script->num_ops < edit_script->num_allocated); + JUMPER_EDIT_BLOCK_ADD(edit_script, new_matches); + *num_identical += new_matches; + } + + /* find optimal length of the extension */ + s_TrimExtension(edit_script, -mismatch_score, &cp, &cq, num_identical, + TRUE); + + *query_ext_len = cp - query; + *subject_ext_len = cq; + + if (is_ungapped) { + *ungapped_ext_len = *query_ext_len; + } + + /* return extension score */ + return s_ComputeExtensionScore(edit_script, match_score, mismatch_score, + gap_open_score, gap_extend_score); +} /* JumperExtendRightCompressedWithTraceback */ + + +Int4 JumperExtendRightCompressedWithTracebackOptimal( + const Uint1* query, const Uint1* subject, + int query_length, int subject_length, + Int4 match_score, Int4 mismatch_score, + Int4 gap_open_score, Int4 gap_extend_score, + int max_mismatches, int window, Uint4* table, + Int4* query_ext_len, Int4* subject_ext_len, + JumperPrelimEditBlock* edit_script, + Int4* best_num_identical, + Boolean left_extension, + Int4* ungapped_ext_len) +{ + const Uint1 *cp, *cp1, *cpmax, *cpmax4, *cpstop = NULL; + Int4 cq, cq1, cqmax, cqmax4, cqstop = 0; + int i, n; + JUMP *jp; + int num_mismatches = 0; + int new_matches = 0; + Uint4 trace = 0; + Uint4 trace_mask = (1 << max_mismatches) - 1; + Boolean is_ungapped = TRUE; + Int4 score = 0, best_score = 0; + Int4 num_ops = 0, num_identical = *best_num_identical; + /* 0 - no gap, JUMPER_INSERTION, JUMPER_DELETION for open insertion or + deletion */ + Int4 last_gap_open = 0; + JUMP* jumper = jumper_default; + + if (!query || ! subject) { + return -1; + } + + cp = query; + cpmax = cp + query_length; + + /* or assume matches up to byte edge */ + cq = 0; + cqmax = subject_length; + + cpmax4 = cpmax - 4; + cqmax4 = cqmax - 4; + + /* skip the first pair as it is compared by the left extension */ + cp++; + cq++; + if (!left_extension) { + new_matches++; + } + + while (cp < cpmax && cq < cqmax && num_mismatches < max_mismatches) { + + if (!(cq & 3) && cp < cpmax4 && cq < cqmax4) { + if (table[subject[cq / 4]] == *(Uint4*)(cp)) { + cp += 4; + cq += 4; + new_matches += 4; + continue; + } + } + + if (*cp == UNPACK_BASE(subject, cq)) { + cp++; + cq++; + new_matches++; + continue; + } + + jp = jumper; + jp-- ; + while (jp++) { /* 1, 1, 0, 0 = last always accepted */ + + if (!jp->lng) { + break; + } + + n = 0; + i = jp->ok; + cp1 = cp + jp->dcp; + cq1 = cq + jp->dcq; + while (i--) { + if (cp1 >= cpmax || cq1 >= cqmax + || *cp1++ != UNPACK_BASE(subject, cq1)) { + + goto next_jp; + } + cq1++; + } + + n = 0; + i = jp->lng; + cp1 = cp + jp->dcp; + cq1 = cq + jp->dcq; + if (i + cp1 >= cpmax || i + cq1 >= cqmax) { + continue; + } + while (i--) { + if (cp1 >= cpmax || cq1 >= cqmax) { + goto next_jp; + } + if (*cp1++ != UNPACK_BASE(subject, cq1)) { + if (++n > jp->ok) { + goto next_jp; + } + } + cq1++; + } + /* current jumper row works */ + break; + +next_jp: + continue; + } + + if (new_matches) { + ASSERT(edit_script->num_ops < edit_script->num_allocated); + JUMPER_EDIT_BLOCK_ADD(edit_script, new_matches); + if (trace) { + if (new_matches < window) { + trace <<= new_matches; + } + else { + trace = 0; + } + } + num_identical += new_matches; + score += new_matches * match_score; + new_matches = 0; + last_gap_open = 0; + } + + /* update optimal alignment extent */ + if (score >= best_score) { + cpstop = cp; + cqstop = cq; + num_ops = edit_script->num_ops; + best_score = score; + *best_num_identical = num_identical; + } + + /* update recent errors */ + if (jp->dcp == jp->dcq) { + score += jp->dcp * mismatch_score; + if (trace & trace_mask) { + num_mismatches += jp->dcp; + trace <<= jp->dcp; + trace |= (1 << jp->dcp) - 1; + } + else { + num_mismatches = jp->dcp; + trace = (1 << jp->dcp) - 1; + } + for (i = 0;i < jp->dcp;i++) { + ASSERT(edit_script->num_ops < edit_script->num_allocated); + JUMPER_EDIT_BLOCK_ADD(edit_script, JUMPER_MISMATCH); + } + } else if (jp->dcp > jp->dcq) { + for (i = 0;i < jp->dcp - jp->dcq;i++) { + ASSERT(edit_script->num_ops < edit_script->num_allocated); + JUMPER_EDIT_BLOCK_ADD(edit_script, JUMPER_INSERTION); + score += gap_extend_score; + } + if (last_gap_open != JUMPER_INSERTION) { + score += gap_open_score; + } + last_gap_open = JUMPER_INSERTION; + if (jp->dcq) { + /* either jp->dcp r jp->dcq must be zero or jp->dcp == jp->dcq + otherwise number of mismatches must be updated here */ + ASSERT(0); + } + } + else { + for (i = 0;i < jp->dcq - jp->dcp;i++) { + ASSERT(edit_script->num_ops < edit_script->num_allocated); + JUMPER_EDIT_BLOCK_ADD(edit_script, JUMPER_DELETION); + score += gap_extend_score; + } + if (last_gap_open != JUMPER_DELETION) { + score += gap_open_score; + } + last_gap_open = JUMPER_DELETION; + if (jp->dcp) { + /* either jp->dcp r jp->dcq must be zero or jp->dcp == jp->dcq + otherwise number of mismatches must be updated here */ + ASSERT(0); + } + } + + /* save the length of the ungapped extension */ + if (is_ungapped && jp->dcp != jp->dcq) { + *ungapped_ext_len = cp - query - 1; + is_ungapped = FALSE; + } + + /* update cp and cq */ + cp += jp->dcp; + cq += jp->dcq; + + /* we have already checked that these are matches */ + if (jp->ok == 0 && jp->lng) { + cp += jp->lng; + cq += jp->lng; + ASSERT(edit_script->num_ops < edit_script->num_allocated); + JUMPER_EDIT_BLOCK_ADD(edit_script, jp->lng); + trace <<= jp->lng; + num_identical += jp->lng; + score += jp->lng * match_score; + last_gap_open = 0; + } + + /* update optimal alignment extent */ + if (score >= best_score) { + cpstop = cp; + cqstop = cq; + num_ops = edit_script->num_ops; + best_score = score; + *best_num_identical = num_identical; + } + } + + /* if matches all the way to the end of a sequence */ + if (new_matches) { + ASSERT(edit_script->num_ops < edit_script->num_allocated); + JUMPER_EDIT_BLOCK_ADD(edit_script, new_matches); + num_identical += new_matches; + score += new_matches; + } + + /* update optimal alignment extent */ + if (score >= best_score) { + cpstop = cp; + cqstop = cq; + num_ops = edit_script->num_ops; + best_score = score; + *best_num_identical = num_identical; + } + + *query_ext_len = cpstop - query; + *subject_ext_len = cqstop; + edit_script->num_ops = num_ops; + + if (is_ungapped) { + *ungapped_ext_len = *query_ext_len; + } + + return best_score; +} /* JumperExtendRightCompressedWithTracebackOptimal */ + + + +Int4 JumperExtendRight(const Uint1* query, const Uint1* subject, + int query_length, int subject_length, + Int4 match_score, Int4 mismatch_score, + Int4 gap_open_score, Int4 gap_extend_score, + int max_mismatches, int window, + int* query_ext_len, int* subject_ext_len, + GapPrelimEditBlock* edit_script, + Boolean left_extension) +{ + const Uint1 *cp, *cp1, *cpmax; + Int4 cq, cq1, cqmax; + int i, n; + JUMP *jp; + int score = 0, num_mismatches = 0; + int new_matches = 0; + Uint4 trace = 0; + Uint4 trace_mask = (1 << max_mismatches) - 1; + JUMP* jumper = jumper_default; + + if (!query || ! subject || !edit_script) { + return -1; + } + + cp = query; + cpmax = cp + query_length; + + /* or assume matches up to byte edge */ + cq = 0; + cqmax = subject_length; + + /* skip the first pair as it is compared by the left extension */ + cp++; + cq++; + if (!left_extension) { + new_matches++; + } + + while (cp < cpmax && cq < cqmax && num_mismatches < max_mismatches) { + + if (*cp == subject[cq]) { + score += match_score; + cp++; + cq++; + new_matches++; + continue; + } + + /* handle ambiguous bases */ + +/* this is only for 454 + jp = (cqmax - cq > 80) ? jumper : jumper_edge; +*/ + jp = jumper; + jp-- ; + while (jp++) { /* 1, 1, 0, 0 = last always accepted */ + + if (!jp->lng) { + break; + } + + n = 0; + i = jp->ok; + cp1 = cp + jp->dcp; + cq1 = cq + jp->dcq; + while (i--) { + if (cp1 >= cpmax || cq1 >= cqmax + || *cp1++ != subject[cq1]) { + + goto next_jp; + } + cq1++; + } + + n = 0; + i = jp->lng; + cp1 = cp + jp->dcp; + cq1 = cq + jp->dcq; + if (i + cp1 >= cpmax || i + cq1 >= cqmax) { + continue; + } + while (i--) { + if (cp1 >= cpmax || cq1 >= cqmax) { + goto next_jp; + } + if (*cp1++ != subject[cq1]) { + if (++n > jp->ok) { + goto next_jp; + } + } + cq1++; + } + /* current jumper row works */ + break; + +next_jp: + continue; + } + + if (new_matches) { + GapPrelimEditBlockAdd(edit_script, eGapAlignSub, new_matches); + if (trace) { + if (new_matches < window) { + trace <<= new_matches; + } + else { + trace = 0; + } + } + new_matches = 0; + } + +/* another stop condition, ensures a positive score *--/ + if (!jp->lng && num_mismatches >= score + mismatch_score) { + break; + } +*/ + + /* update score */ + if (jp->dcp == jp->dcq) { + score += mismatch_score * jp->dcp; + if (trace & trace_mask) { + num_mismatches += jp->dcp; + trace <<= jp->dcp; + trace |= (1 << jp->dcp) - 1; + } + else { + num_mismatches = jp->dcp; + trace = (1 << jp->dcp) - 1; + } + GapPrelimEditBlockAdd(edit_script, eGapAlignSub, jp->dcp); + } else if (jp->dcp > jp->dcq) { + score += gap_open_score + gap_extend_score * (jp->dcp - jp->dcq); + GapPrelimEditBlockAdd(edit_script, eGapAlignIns, jp->dcp - jp->dcq); + ASSERT(!jp->dcq); + } + else { + score += gap_open_score + gap_extend_score * (jp->dcq - jp->dcp); + GapPrelimEditBlockAdd(edit_script, eGapAlignDel, jp->dcq - jp->dcp); + ASSERT(!jp->dcp); + } + + /* update cp and cq */ + cp += jp->dcp; + cq += jp->dcq; + + /* we have already checked that these are matches */ + if (jp->ok == 0 && jp->lng) { + score += match_score * jp->lng; + cp += jp->lng; + cq += jp->lng; + + GapPrelimEditBlockAdd(edit_script, eGapAlignSub, jp->lng); + trace <<= jp->lng; + } + } + + /* if matches all the way to the end of a sequence */ + if (new_matches) { + GapPrelimEditBlockAdd(edit_script, eGapAlignSub, new_matches); + } + + *query_ext_len = cp - query; + *subject_ext_len = cq; + + return score; +} /* JumperExtendRight */ + + +Int4 JumperExtendRightWithTraceback( + const Uint1* query, const Uint1* subject, + int query_length, int subject_length, + Int4 match_score, Int4 mismatch_score, + Int4 gap_open_score, Int4 gap_extend_score, + int max_mismatches, int window, + Int4* query_ext_len, Int4* subject_ext_len, + JumperPrelimEditBlock* edit_script, + Int4* num_identical, + Boolean left_extension, + Int4* ungapped_ext_len, + JUMP* jumper) +{ + const Uint1 *cp, *cp1, *cpmax; + Int4 cq, cq1, cqmax; + int i, n; + JUMP *jp; + int num_mismatches = 0; + int new_matches = 0; + Uint4 trace = 0; + Uint4 trace_mask = (1 << max_mismatches) - 1; + Boolean is_ungapped = TRUE; + + if (!query || ! subject) { + return -1; + } + + cp = query; + cpmax = cp + query_length; + + /* or assume matches up to byte edge */ + cq = 0; + cqmax = subject_length; + + /* skip the first pair as it is compared by the left extension */ + if (left_extension) { + cp++; + cq++; + } + + while (cp < cpmax && cq < cqmax && num_mismatches < max_mismatches) { + + if (*cp == subject[cq]) { + cp++; + cq++; + new_matches++; + continue; + } + + jp = jumper; + jp-- ; + while (jp++) { /* 1, 1, 0, 0 = last always accepted */ + + if (!jp->lng) { + break; + } + + n = 0; + i = jp->ok; + cp1 = cp + jp->dcp; + cq1 = cq + jp->dcq; + while (i--) { + if (cp1 >= cpmax || cq1 >= cqmax + || *cp1++ != subject[cq1]) { + + goto next_jp; + } + cq1++; + } + + n = 0; + i = jp->lng; + cp1 = cp + jp->dcp; + cq1 = cq + jp->dcq; + if (i + cp1 >= cpmax || i + cq1 >= cqmax) { + continue; + } + while (i--) { + if (cp1 >= cpmax || cq1 >= cqmax) { + goto next_jp; + } + if (*cp1++ != subject[cq1]) { + if (++n > jp->ok) { + goto next_jp; + } + } + cq1++; + } + /* current jumper row works */ + break; + +next_jp: + continue; + } + + if (new_matches) { + ASSERT(edit_script->num_ops < edit_script->num_allocated); + JUMPER_EDIT_BLOCK_ADD(edit_script, new_matches); + if (trace) { + if (new_matches < window) { + trace <<= new_matches; + } + else { + trace = 0; + } + } + *num_identical += new_matches; + new_matches = 0; + } + + /* update recent errors */ + if (jp->dcp == jp->dcq) { + if (trace & trace_mask) { + num_mismatches += jp->dcp; + trace <<= jp->dcp; + trace |= (1 << jp->dcp) - 1; + } + else { + num_mismatches = jp->dcp; + trace = (1 << jp->dcp) - 1; + } + for (i = 0;i < jp->dcp;i++) { + ASSERT(edit_script->num_ops < edit_script->num_allocated); + JUMPER_EDIT_BLOCK_ADD(edit_script, JUMPER_MISMATCH); + } + } else if (jp->dcp > jp->dcq) { + for (i = 0;i < jp->dcp - jp->dcq;i++) { + ASSERT(edit_script->num_ops < edit_script->num_allocated); + JUMPER_EDIT_BLOCK_ADD(edit_script, JUMPER_INSERTION); + } + if (jp->dcq) { + /* either jp->dcp r jp->dcq must be zero or jp->dcp == jp->dcq + otherwise number of mismatches must be updated here */ + ASSERT(0); + } + } + else { + for (i = 0;i < jp->dcq - jp->dcp;i++) { + ASSERT(edit_script->num_ops < edit_script->num_allocated); + JUMPER_EDIT_BLOCK_ADD(edit_script, JUMPER_DELETION); + } + if (jp->dcp) { + /* either jp->dcp r jp->dcq must be zero or jp->dcp == jp->dcq + otherwise number of mismatches must be updated here */ + ASSERT(0); + } + } + + /* save the length of the ungapped extension */ + if (is_ungapped && jp->dcp != jp->dcq) { + *ungapped_ext_len = cp - query - 1; + is_ungapped = FALSE; + } + + /* update cp and cq */ + cp += jp->dcp; + cq += jp->dcq; + + /* we have already checked that these are matches */ + if (jp->ok == 0 && jp->lng) { + cp += jp->lng; + cq += jp->lng; + ASSERT(edit_script->num_ops < edit_script->num_allocated); + JUMPER_EDIT_BLOCK_ADD(edit_script, jp->lng); + trace <<= jp->lng; + *num_identical += jp->lng; + /* reset number of mismatches (we assume that error window is + smaller than jp->lng) */ + num_mismatches = 0; + } + } + + /* if matches all the way to the end of a sequence */ + if (new_matches) { + ASSERT(edit_script->num_ops < edit_script->num_allocated); + JUMPER_EDIT_BLOCK_ADD(edit_script, new_matches); + *num_identical += new_matches; + } + + /* find optimal length of the extension */ + s_TrimExtension(edit_script, -mismatch_score, &cp, &cq, num_identical, + TRUE); + + *query_ext_len = cp - query; + *subject_ext_len = cq; + + if (is_ungapped) { + *ungapped_ext_len = *query_ext_len; + } + + /* return extension score */ + return s_ComputeExtensionScore(edit_script, match_score, mismatch_score, + gap_open_score, gap_extend_score); +} /* JumperExtendRightWithTraceback */ + + + +Int4 JumperExtendLeftCompressed(const Uint1* query, const Uint1* subject, + Int4 query_offset, Int4 subject_offset, + Int4 match_score, Int4 mismatch_score, + Int4 gap_open_score, Int4 gap_extend_score, + int max_mismatches, int window, Uint4* table, + Int4* query_ext_len, Int4* subject_ext_len, + Int4* num_identical) +{ + const Uint1 *cp, *cp1, *cpmin, *cpmin4, *cpstop = NULL; + Int4 cq, cq1, cqmin, cqmin4, cqstop = 0; + int i, n; + JUMP *jp; + int num_mismatches = 0; + int new_matches = 0; + Uint4 trace = 0; + Uint4 trace_mask = (1 << max_mismatches) - 1; + Int4 score = 0, best_score = 0; + JUMP* jumper = jumper_default; + + if (!query || ! subject) { + return -1; + } + + cp = query + query_offset; + cpmin = query; + + /* or assume matches up to byte edge */ + cq = subject_offset; + cqmin = 0; + + cpmin4 = query + 4; + cqmin4 = 4; + + + while (cp >= cpmin && cq >= cqmin && num_mismatches < max_mismatches) { + + if ((cq & 3) == 3 && cp >= cpmin4 && cq >= cqmin4) { + if (table[subject[cq / 4]] == *(Uint4*)(cp - 3)) { + cp -= 4; + cq -= 4; + new_matches += 4; + continue; + } + } + + if (*cp == UNPACK_BASE(subject, cq)) { + cp--; + cq--; + new_matches++; + continue; + } + + /* handle ambiguous bases */ + + + jp = jumper; + jp-- ; + while (jp++) { /* 1, 1, 0, 0 = last always accepted */ + + if (!jp->lng) { + break; + } + + n = 0; + i = jp->ok; + cp1 = cp - jp->dcp; + cq1 = cq - jp->dcq; + while (i--) { + if (cp1 < cpmin || cq1 < cqmin + || *cp1-- != UNPACK_BASE(subject, cq1)) { + + goto next_jp; + } + cq1--; + } + + n = 0; + i = jp->lng; + cp1 = cp - jp->dcp; + cq1 = cq - jp->dcq; + if (cp1 - i < cpmin || cq1 - i < cqmin) { + continue; + } + while (i--) { + if (cp1 < cpmin || cq1 < cqmin) { + goto next_jp; + } + if (*cp1-- != UNPACK_BASE(subject, cq1)) { + if (++n > jp->ok) { + goto next_jp; + } + } + cq1--; + } + /* current jumper row works */ + break; + +next_jp: + continue; + } + + if (new_matches) { + if (trace) { + if (new_matches < window) { + trace <<= new_matches; + } + else { + trace = 0; + } + } + *num_identical += new_matches; + score = new_matches * match_score; + new_matches = 0; + } + + /* update recent errors and score */ + if (jp->dcp == jp->dcq) { + score += mismatch_score * jp->dcp; + if (trace & trace_mask) { + num_mismatches += jp->dcp; + trace <<= jp->dcp; + trace |= (1 << jp->dcp) - 1; + } + else { + num_mismatches = jp->dcp; + trace = (1 << jp->dcp) - 1; + } + } + /* note that we are not penalizing gaps */ + + /* update cp and cq */ + cp -= jp->dcp; + cq -= jp->dcq; + + /* we have already checked that these are matches */ + if (!jp->ok && jp->lng) { + cp -= jp->lng; + cq -= jp->lng; + trace <<= jp->lng; + *num_identical += jp->lng; + score += jp->lng * match_score; + } + + /* update optimal alignment extent */ + if (score >= best_score) { + cpstop = cp; + cqstop = cq; + best_score = score; + } + } + + /* if matches all the way to the end of a sequence */ + if (new_matches) { + *num_identical += new_matches; + score += new_matches * match_score; + if (score >= best_score) { + cpstop = cp; + cqstop = cq; + } + } + + *query_ext_len = query + query_offset - cpstop; + *subject_ext_len = subject_offset - cqstop; + + return best_score; +} /* JumperExtendLeftCompressed */ + + +Int4 JumperExtendLeftCompressedWithTraceback( + const Uint1* query, const Uint1* subject, + Int4 query_offset, Int4 subject_offset, + Int4 match_score, Int4 mismatch_score, + Int4 gap_open_score, Int4 gap_extend_score, + int max_mismatches, int window, Uint4* table, + Int4* query_ext_len, Int4* subject_ext_len, + JumperPrelimEditBlock* edit_script, + Int4* num_identical, + JUMP* jumper) +{ + const Uint1 *cp, *cp1, *cpmin, *cpmin4; + Int4 cq, cq1, cqmin, cqmin4; + int i, n; + JUMP *jp; + int num_mismatches = 0; + int new_matches = 0; + Uint4 trace = 0; + Uint4 trace_mask = (1 << max_mismatches) - 1; + + if (!query || ! subject) { + return -1; + } + + cp = query + query_offset; + cpmin = query; + + /* or assume matches up to byte edge */ + cq = subject_offset; + cqmin = 0; + + cpmin4 = query + 4; + cqmin4 = 4; + + + while (cp >= cpmin && cq >= cqmin && num_mismatches < max_mismatches) { + + if ((cq & 3) == 3 && cp >= cpmin4 && cq >= cqmin4) { + if (table[subject[cq / 4]] == *(Uint4*)(cp - 3)) { + cp -= 4; + cq -= 4; + new_matches += 4; + continue; + } + } + + if (*cp == UNPACK_BASE(subject, cq)) { + cp--; + cq--; + new_matches++; + continue; + } + + /* handle ambiguous bases */ + + + jp = jumper; + jp-- ; + while (jp++) { /* 1, 1, 0, 0 = last always accepted */ + + if (!jp->lng) { + break; + } + + n = 0; + i = jp->ok; + cp1 = cp - jp->dcp; + cq1 = cq - jp->dcq; + while (i--) { + if (cp1 < cpmin || cq1 < cqmin + || *cp1-- != UNPACK_BASE(subject, cq1)) { + + goto next_jp; + } + cq1--; + } + + n = 0; + i = jp->lng; + cp1 = cp - jp->dcp; + cq1 = cq - jp->dcq; + if (cp1 - i < cpmin || cq1 - i < cqmin) { + continue; + } + while (i--) { + if (cp1 < cpmin || cq1 < cqmin) { + goto next_jp; + } + if (*cp1-- != UNPACK_BASE(subject, cq1)) { + if (++n > jp->ok) { + goto next_jp; + } + } + cq1--; + } + /* current jumper row works */ + break; + +next_jp: + continue; + } + + if (new_matches) { + ASSERT(edit_script->num_ops < edit_script->num_allocated); + JUMPER_EDIT_BLOCK_ADD(edit_script, new_matches); + if (trace) { + if (new_matches < window) { + trace <<= new_matches; + } + else { + trace = 0; + } + } + *num_identical += new_matches; + new_matches = 0; + } + + /* update recent errors */ + if (jp->dcp == jp->dcq) { + if (trace & trace_mask) { + num_mismatches += jp->dcp; + trace <<= jp->dcp; + trace |= (1 << jp->dcp) - 1; + } + else { + num_mismatches = jp->dcp; + trace = (1 << jp->dcp) - 1; + } + for (i = 0;i < jp->dcp;i++) { + ASSERT(edit_script->num_ops < edit_script->num_allocated); + JUMPER_EDIT_BLOCK_ADD(edit_script, JUMPER_MISMATCH); + } + } else if (jp->dcp > jp->dcq) { + for (i = 0;i < jp->dcp - jp->dcq;i++) { + ASSERT(edit_script->num_ops < edit_script->num_allocated); + JUMPER_EDIT_BLOCK_ADD(edit_script, JUMPER_INSERTION); + } + if (jp->dcq) { + /* either jp->dcp r jp->dcq must be zero or jp->dcp == jp->dcq + otherwise number of mismatches must be updated here */ + ASSERT(0); + } + } + else { + for (i = 0;i < jp->dcq - jp->dcp;i++) { + ASSERT(edit_script->num_ops < edit_script->num_allocated); + JUMPER_EDIT_BLOCK_ADD(edit_script, JUMPER_DELETION); + } + if (jp->dcp) { + /* either jp->dcp r jp->dcq must be zero or jp->dcp == jp->dcq + otherwise number of mismatches must be updated here */ + ASSERT(0); + } + } + + /* update cp and cq */ + cp -= jp->dcp; + cq -= jp->dcq; + + /* we have already checked that these are matches */ + if (!jp->ok && jp->lng) { + cp -= jp->lng; + cq -= jp->lng; + ASSERT(edit_script->num_ops < edit_script->num_allocated); + JUMPER_EDIT_BLOCK_ADD(edit_script, jp->lng); + trace <<= jp->lng; + *num_identical += jp->lng; + /* reset number of mismatches (we assume that error window is + smaller than jp->lng) */ + num_mismatches = 0; + } + } + + /* if matches all the way to the end of a sequence */ + if (new_matches) { + ASSERT(edit_script->num_ops < edit_script->num_allocated); + JUMPER_EDIT_BLOCK_ADD(edit_script, new_matches); + *num_identical += new_matches; + } + + /* find optimal extension length */ + s_TrimExtension(edit_script, -mismatch_score, &cp, &cq, num_identical, + FALSE); + + *query_ext_len = query + query_offset - cp; + *subject_ext_len = subject_offset - cq; + + /* return extension score */ + return s_ComputeExtensionScore(edit_script, match_score, mismatch_score, + gap_open_score, gap_extend_score); +} /* JumperExtendLeftCompressedWithTraceback */ + + +Int4 JumperExtendLeftCompressedWithTracebackOptimal( + const Uint1* query, const Uint1* subject, + Int4 query_offset, Int4 subject_offset, + Int4 match_score, Int4 mismatch_score, + Int4 gap_open_score, Int4 gap_extend_score, + int max_mismatches, int window, Uint4* table, + Int4* query_ext_len, Int4* subject_ext_len, + JumperPrelimEditBlock* edit_script, + Int4* best_num_identical) +{ + const Uint1 *cp, *cp1, *cpmin, *cpmin4, *cpstop = NULL; + Int4 cq, cq1, cqmin, cqmin4, cqstop = 0; + int i, n; + JUMP *jp; + int num_mismatches = 0; + int new_matches = 0; + Uint4 trace = 0; + Uint4 trace_mask = (1 << max_mismatches) - 1; + Int4 score = 0, best_score = 0; + Int4 num_ops = 0, num_identical = *best_num_identical; + /* 0 - no gap, JUMPER_INSERTION, JUMPER_DELETION for open insertion or + deletion */ + Int4 last_gap_open = 0; + JUMP* jumper = jumper_default; + + if (!query || ! subject) { + return -1; + } + + cp = query + query_offset; + cpmin = query; + + /* or assume matches up to byte edge */ + cq = subject_offset; + cqmin = 0; + + cpmin4 = query + 4; + cqmin4 = 4; + + + while (cp >= cpmin && cq >= cqmin && num_mismatches < max_mismatches) { + + if ((cq & 3) == 3 && cp >= cpmin4 && cq >= cqmin4) { + if (table[subject[cq / 4]] == *(Uint4*)(cp - 3)) { + cp -= 4; + cq -= 4; + new_matches += 4; + continue; + } + } + + if (*cp == UNPACK_BASE(subject, cq)) { + cp--; + cq--; + new_matches++; + continue; + } + + /* handle ambiguous bases */ + + + jp = jumper; + jp-- ; + while (jp++) { /* 1, 1, 0, 0 = last always accepted */ + + if (!jp->lng) { + break; + } + + n = 0; + i = jp->ok; + cp1 = cp - jp->dcp; + cq1 = cq - jp->dcq; + while (i--) { + if (cp1 < cpmin || cq1 < cqmin + || *cp1-- != UNPACK_BASE(subject, cq1)) { + + goto next_jp; + } + cq1--; + } + + n = 0; + i = jp->lng; + cp1 = cp - jp->dcp; + cq1 = cq - jp->dcq; + if (cp1 - i < cpmin || cq1 - i < cqmin) { + continue; + } + while (i--) { + if (cp1 < cpmin || cq1 < cqmin) { + goto next_jp; + } + if (*cp1-- != UNPACK_BASE(subject, cq1)) { + if (++n > jp->ok) { + goto next_jp; + } + } + cq1--; + } + /* current jumper row works */ + break; + +next_jp: + continue; + } + + if (new_matches) { + ASSERT(edit_script->num_ops < edit_script->num_allocated); + JUMPER_EDIT_BLOCK_ADD(edit_script, new_matches); + if (trace) { + if (new_matches < window) { + trace <<= new_matches; + } + else { + trace = 0; + } + } + num_identical += new_matches; + score += new_matches * match_score; + new_matches = 0; + last_gap_open = 0; + } + + /* update optimal alignment extent */ + if (score >= best_score) { + cpstop = cp; + cqstop = cq; + best_score = score; + num_ops = edit_script->num_ops; + *best_num_identical = num_identical; + } + + /* update recent errors */ + if (jp->dcp == jp->dcq) { + score += jp->dcp * mismatch_score; + if (trace & trace_mask) { + num_mismatches += jp->dcp; + trace <<= jp->dcp; + trace |= (1 << jp->dcp) - 1; + } + else { + num_mismatches = jp->dcp; + trace = (1 << jp->dcp) - 1; + } + for (i = 0;i < jp->dcp;i++) { + ASSERT(edit_script->num_ops < edit_script->num_allocated); + JUMPER_EDIT_BLOCK_ADD(edit_script, JUMPER_MISMATCH); + } + } else if (jp->dcp > jp->dcq) { + for (i = 0;i < jp->dcp - jp->dcq;i++) { + ASSERT(edit_script->num_ops < edit_script->num_allocated); + JUMPER_EDIT_BLOCK_ADD(edit_script, JUMPER_INSERTION); + score += gap_extend_score; + } + if (last_gap_open != JUMPER_INSERTION) { + score += gap_open_score; + } + last_gap_open = JUMPER_INSERTION; + if (jp->dcq) { + /* either jp->dcp r jp->dcq must be zero or jp->dcp == jp->dcq + otherwise number of mismatches must be updated here */ + ASSERT(0); + } + } + else { + for (i = 0;i < jp->dcq - jp->dcp;i++) { + ASSERT(edit_script->num_ops < edit_script->num_allocated); + JUMPER_EDIT_BLOCK_ADD(edit_script, JUMPER_DELETION); + score += gap_extend_score; + } + if (last_gap_open != JUMPER_DELETION) { + score += gap_open_score; + } + last_gap_open = JUMPER_DELETION; + if (jp->dcp) { + /* either jp->dcp r jp->dcq must be zero or jp->dcp == jp->dcq + otherwise number of mismatches must be updated here */ + ASSERT(0); + } + } + + /* update cp and cq */ + cp -= jp->dcp; + cq -= jp->dcq; + + /* we have already checked that these are matches */ + if (!jp->ok && jp->lng) { + cp -= jp->lng; + cq -= jp->lng; + ASSERT(edit_script->num_ops < edit_script->num_allocated); + JUMPER_EDIT_BLOCK_ADD(edit_script, jp->lng); + trace <<= jp->lng; + num_identical += jp->lng; + score += jp->lng * match_score; + last_gap_open = 0; + } + + /* update optimal alignment extent */ + if (score >= best_score) { + cpstop = cp; + cqstop = cq; + best_score = score; + num_ops = edit_script->num_ops; + *best_num_identical = num_identical; + } + } + + /* if matches all the way to the end of a sequence */ + if (new_matches) { + ASSERT(edit_script->num_ops < edit_script->num_allocated); + JUMPER_EDIT_BLOCK_ADD(edit_script, new_matches); + num_identical += new_matches; + score += new_matches * match_score; + } + + /* update optimal alignment extent */ + if (score >= best_score) { + cpstop = cp; + cqstop = cq; + best_score = score; + num_ops = edit_script->num_ops; + *best_num_identical = num_identical; + } + + *query_ext_len = query + query_offset - cpstop; + *subject_ext_len = subject_offset - cqstop; + edit_script->num_ops = num_ops; + + /* return extension score */ + return best_score; +} /* JumperExtendLeftCompressedWithTracebackOptimal */ + + +Int4 JumperExtendLeft(const Uint1* query, const Uint1* subject, + Int4 query_offset, Int4 subject_offset, + Int4 match_score, Int4 mismatch_score, + Int4 gap_open_score, Int4 gap_extend_score, + int max_mismatches, int window, + int* query_ext_len, int* subject_ext_len, + GapPrelimEditBlock* edit_script) +{ + const Uint1 *cp, *cp1, *cpmin; + Int4 cq, cq1, cqmin; + int i, n; + JUMP *jp; + int score = 0, num_mismatches = 0; + int new_matches = 0; + Uint4 trace = 0; + Uint4 trace_mask = (1 << max_mismatches) - 1; + JUMP* jumper = jumper_default; + + if (!query || ! subject || !edit_script) { + return -1; + } + + cp = query + query_offset; + cpmin = query; + + /* or assume matches up to byte edge */ + cq = subject_offset; + cqmin = 0; + + while (cp >= cpmin && cq >= cqmin && num_mismatches < max_mismatches) { + + if (*cp == subject[cq]) { + score += match_score; + cp--; + cq--; + new_matches++; + continue; + } + + /* handle ambiguous bases */ + + + jp = jumper; + jp-- ; + while (jp++) { /* 1, 1, 0, 0 = last always accepted */ + + if (!jp->lng) { + break; + } + + n = 0; + i = jp->ok; + cp1 = cp - jp->dcp; + cq1 = cq - jp->dcq; + while (i--) { + if (cp1 < cpmin || cq1 < cqmin + || *cp1-- != subject[cq1]) { + + goto next_jp; + } + cq1--; + } + + n = 0; + i = jp->lng; + cp1 = cp - jp->dcp; + cq1 = cq - jp->dcq; + if (cp1 - i < cpmin || cq1 - i < cqmin) { + continue; + } + while (i--) { + if (cp1 < cpmin || cq1 < cqmin) { + goto next_jp; + } + if (*cp1-- != subject[cq1]) { + if (++n > jp->ok) { + goto next_jp; + } + } + cq1--; + } + /* current jumper row works */ + break; + +next_jp: + continue; + } + + if (new_matches) { + GapPrelimEditBlockAdd(edit_script, eGapAlignSub, new_matches); + if (trace) { + if (new_matches < window) { + trace <<= new_matches; + } + else { + trace = 0; + } + } + new_matches = 0; + } + +/* another stop condition, ensures a positive score *--/ + if (!jp->lng && num_mismatches >= score + mismatch_score) { + break; + } +*/ + + /* update score */ + if (jp->dcp == jp->dcq) { + score += mismatch_score * jp->dcp; + if (trace & trace_mask) { + num_mismatches += jp->dcp; + trace <<= jp->dcp; + trace |= (1 << jp->dcp) - 1; + } + else { + num_mismatches = jp->dcp; + trace = (1 << jp->dcp) - 1; + } + GapPrelimEditBlockAdd(edit_script, eGapAlignSub, jp->dcp); + } else if (jp->dcp > jp->dcq) { + score += gap_open_score + gap_extend_score * (jp->dcp - jp->dcq); + GapPrelimEditBlockAdd(edit_script, eGapAlignIns, jp->dcp - jp->dcq); + ASSERT(!jp->dcq); + } + else { + score += gap_open_score + gap_extend_score * (jp->dcq - jp->dcp); + GapPrelimEditBlockAdd(edit_script, eGapAlignDel, jp->dcq - jp->dcp); + ASSERT(!jp->dcp); + } + + /* update cp and cq */ + cp -= jp->dcp; + cq -= jp->dcq; + + /* we have already checked that these are matches */ + if (!jp->ok && jp->lng) { + score += match_score * jp->lng; + cp -= jp->lng; + cq -= jp->lng; + + GapPrelimEditBlockAdd(edit_script, eGapAlignSub, jp->lng); + trace <<= jp->lng; + } + } + + /* if matches all the way to the end of a sequence */ + if (new_matches) { + GapPrelimEditBlockAdd(edit_script, eGapAlignSub, new_matches); + } + + *query_ext_len = query + query_offset - cp; + *subject_ext_len = subject_offset - cq; + + return score; +} /* JumperExtendLeft */ + + +int JumperGappedAlignmentCompressedWithTraceback(const Uint1* query, + const Uint1* subject, + Int4 query_length, Int4 subject_length, + Int4 query_start, Int4 subject_start, + BlastGapAlignStruct* gap_align, + const BlastScoringParameters* score_params, + Int4* num_identical, + Int4* right_ungapped_ext_len) +{ + Int4 score_left = 0, score_right = 0; + Int4 q_ext_len, s_ext_len; + Int4 q_length, s_length; + Int4 offset_adjustment; + Boolean left_ext_done = FALSE; + const Uint1 kBaseN = 14; + Int4 i; + + + ASSERT(gap_align->jumper); + + *num_identical = 0; + + JumperPrelimEditBlock** rev_prelim_block = + &gap_align->jumper->left_prelim_block; + + JumperPrelimEditBlock** fwd_prelim_block = + &gap_align->jumper->right_prelim_block; + + /* reallocate gapped preliminary edit blocks if necessary; + edit scripts should not be longer than 2 times the length of the shorter + sequence, so memory reallocation will not be necessary */ + if (!*rev_prelim_block || !*fwd_prelim_block || + (*rev_prelim_block)->num_allocated < + 2 * MIN(query_length, subject_length)) { + + JumperPrelimEditBlockFree(*rev_prelim_block); + *rev_prelim_block = + JumperPrelimEditBlockNew(2 * MIN(query_length, subject_length)); + + JumperPrelimEditBlockFree(*fwd_prelim_block); + *fwd_prelim_block = + JumperPrelimEditBlockNew(2 * MIN(query_length, subject_length)); + } + s_ResetJumperPrelimEditBlocks(*rev_prelim_block, *fwd_prelim_block); + + /* this is currently needed for right extension */ + offset_adjustment = COMPRESSION_RATIO - (subject_start % COMPRESSION_RATIO); + + q_length = query_start + offset_adjustment; + s_length = subject_start + offset_adjustment; + + + if (query_start > 0 && subject_start > 0) { + + score_left = JumperExtendLeftCompressedWithTracebackOptimal( + query, subject, + q_length, s_length, + score_params->reward, + score_params->penalty, + -score_params->gap_open, + -score_params->gap_extend, + gap_align->max_mismatches, + gap_align->mismatch_window, + gap_align->jumper->table, + &q_ext_len, &s_ext_len, + *rev_prelim_block, + num_identical); + + + gap_align->query_start = q_length - q_ext_len + 1; + gap_align->subject_start = s_length - s_ext_len + 1; + left_ext_done = TRUE; + ASSERT(gap_align->query_start >= 0); + ASSERT(gap_align->subject_start >= 0); + } + else { + gap_align->query_start = query_start; + gap_align->subject_start = subject_start; + } + + if (query_start < query_length - 1 && subject_start < subject_length - 1) { + + score_right = JumperExtendRightCompressedWithTracebackOptimal( + query + q_length, + subject + (s_length + 3) / 4, + query_length - q_length, + subject_length - s_length, + score_params->reward, + score_params->penalty, + -score_params->gap_open, + -score_params->gap_extend, + gap_align->max_mismatches, + gap_align->mismatch_window, + gap_align->jumper->table, + &q_ext_len, &s_ext_len, + *fwd_prelim_block, + num_identical, + left_ext_done, + right_ungapped_ext_len); + + gap_align->query_stop = q_length + q_ext_len; + gap_align->subject_stop = s_length + s_ext_len; + } + else { + gap_align->query_stop = query_start; + gap_align->subject_stop = subject_start; + } + + gap_align->score = score_left + score_right; + + if (offset_adjustment && !left_ext_done) { + ASSERT((*rev_prelim_block)->num_ops < + (*rev_prelim_block)->num_allocated); + JUMPER_EDIT_BLOCK_ADD(*rev_prelim_block, offset_adjustment); + + *num_identical += offset_adjustment; + gap_align->score += offset_adjustment * score_params->reward; + } + if (offset_adjustment && *right_ungapped_ext_len) { + *right_ungapped_ext_len += offset_adjustment; + } + + /* Remove mismatch penalty for Ns. We assume that there are no gaps + corresponfding to Ns (gaps may happen, but are unlikely). This to + ensure that an alignment spanning the whole read containing a few Ns + has a larger score than one covering a part. */ + for (i = gap_align->query_start;i < gap_align->query_stop;i++) { + if (query[i] == kBaseN) { + gap_align->score -= score_params->penalty; + } + } + + return 0; +} + + +Boolean JumperGoodAlign(const BlastGapAlignStruct* gap_align, + const BlastHitSavingParameters* hit_params, + Int4 num_identical, + BlastContextInfo* context_info) +{ + Int4 score = gap_align->score; + + /* first check general score and coverage thresholds */ + if (score < hit_params->options->cutoff_score) { + return FALSE; + } + + Int4 align_len = MAX(gap_align->query_stop - gap_align->query_start, + gap_align->subject_stop - gap_align->subject_start); + + if (100.0 * (double)num_identical / (double)align_len + < hit_params->options->percent_identity) { + + return FALSE; + } + + return TRUE; +} + + + +JumperEditsBlock* JumperEditsBlockFree(JumperEditsBlock* block) +{ + if (!block) { + return NULL; + } + + if (block->edits) { + sfree(block->edits); + } + sfree(block); + + return NULL; +} + +JumperEditsBlock* JumperEditsBlockNew(Int4 num) +{ + JumperEditsBlock* retval = + (JumperEditsBlock*)calloc(1, sizeof(JumperEditsBlock)); + + if (!retval) { + return NULL; + } + + retval->edits = (JumperEdit*)calloc(num, sizeof(JumperEdit)); + if (!retval->edits) { + JumperEditsBlockFree(retval); + return NULL; + } + + retval->num_edits = 0; + return retval; +} + +JumperEditsBlock* JumperEditsBlockDup(const JumperEditsBlock* block) +{ + JumperEditsBlock* retval = NULL; + + if (!block) { + return NULL; + } + + retval = JumperEditsBlockNew(block->num_edits); + if (retval) { + memcpy(retval->edits, block->edits, + block->num_edits * sizeof(JumperEdit)); + retval->num_edits = block->num_edits; + } + + return retval; +} + +JumperEditsBlock* JumperFindEdits(const Uint1* query, const Uint1* subject, + BlastGapAlignStruct* gap_align) +{ + const Uint1 kGap = 15; + Int4 q_pos = gap_align->query_start; + Int4 s_pos = gap_align->subject_start; + + JumperPrelimEditBlock* left_ext = gap_align->jumper->left_prelim_block; + JumperPrelimEditBlock* right_ext = gap_align->jumper->right_prelim_block; + + JumperEditsBlock* retval = NULL; + int len = left_ext->num_ops + right_ext->num_ops; + int i, k; + + retval = JumperEditsBlockNew(len); + if (!retval) { + return NULL; + } + k = 0; + for (i=left_ext->num_ops - 1;i >= 0;i--) { + + ASSERT(k < len); + + JumperEdit* edit = &retval->edits[k]; + JumperOpType* edit_op = &left_ext->edit_ops[i]; + switch(*edit_op) { + case JUMPER_MISMATCH: + edit->query_pos = q_pos; + edit->query_base = query[q_pos]; + edit->subject_base = UNPACK_BASE(subject, s_pos); + q_pos++; + s_pos++; + k++; + break; + + case JUMPER_DELETION: + edit->query_pos = q_pos; + edit->query_base = kGap; + edit->subject_base = UNPACK_BASE(subject, s_pos); + s_pos++; + k++; + break; + + case JUMPER_INSERTION: + edit->query_pos = q_pos; + edit->query_base = query[q_pos]; + edit->subject_base = kGap; + q_pos++; + k++; + break; + + default: + q_pos += *edit_op; + s_pos += *edit_op; + } + } + + for (i=0;i < right_ext->num_ops;i++) { + + ASSERT(k < len); + + JumperEdit* edit = &retval->edits[k]; + JumperOpType* edit_op = &right_ext->edit_ops[i]; + switch(*edit_op) { + case JUMPER_MISMATCH: + edit->query_pos = q_pos; + edit->query_base = query[q_pos]; + edit->subject_base = UNPACK_BASE(subject, s_pos); + q_pos++; + s_pos++; + k++; + break; + + case JUMPER_DELETION: + edit->query_pos = q_pos; + edit->query_base = kGap; + edit->subject_base = UNPACK_BASE(subject, s_pos); + s_pos++; + k++; + break; + + case JUMPER_INSERTION: + edit->query_pos = q_pos; + edit->query_base = query[q_pos]; + edit->subject_base = kGap; + q_pos++; + k++; + break; + + default: + q_pos += *edit_op; + s_pos += *edit_op; + } + } + + retval->num_edits = k; + + ASSERT(k <= len); + ASSERT(q_pos == gap_align->query_stop); + ASSERT(s_pos == gap_align->subject_stop); + + return retval; +} + + +JumperEditsBlock* JumperEditsBlockCombine(JumperEditsBlock** block_ptr, + JumperEditsBlock** append_ptr) +{ + Int4 i; + JumperEditsBlock* block = NULL; + JumperEditsBlock* append = NULL; + + if (!block_ptr || !*block_ptr || !append_ptr) { + return NULL; + } + + block = *block_ptr; + append = *append_ptr; + + if (!append || append->num_edits == 0) { + *append_ptr = JumperEditsBlockFree(*append_ptr); + return block; + } + + block->edits = realloc(block->edits, + (block->num_edits + append->num_edits) * + sizeof(JumperEdit)); + + if (!block->edits) { + return NULL; + } + for (i = 0;i < append->num_edits;i++) { + block->edits[block->num_edits++] = append->edits[i]; + } + + *append_ptr = JumperEditsBlockFree(*append_ptr); + + return block; +} + +GapEditScript* GapEditScriptCombine(GapEditScript** edit_script_ptr, + GapEditScript** append_ptr) +{ + Int4 i = 0; + GapEditScript* edit_script = NULL; + GapEditScript* append = NULL; + + if (!edit_script_ptr || !*edit_script_ptr || !append_ptr) { + return NULL; + } + + edit_script = *edit_script_ptr; + append = *append_ptr; + + if (!append || append->size == 0) { + *append_ptr = GapEditScriptDelete(*append_ptr); + return edit_script; + } + + edit_script->op_type = realloc(edit_script->op_type, + (edit_script->size + append->size) * + sizeof(EGapAlignOpType)); + if (!edit_script->op_type) { + return NULL; + } + edit_script->num = realloc(edit_script->num, + (edit_script->size + append->size) * + sizeof(Int4)); + if (!edit_script->num) { + return NULL; + } + + if (edit_script->op_type[edit_script->size - 1] == append->op_type[0]) { + edit_script->num[edit_script->size - 1] += append->num[0]; + i = 1; + } + for (;i < append->size;i++) { + edit_script->op_type[edit_script->size] = append->op_type[i]; + edit_script->num[edit_script->size] = append->num[i]; + edit_script->size++; + } + + *append_ptr = GapEditScriptDelete(*append_ptr); + + return edit_script; +} + + +#define NUM_SIGNALS 8 + +/* Record subject bases pre and post alignment in HSP as possible splice + signals and set a flag for recognized signals */ +int JumperFindSpliceSignals(BlastHSP* hsp, Int4 query_len, + const Uint1* subject, Int4 subject_len) +{ + Uint1 signals[NUM_SIGNALS] = {1, /* AC */ + 2, /* AG */ + 4, /* CA */ + 7, /* CT */ + 8, /* GA */ + 11, /* GT */ + 13, /* TC */ + 14 /* TG */ }; + + + if (!hsp || !subject) { + return -1; + } + + if (hsp->query.offset == 0 || hsp->subject.offset < 2) { + hsp->map_info->left_edge = MAPPER_EXON; + } + else { + int k; + hsp->map_info->left_edge = + (UNPACK_BASE(subject, hsp->subject.offset - 2) << 2) | + UNPACK_BASE(subject, hsp->subject.offset - 1); + + for (k = 0;k < NUM_SIGNALS;k++) { + if (hsp->map_info->left_edge == signals[k]) { + hsp->map_info->left_edge |= MAPPER_SPLICE_SIGNAL; + break; + } + } + } + + if (hsp->query.end == query_len || hsp->subject.end == subject_len) { + hsp->map_info->right_edge = MAPPER_EXON; + } + else { + int k; + hsp->map_info->right_edge = + (UNPACK_BASE(subject, hsp->subject.end) << 2) | + UNPACK_BASE(subject, hsp->subject.end + 1); + + for (k = 0;k < NUM_SIGNALS;k++) { + if (hsp->map_info->right_edge == signals[k]) { + hsp->map_info->right_edge |= MAPPER_SPLICE_SIGNAL; + break; + } + } + } + + return 0; +} + + +#define MAX_SUBJECT_OVERHANG 20 + +SequenceOverhangs* SequenceOverhangsFree(SequenceOverhangs* overhangs) +{ + if (!overhangs) { + return NULL; + } + + if (overhangs->left) { + sfree(overhangs->left); + } + + if (overhangs->right) { + sfree(overhangs->right); + } + + sfree(overhangs); + return NULL; +} + + +static Int4 s_SaveSubjectOverhangs(BlastHSP* hsp, Uint1* subject, + Int4 query_len) +{ + SequenceOverhangs* overhangs = NULL; + const Int4 kMinOverhangLength = 0; + + if (hsp->query.offset < kMinOverhangLength && + query_len - hsp->query.end < kMinOverhangLength) { + + return 0; + } + + overhangs = calloc(1, sizeof(SequenceOverhangs)); + if (!overhangs) { + return -1; + } + + if (hsp->query.offset >= kMinOverhangLength) { + Int4 i; + /* at least two subject bases are needed for the search for splice + signals */ + Int4 len = MIN(MAX(hsp->query.offset, 2), MAX_SUBJECT_OVERHANG); + Uint1* overhang = calloc(len, sizeof(Uint1)); + if (!overhang) { + SequenceOverhangsFree(overhangs); + return -1; + } + if (hsp->subject.offset < len) { + len = hsp->subject.offset; + } + for (i = 0;i < len; i++) { + overhang[i] = UNPACK_BASE(subject, hsp->subject.offset - len + i); + } + overhangs->left = overhang; + overhangs->left_len = len; + } + + if (hsp->query.end <= query_len - kMinOverhangLength) { + Int4 i; + Int4 len = + MIN(MAX(query_len - hsp->query.end + 1, 2), MAX_SUBJECT_OVERHANG); + Uint1* overhang = calloc(len, sizeof(Uint1)); + if (!overhang) { + SequenceOverhangsFree(overhangs); + return -1; + } + for (i = 0;i < len;i++) { + /* hsp->subject.end is an open limit */ + overhang[i] = UNPACK_BASE(subject, hsp->subject.end + i); + } + overhangs->right = overhang; + overhangs->right_len = len; + } + + hsp->map_info->subject_overhangs = overhangs; + + return 0; +} + + +static int s_CompareOffsetPairsByDiagQuery(const void* a, const void* b) +{ + BlastOffsetPair* first = (BlastOffsetPair*)a; + BlastOffsetPair* second = (BlastOffsetPair*)b; + + Int4 first_diag = first->qs_offsets.s_off - first->qs_offsets.q_off; + Int4 second_diag = second->qs_offsets.s_off - second->qs_offsets.q_off; + + if (first_diag < second_diag) { + return -1; + } + if (first_diag > second_diag) { + return 1; + } + + if (first->qs_offsets.q_off < second->qs_offsets.q_off) { + return -1; + } + if (first->qs_offsets.q_off > second->qs_offsets.q_off) { + return 1; + } + + if (first->qs_offsets.s_off < second->qs_offsets.s_off) { + return -1; + } + if (first->qs_offsets.s_off > second->qs_offsets.s_off) { + return 1; + } + + return 0; +} + + +/* Create an HSP from a word hit */ +static BlastHSP* s_CreateHSPForWordHit(Int4 q_offset, Int4 s_offset, + Int4 length, Int4 context, + const Uint1* query, + const BlastQueryInfo* query_info, + const BLAST_SequenceBlk* subject, + Int4 query_len) +{ + BlastHSP* retval = NULL; + GapEditScript* edit_script = NULL; + Int2 status; + Int4 i; + Int4 num_Ns = 0; + + edit_script = GapEditScriptNew(1); + if (!edit_script) { + return NULL; + } + + edit_script->num[0] = length; + edit_script->op_type[0] = eGapAlignSub; + + + status = Blast_HSPInit(q_offset, + q_offset + length, + s_offset, + s_offset + length, + q_offset, s_offset, + context, + query_info->contexts[context].frame, + subject->frame, + length, + &edit_script, + &retval); + if (status) { + if (retval) { + Blast_HSPFree(retval); + } + else { + GapEditScriptDelete(edit_script); + } + return NULL; + } + + retval->map_info = BlastHSPMappingInfoNew(); + if (!retval->map_info) { + Blast_HSPFree(retval); + return NULL; + } + + /* ambiguous bases in query are allowed for extending small word matches, + so there can be Ns within the word hit */ + for (i = 0;i < length;i++) { + if ((query[q_offset + i] & 0xfc) != 0) { + num_Ns++; + } + } + + retval->num_ident = length - num_Ns; + retval->evalue = 0.0; + retval->map_info->edits = JumperEditsBlockNew(num_Ns); + if (!retval->map_info->edits) { + Blast_HSPFree(retval); + return NULL; + } + + /* add edits for ambiguous bases */ + for (i = 0;i < length;i++) { + if ((query[q_offset + i] & 0xfc) != 0) { + JumperEdit* edit = retval->map_info->edits->edits + + retval->map_info->edits->num_edits; + + ASSERT(retval->map_info->edits->num_edits < num_Ns); + edit->query_pos = q_offset + i; + edit->query_base = query[q_offset + i]; + edit->subject_base = UNPACK_BASE(subject->sequence, s_offset + i); + retval->map_info->edits->num_edits++; + } + } + + /* FIXME: This is currently needed because these splice sites are used + in finding splice signals for overlapping HSPs */ + JumperFindSpliceSignals(retval, query_len, subject->sequence, + subject->length); + + s_SaveSubjectOverhangs(retval, subject->sequence, query_len); + + return retval; +} + +/* for mapping this may only work if we hash genome and scan reads */ +Int4 +BlastNaExtendJumper(BlastOffsetPair* offset_pairs, Int4 num_hits, + const BlastInitialWordParameters* word_params, + const BlastScoringParameters* score_params, + const BlastHitSavingParameters* hit_params, + LookupTableWrap* lookup_wrap, + BLAST_SequenceBlk* query, + BLAST_SequenceBlk* subject, + BlastQueryInfo* query_info, + BlastGapAlignStruct* gap_align, + BlastHSPList* hsp_list, + Uint4 s_range, + SubjectIndex* s_index) +{ + Int4 index = 0; + Int4 hits_extended = 0; + Int4 word_length, lut_word_length, ext_to; + Int4 context; + int status; + Int4 num_identical = 0; + /* word matches until this query position will be skipped */ + Int4 skip_until = 0; + Int4 last_diag = 0; + + if (lookup_wrap->lut_type == eMBLookupTable) { + BlastMBLookupTable *lut = (BlastMBLookupTable *) lookup_wrap->lut; + word_length = lut->word_length; + lut_word_length = lut->lut_word_length; + } + else { + BlastNaLookupTable *lut = (BlastNaLookupTable *) lookup_wrap->lut; + word_length = lut->word_length; + lut_word_length = lut->lut_word_length; + } + ext_to = word_length - lut_word_length; + + /* We trust that the bases of the hit itself are exact matches, + and look only for exact matches before and after the hit. + + Most of the time, the lookup table width is close to the word size + so only a few bases need examining. Also, most of the time (for + random sequences) extensions will fail almost immediately (the + first base examined will not match about 3/4 of the time). Thus it + is critical to reduce as much as possible all work that is not the + actual examination of sequence data */ + + /* Sort word hits by diagnal, query, and subject position */ + qsort(offset_pairs, num_hits, sizeof(BlastOffsetPair), + s_CompareOffsetPairsByDiagQuery); + + for (; index < num_hits; ++index) { + Int4 s_offset = offset_pairs[index].qs_offsets.s_off; + Int4 q_offset = offset_pairs[index].qs_offsets.q_off; + Int4 query_start; + /* FIXME: this may need to be Int8 for 10M queries or long reads */ + Int4 diag = s_offset - q_offset; + + /* skip word hits from already explored part of the diagonal (word + hits must be sorted by diagonal and query position) */ + if (diag == last_diag && q_offset < skip_until) { + continue; + } + + /* begin with the left extension; the initialization is slightly + faster. Point to the first base of the lookup table hit and + work backwards */ + + Int4 ext_left = 0; + Int4 s_off = s_offset; + Uint1 *q = query->sequence + q_offset; + Uint1 *s = subject->sequence + s_off / COMPRESSION_RATIO; + + for (; ext_left < MIN(ext_to, s_offset); ++ext_left) { + s_off--; + q--; + if (s_off % COMPRESSION_RATIO == 3) + s--; + if (((Uint1) (*s << (2 * (s_off % COMPRESSION_RATIO))) >> 6) + != *q) + break; + } + + /* do the right extension if the left extension did not find all + the bases required. Begin at the first base beyond the lookup + table hit and move forwards */ + + if (ext_left < ext_to) { + Int4 ext_right = 0; + s_off = s_offset + lut_word_length; + if (s_off + ext_to - ext_left > s_range) + continue; + q = query->sequence + q_offset + lut_word_length; + s = subject->sequence + s_off / COMPRESSION_RATIO; + + for (; ext_right < ext_to - ext_left; ++ext_right) { + if (((Uint1) (*s << (2 * (s_off % COMPRESSION_RATIO))) >> + 6) != *q) + break; + s_off++; + q++; + if (s_off % COMPRESSION_RATIO == 0) + s++; + } + + /* check if enough extra matches were found */ + if (ext_left + ext_right < ext_to) + continue; + } + + q_offset -= ext_left; + s_offset -= ext_left; + + /* adjust query offset */ + context = BSearchContextInfo(q_offset, query_info); + query_start = query_info->contexts[context].query_offset; + q_offset -= query_start; + ASSERT(q_offset >= 0); + + Int4 query_len = query_info->contexts[context].query_length; + Uint1* query_seq = query->sequence + query_start; + Int4 right_ungapped_ext_len = 0; + + JumperGappedAlignmentCompressedWithTraceback(query_seq, + subject->sequence, + query_len, + subject->length, + q_offset, + s_offset, + gap_align, + score_params, + &num_identical, + &right_ungapped_ext_len); + + hits_extended++; + /* Word hits on the same diagonal up to this query position will be + skipped. right_ungapped_ext_len gives the length of the first + ungapped segment of the right extension, hence word hits on this + part of the diagonal will not generate better alignment than the + one just found. This is assuming that word hits are sorted by + diagonal and query position. */ + skip_until = q_offset + query_start + right_ungapped_ext_len; + last_diag = diag; + + if (JumperGoodAlign(gap_align, hit_params, num_identical, + &query_info->contexts[context])) { + + BlastHSP* new_hsp; + Uint1* query_seq = query->sequence + query_start; + /* minimum length of the unaligned part of the subject to search + for matching small words */ + const Int4 kMinSubjectOverhang = 100; + /* maximum intron length, i.e. gap between two hsps that can be + combined */ + const Int4 kMaxIntronLength = hit_params->options->longest_intron; + + /* shift gaps the right */ + /* When several gap positions give the same alignment score, + gap positions in the alignment are arbitrary. Here we ensure + that gaps will be at the same postitions for all reads + that map to the same place in the genome. */ + if (!getenv("MAPPER_NO_GAP_SHIFT")) { + s_ShiftGaps(gap_align, query_seq, subject->sequence, + query_len, subject->length, + score_params->penalty, &num_identical); + } + + gap_align->edit_script = JumperPrelimEditBlockToGapEditScript( + gap_align->jumper->left_prelim_block, + gap_align->jumper->right_prelim_block); + + + status = Blast_HSPInit(gap_align->query_start, + gap_align->query_stop, + gap_align->subject_start, + gap_align->subject_stop, + q_offset, s_offset, + context, + query_info->contexts[context].frame, + subject->frame, + gap_align->score, + &(gap_align->edit_script), + &new_hsp); + if (!new_hsp) { + return -1; + } + new_hsp->map_info = BlastHSPMappingInfoNew(); + if (!new_hsp->map_info) { + return -1; + } + new_hsp->num_ident = num_identical; + new_hsp->evalue = 0.0; + new_hsp->map_info->edits = + JumperFindEdits(query_seq, subject->sequence, gap_align); + + if (hit_params->options->splice) { + /* FIXME: This is currently needed because these splice + sites are used in finding splice signals for overlapping + HSPs */ + JumperFindSpliceSignals(new_hsp, query_len, subject->sequence, + subject->length); + + s_SaveSubjectOverhangs(new_hsp, subject->sequence, query_len); + } + + ASSERT(new_hsp); + status = Blast_HSPListSaveHSP(hsp_list, new_hsp); + if (status) { + break; + } + + + /* If left of right query overhang is shorter than word size, then + if overhang length is smaller than mismatch penalty, + first assume the alignment ended with a mismatch and try to + extend it with perfect matches to the end of the query. If this + does not succeed, then look for 4-base word matches from + query overhangs. */ + + /* first for the right end of the query */ + if (getenv("MAPPER_USE_SMALL_WORDS") && + query_len - new_hsp->query.end < 16 && + query_len - new_hsp->query.end >= SUBJECT_INDEX_WORD_LENGTH && + subject->length - new_hsp->subject.end >= kMinSubjectOverhang) { + + Int4 q = new_hsp->query.end; + Int4 round = 0; + Boolean found = FALSE; + ASSERT(s_index); + + /* if number of unaligned query bases is smaller than + mismatch penalty, then try extending the alignment past the + mismatch to the end of the query */ + if (query_len - new_hsp->query.end < -score_params->penalty) { + Int4 i; + for (i = 1;i < query_len - new_hsp->query.end;i++) { + if (query_seq[new_hsp->query.end + i] != + UNPACK_BASE(subject->sequence, + new_hsp->subject.end + i)) { + break; + } + } + + /* if extension succeeded through 4 bases or till the end + of thequery, create and save an HSP */ + if (i > 4 || i == query_len - new_hsp->query.end) { + + BlastHSP* w_hsp = s_CreateHSPForWordHit( + new_hsp->query.end + 1, + new_hsp->subject.end + 1, + i - 1, + context, query_seq, + query_info, subject, + query_len); + + ASSERT(w_hsp->query.offset >= 0 && + w_hsp->query.end <= query_len); + status = Blast_HSPListSaveHSP(hsp_list, w_hsp); + if (status) { + return -1; + } + } + } + + for (; !found && q + SUBJECT_INDEX_WORD_LENGTH <= query_len && + round < 2;q++, round++) { + Int4 word; + Int4 from; + Int4 s_pos; + SubjectIndexIterator* it = NULL; + Int4 i; + + /* skip over ambiguous bases */ + while (q + SUBJECT_INDEX_WORD_LENGTH <= query_len) { + for (i = 0;i < SUBJECT_INDEX_WORD_LENGTH;i++) { + if ((query_seq[q + i] & 0xfc) != 0) { + q = q + i + 1; + break; + } + } + + if (i == SUBJECT_INDEX_WORD_LENGTH) { + break; + } + } + + if (q + SUBJECT_INDEX_WORD_LENGTH - 1 >= query_len) { + break; + } + + /* this is query word */ + word = (query_seq[q] << 6) | (query_seq[q + 1] << 4) | + (query_seq[q + 2] << 2) | query_seq[q + 3]; + for (i = 4; i < SUBJECT_INDEX_WORD_LENGTH; i++) { + word = (word << 2) | query_seq[q + i]; + } + + /* search subject for matching words from this position */ + from = new_hsp->subject.end; + + /* create subject word iterator and iterate from the end + of current HSP through the max intron length or up to + the end of subject less query overhang bases (so that + we can extend to the end of the query) */ + it = SubjectIndexIteratorNew(s_index, word, from, + MIN((from + kMaxIntronLength), + (subject->length - (query_len - q + 1)))); + + /* for each word match position in the subject */ + for (s_pos = SubjectIndexIteratorNext(it); s_pos >= 0; + s_pos = SubjectIndexIteratorNext(it)) { + Int4 qt; + Int4 st; + + /* try to extend the hit right to the end of the + query accepting only matches */ + qt = q; + st = s_pos; + while (qt < query_len && st < subject->length && + (query_seq[qt] == + UNPACK_BASE(subject->sequence, st) || + /* skip over ambiguous bases */ + (query_seq[qt] & 0xfc) != 0)) { + qt++; + st++; + } + + /* proceed only if query matches to the end and try + extending left as much as possible */ + if (qt == query_len) { + Int4 qf = q; + Int4 sf = s_pos; + BlastHSP* w_hsp = NULL; + + while (qf >= 0 && sf >= 0 && + (query_seq[qf] == + UNPACK_BASE(subject->sequence, sf) || + (query_seq[qf] & 0xfc) != 0)) { + + qf--; + sf--; + } + qf++; + sf++; + ASSERT(qt - qf == st - sf); + + if (qt - qf < 5 || + qf > new_hsp->query.end + 1 || + qf <= new_hsp->query.offset) { + + continue; + } + + + /* trim ambiguous bases at the ends of the word + match */ + while (qf < qt && (query_seq[qf] & 0xfc) != 0) { + qf++; + sf++; + } + + while (qt > qf && (query_seq[qt - 1] & 0xfc) != 0) { + qt--; + st--; + } + + if (qf >= qt) { + continue; + } + + /* create HSP */ + w_hsp = s_CreateHSPForWordHit(qf, sf, qt - qf, + context, query_seq, + query_info, subject, + query_len); + + ASSERT(w_hsp->query.offset >= 0 && + w_hsp->query.end <= query_len); + + ASSERT(w_hsp); + if (!w_hsp) { + return -1; + } + + /* add HSP to the list */ + status = Blast_HSPListSaveHSP(hsp_list, w_hsp); + if (status) { + return -1; + } + } + } + it = SubjectIndexIteratorFree(it); + } + } + + + if (getenv("MAPPER_USE_SMALL_WORDS") && + new_hsp->query.offset < 16 && + new_hsp->query.offset >= SUBJECT_INDEX_WORD_LENGTH && + new_hsp->subject.offset >= kMinSubjectOverhang) { + + Int4 q = MAX(new_hsp->query.offset - SUBJECT_INDEX_WORD_LENGTH, + 0); + Int4 round = 0; + Boolean found = FALSE; + ASSERT(s_index); + + /* if number of unaligned query bases is smaller than + mismatch penalty, then try extending the alignment past the + mismatch to beginning of the query */ + if (new_hsp->query.offset < -score_params->penalty) { + Int4 i; + for (i = 2;i < new_hsp->query.offset - 1;i++) { + if (query_seq[new_hsp->query.offset - i] != + UNPACK_BASE(subject->sequence, + new_hsp->subject.offset - i)) { + break; + } + } + + /* if the extension suceeded thrught at least 4 bases or + to the beginning of the query, create and save the HSP */ + if (i > 4 || i == new_hsp->query.offset - 1) { + + BlastHSP* w_hsp = s_CreateHSPForWordHit( + new_hsp->query.offset - 1 - i, + new_hsp->subject.offset - 1- i, + i, + context, query_seq, + query_info, subject, + query_len); + + ASSERT(w_hsp->query.offset >= 0 && + w_hsp->query.end <= query_len); + status = Blast_HSPListSaveHSP(hsp_list, w_hsp); + if (status) { + return -1; + } + } + } + + + for (; !found && q >= 0 && round < 2;q--, round++) { + + Int4 word; + Int4 from; + Int4 s_pos; + SubjectIndexIterator* it = NULL; + Int4 i; + + /* skip over ambiguous bases */ + while (q >= 0) { + for (i = 0;i < SUBJECT_INDEX_WORD_LENGTH;i++) { + if ((query_seq[q + i] & 0xfc) != 0) { + q = q + i - SUBJECT_INDEX_WORD_LENGTH; + break; + } + } + + if (i == SUBJECT_INDEX_WORD_LENGTH) { + break; + } + } + + if (q < 0) { + break; + } + + + /* this is query word */ + word = (query_seq[q] << 6) | (query_seq[q + 1] << 4) | + (query_seq[q + 2] << 2) | query_seq[q + 3]; + for (i = 4; i < SUBJECT_INDEX_WORD_LENGTH; i++) { + word = (word << 2) | query_seq[q + i]; + } + + + /* search subject for matching words from this position */ + from = new_hsp->subject.offset - SUBJECT_INDEX_WORD_LENGTH; + + it = SubjectIndexIteratorNew(s_index, word, from, + MAX(from - kMaxIntronLength, q + 1)); + + /* for each word match position in the subject */ + for (s_pos = SubjectIndexIteratorPrev(it); s_pos >= 0; + s_pos = SubjectIndexIteratorPrev(it)) { + + /* try extending left */ + Int4 k = q; + Int4 s = s_pos; + while (k >= 0 && + (query_seq[k] == + UNPACK_BASE(subject->sequence, s) || + (query_seq[k] & 0xfc) != 0)) { + k--; + s--; + } + /* if query matches all the way, then extend right as + far as there are matches */ + if (k == -1) { + Int4 qt = q; + Int4 st = s_pos; + BlastHSP* w_hsp = NULL; + + k++; + s++; + while (qt < query_len && st < subject->length && + (query_seq[qt] == + UNPACK_BASE(subject->sequence, st) || + /* skip over ambiguous bases */ + (query_seq[qt] & 0xfc) != 0)) { + qt++; + st++; + } + ASSERT(k - qt == s - st); + + + if (qt - k < 5 || + s >= new_hsp->subject.offset || + new_hsp->query.offset > qt + 1) { + continue; + } + + + /* trim ambiguous bases at the ends of the word + match */ + while (k < qt && (query_seq[k] & 0xfc) != 0) { + k++; + s++; + } + + while (qt > k && (query_seq[qt] & 0xfc) != 0) { + qt--; + st--; + } + + if (k >= qt) { + continue; + } + + /* create HSP */ + w_hsp = s_CreateHSPForWordHit(k, s, qt - k, + context, query_seq, + query_info, subject, + query_len); + + ASSERT(w_hsp->query.offset >= 0 && + w_hsp->query.end <= query_len); + + ASSERT(w_hsp); + if (!w_hsp) { + return -1; + } + + status = Blast_HSPListSaveHSP(hsp_list, w_hsp); + if (status) { + return -1; + } + } + } + it = SubjectIndexIteratorFree(it); + } + } + + } + } + + return hits_extended; +} + + +SubjectIndex* SubjectIndexFree(SubjectIndex* sindex) +{ + if (!sindex) { + return NULL; + } + + if (sindex->lookups) { + Int4 i; + for (i = 0;i < sindex->num_lookups;i++) { + if (sindex->lookups[i]) { + BlastNaLookupTableDestruct(sindex->lookups[i]); + } + } + free(sindex->lookups); + } + + free(sindex); + return NULL; +} + +static void +s_SubjectIndexNewCleanup(BLAST_SequenceBlk* sequence, BlastSeqLoc* seqloc, + LookupTableOptions* opt, QuerySetUpOptions* query_opt, + SubjectIndex* sindex) +{ + if (sequence) { + if (sequence->sequence) { + free(sequence->sequence); + } + free(sequence); + } + + while (seqloc) { + BlastSeqLoc* s = seqloc->next; + if (seqloc->ssr) { + free(seqloc->ssr); + } + free(seqloc); + seqloc = s; + } + + if (opt) { + free(opt); + } + + if (query_opt) { + free(query_opt); + } + + SubjectIndexFree(sindex); +} + +SubjectIndex* SubjectIndexNew(BLAST_SequenceBlk* subject, Int4 width, + Int4 word_size) +{ + Int4 i; + BLAST_SequenceBlk* sequence = NULL; + BlastSeqLoc* seqloc = NULL; + SSeqRange* ssr = NULL; + LookupTableOptions* opt = NULL; + QuerySetUpOptions* query_opt = NULL; + SubjectIndex* retval = NULL; + Int4 num_lookups = subject->length / width + 1; + + sequence = calloc(1, sizeof(BLAST_SequenceBlk)); + if (!sequence) { + return NULL; + } + + /* convert subject sequence to blastna */ + sequence->sequence = calloc(subject->length, sizeof(Uint1)); + if (!sequence->sequence) { + free(sequence); + return NULL; + } + + for (i = 0;i < subject->length / 4;i++) { + Int4 k; + for (k = 0;k < 4;k++) { + sequence->sequence[4 * i + k] = + (subject->sequence[i] >> (2 * (3 - k))) & 3; + } + } + + retval = calloc(1, sizeof(SubjectIndex)); + if (!retval) { + s_SubjectIndexNewCleanup(sequence, seqloc, opt, query_opt, retval); + } + + retval->lookups = calloc(num_lookups, sizeof(BlastNaLookupTable*)); + if (!retval->lookups) { + s_SubjectIndexNewCleanup(sequence, seqloc, opt, query_opt, retval); + } + + ssr = malloc(sizeof(SSeqRange)); + if (!ssr) { + s_SubjectIndexNewCleanup(sequence, seqloc, opt, query_opt, retval); + } + + seqloc = calloc(1, sizeof(BlastSeqLoc)); + if (!seqloc) { + if (ssr) { + free(ssr); + } + s_SubjectIndexNewCleanup(sequence, seqloc, opt, query_opt, retval); + return NULL; + } + + opt = calloc(1, sizeof(LookupTableOptions)); + if (!opt) { + s_SubjectIndexNewCleanup(sequence, seqloc, opt, query_opt, retval); + return NULL; + } + opt->word_size = 4; + + query_opt = calloc(1, sizeof(QuerySetUpOptions)); + if (!query_opt) { + s_SubjectIndexNewCleanup(sequence, seqloc, opt, query_opt, retval); + return NULL; + } + + + for (i = 0;i < num_lookups;i++) { + + ssr->left = width * i; + ssr->right = MIN(ssr->left + width, subject->length - 1); + + seqloc->ssr = ssr; + + BlastNaLookupTableNew(sequence, seqloc, &(retval->lookups[i]), opt, + query_opt, word_size); + + if (!retval->lookups[i]) { + s_SubjectIndexNewCleanup(sequence, seqloc, opt, query_opt, retval); + } + + ASSERT(i < num_lookups); + } + retval->num_lookups = i; + retval->width = width; + + s_SubjectIndexNewCleanup(sequence, seqloc, opt, query_opt, NULL); + + return retval; +} + + +SubjectIndexIterator* SubjectIndexIteratorFree(SubjectIndexIterator* it) +{ + if (it) { + free(it); + } + + return NULL; +} + +/* Create an iterator for positions of a given word in subject sequence between + positions from and to */ +SubjectIndexIterator* SubjectIndexIteratorNew(SubjectIndex* s_index, Int4 word, + Int4 from, Int4 to) +{ + SubjectIndexIterator* retval = NULL; + + if (!s_index || !s_index->lookups[0]) { + return NULL; + } + + retval = calloc(1, sizeof(SubjectIndexIterator)); + if (!retval) { + return NULL; + } + + retval->subject_index = s_index; + retval->to = to; + retval->lookup_index = from / s_index->width; + ASSERT(retval->lookup_index < s_index->num_lookups); + if (retval->lookup_index >= s_index->num_lookups) { + SubjectIndexIteratorFree(retval); + return NULL; + } + + /* find the first word with position at least from */ + while (retval->lookup_index < retval->subject_index->num_lookups) { + BlastNaLookupTable* lookup = s_index->lookups[retval->lookup_index]; + if (!lookup) { + SubjectIndexIteratorFree(retval); + return NULL; + } + + word = word & lookup->mask; + retval->num_words = lookup->thick_backbone[word].num_used; + if (retval->num_words <= NA_HITS_PER_CELL) { + retval->lookup_pos = lookup->thick_backbone[word].payload.entries; + } + else { + retval->lookup_pos = lookup->overflow + + lookup->thick_backbone[word].payload.overflow_cursor; + } + + retval->word = word; + retval->word_index = 0; + + while (retval->word_index < retval->num_words && + retval->lookup_pos[retval->word_index] < from) { + + retval->word_index++; + } + + if (retval->word_index >= retval->num_words) { + retval->lookup_index++; + } + else { + break; + } + } + + return retval; +} + +/* Return current position of a word and move iterator to the next position */ +Int4 SubjectIndexIteratorNext(SubjectIndexIterator* it) +{ + Int4 pos; + + if (!it) { + return -1; + } + + /* if all words in the current lookup table were processed, move to the + next lookup table */ + if (it->word_index >= it->num_words) { + BlastNaLookupTable* lookup = NULL; + it->lookup_index++; + + /* if no more lookup table return no positon found */ + if (it->lookup_index >= it->subject_index->num_lookups) { + return -1; + } + lookup = it->subject_index->lookups[it->lookup_index]; + ASSERT(lookup); + it->num_words = lookup->thick_backbone[it->word].num_used; + if (it->num_words <= NA_HITS_PER_CELL) { + it->lookup_pos = lookup->thick_backbone[it->word].payload.entries; + } + else { + it->lookup_pos = lookup->overflow + + lookup->thick_backbone[it->word].payload.overflow_cursor; + } + ASSERT(it->lookup_pos); + it->word_index = 0; + } + + if (!it->lookup_pos) { + return -1; + } + + pos = it->lookup_pos[it->word_index]; + if (pos > it->to) { + return -1; + } + + /* move iterator to the next position */ + it->word_index++; + + return pos; +} + +/* Return current position of a word and move iterator to the previous + position */ +Int4 SubjectIndexIteratorPrev(SubjectIndexIterator* it) +{ + Int4 pos; + + if (!it) { + return -1; + } + + if (it->word_index < 0) { + BlastNaLookupTable* lookup = NULL; + it->lookup_index--; + if (it->lookup_index < 0) { + return -1; + } + lookup = it->subject_index->lookups[it->lookup_index]; + ASSERT(lookup); + it->num_words = lookup->thick_backbone[it->word].num_used; + if (it->num_words <= NA_HITS_PER_CELL) { + it->lookup_pos = lookup->thick_backbone[it->word].payload.entries; + } + else { + it->lookup_pos = lookup->overflow + + lookup->thick_backbone[it->word].payload.overflow_cursor; + } + ASSERT(it->lookup_pos); + it->word_index = it->num_words - 1; + } + + if (!it->lookup_pos) { + return -1; + } + + pos = it->lookup_pos[it->word_index]; + if (pos < it->to) { + return -1; + } + + it->word_index--; + + return pos; +} + + diff --git a/c++/src/algo/blast/core/jumper.h b/c++/src/algo/blast/core/jumper.h new file mode 100644 index 00000000..9895ddba --- /dev/null +++ b/c++/src/algo/blast/core/jumper.h @@ -0,0 +1,279 @@ +/* $Id: jumper.h 504946 2016-06-21 13:53:04Z madden $ + * =========================================================================== + * + * PUBLIC DOMAIN NOTICE + * National Center for Biotechnology Information + * + * This software/database is a "United States Government Work" under the + * terms of the United States Copyright Act. It was written as part of + * the author's official duties as a United States Government employee and + * thus cannot be copyrighted. This software/database is freely available + * to the public for use. The National Library of Medicine and the U.S. + * Government have not placed any restriction on its use or reproduction. + * + * Although all reasonable efforts have been taken to ensure the accuracy + * and reliability of the software and data, the NLM and the U.S. + * Government do not and cannot warrant the performance or results that + * may be obtained by using this software or data. The NLM and the U.S. + * Government disclaim all warranties, express or implied, including + * warranties of performance, merchantability or fitness for any particular + * purpose. + * + * Please cite the author in any work or product based on this material. + * + * =========================================================================== + * + * Author: Greg Boratyn + * + * Jumper alignment + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { int dcp, dcq, lng, ok; } JUMP; + +/* Simple edit script for jumper: represented as integer n: + n > 0: n matches + n == 0: a single mismatch + n < 0: a single insertion or deletion */ +#define JUMPER_MISMATCH (0) +#define JUMPER_INSERTION (-1) +#define JUMPER_DELETION (-2) + +/** Jumper edit script operation */ +typedef Int2 JumperOpType; + +/** Internal alignment edit script */ +typedef struct JumperPrelimEditBlock +{ + JumperOpType* edit_ops; + Int4 num_ops; + Int4 num_allocated; +} JumperPrelimEditBlock; + + +/** Gapped alignment data needed for jumper */ +typedef struct JumperGapAlign +{ + JumperPrelimEditBlock* left_prelim_block; + JumperPrelimEditBlock* right_prelim_block; + Uint4* table; /**< Table used for matching 4 bases in compressed subject + to 4 bases in uncompressed query */ +} JumperGapAlign; + + +JumperGapAlign* JumperGapAlignFree(JumperGapAlign* jumper_align); +JumperGapAlign* JumperGapAlignNew(Int4 size); +Int4 JumperPrelimEditBlockAdd(JumperPrelimEditBlock* block, JumperOpType op); + + +/** Single alignment error */ +typedef struct JumperEdit +{ + Int4 query_pos; /**< Query position*/ + Uint1 query_base; /**< Query base at this position */ + Uint1 subject_base; /**< Subject base at this position */ +} JumperEdit; + + +/** Alignment edit script for gapped alignment */ +typedef struct JumperEditsBlock +{ + JumperEdit* edits; + Int4 num_edits; +} JumperEditsBlock; + + +JumperEditsBlock* JumperEditsBlockFree(JumperEditsBlock* block); +JumperEditsBlock* JumperEditsBlockDup(const JumperEditsBlock* block); +JumperEditsBlock* JumperFindEdits(const Uint1* query, const Uint1* subject, + BlastGapAlignStruct* gap_align); + +/** Convert Jumper's preliminary edit script to GapEditScript */ +GapEditScript* JumperPrelimEditBlockToGapEditScript( + JumperPrelimEditBlock* rev_prelim_block, + JumperPrelimEditBlock* fwd_prelim_block); + + +/** Test whether an HSP should be saved */ +Boolean JumperGoodAlign(const BlastGapAlignStruct* gap_align, + const BlastHitSavingParameters* hit_params, + Int4 num_identical, + BlastContextInfo* range_info); + + +/** Right extension with traceback */ +Int4 JumperExtendRightWithTraceback( + const Uint1* query, const Uint1* subject, + int query_length, int subject_length, + Int4 match_score, Int4 mismatch_score, + Int4 gap_open, Int4 gap_extend, + int max_mismatches, int window, + Int4* query_ext_len, Int4* subject_ext_len, + JumperPrelimEditBlock* edit_script, + Int4* num_identical, + Boolean left_extension, + Int4* ungapped_ext_len, + JUMP* jumper); + + + +/** Jumper gapped alignment with traceback; 1 base per byte in query, 4 bases + per byte in subject */ +int JumperGappedAlignmentCompressedWithTraceback(const Uint1* query, + const Uint1* subject, + Int4 query_length, Int4 subject_length, + Int4 query_start, Int4 subject_start, + BlastGapAlignStruct* gap_align, + const BlastScoringParameters* score_params, + Int4* num_identical, + Int4* right_ungapped_ext_len); + + +#define SUBJECT_INDEX_WORD_LENGTH (4) + +/** Index for a chunk of a subject sequence */ +typedef struct SubjectIndex +{ + /** Array of lookup tables */ + BlastNaLookupTable** lookups; + /** Number of bases covered by each lookup table */ + Int4 width; + /** Number of lookup tables used */ + Int4 num_lookups; +} SubjectIndex; + +/** Free subject index structure */ +SubjectIndex* SubjectIndexFree(SubjectIndex* sindex); + +/** Index a sequence, used for indexing compressed nucleotide subject + * sequence. The index consists of a list of lookup tables, each covering + * width number of bases. + * + * @param subject Sequence to be indexed [in] + * @param width Number of bases covered by a single lookup table [in] + * @param word_size Word size to be used in the lookup table [in] + * @return Pointer to the created index + */ +SubjectIndex* SubjectIndexNew(BLAST_SequenceBlk* subject, Int4 width, + Int4 word_size); + + +/** Iterator over word locations in subject index */ +typedef struct SubjectIndexIterator +{ + SubjectIndex* subject_index; + Int4 word; + Int4 from; + Int4 to; + Int4 lookup_index; + Int4* lookup_pos; + Int4 num_words; + Int4 word_index; +} SubjectIndexIterator; + + +/** Free memory reserved for subject index word iterator */ +SubjectIndexIterator* SubjectIndexIteratorFree(SubjectIndexIterator* it); + +/** Create an iterator for locations of a given word + * @param s_index Sequence index [in] + * @param word Nucleotide word to be searched [in] + * @param from Sequence location to begin search [in] + * @param to Sequence location to end search [in] + * @return Word location iterator + */ +SubjectIndexIterator* SubjectIndexIteratorNew(SubjectIndex* s_index, Int4 word, + Int4 from, Int4 to); + +/** Return the next location of a word in an indexed sequence + * @param it Iterator [in|out] + * @return Word location or value less than zero if no more words are found + */ +Int4 SubjectIndexIteratorNext(SubjectIndexIterator* it); + +/** Return the previous location of a word in an indexed sequence + * @param it Iterator [in|out] + * @return Word location or value less than zero if no more words are found + */ +Int4 SubjectIndexIteratorPrev(SubjectIndexIterator* it); + + + +/** Extend a list of word hits */ +Int4 BlastNaExtendJumper(BlastOffsetPair* offset_pairs, Int4 num_hits, + const BlastInitialWordParameters* word_params, + const BlastScoringParameters* score_params, + const BlastHitSavingParameters* hit_params, + LookupTableWrap* lookup_wrap, + BLAST_SequenceBlk* query, + BLAST_SequenceBlk* subject, + BlastQueryInfo* query_info, + BlastGapAlignStruct* gap_align, + BlastHSPList* hsp_list, + Uint4 s_range, + SubjectIndex* s_index); + + +#define MAPPER_SPLICE_SIGNAL (0x80) +#define MAPPER_EXON (0x40) +#define MAPPER_POLY_A (0x20) +#define MAPPER_ADAPTER (0x10) + +/** Find splice signals at the edges of an HSP and save them in the HSP + * @param hsp HSP [in|out] + * @param query_len Length of the query/read [in] + * @param subject Subject sequence [in] + * @param subject_len Subject length [in] + * @return Zero on success + */ +int JumperFindSpliceSignals(BlastHSP* hsp, Int4 query_len, + const Uint1* subject, Int4 subject_len); + + +#define MAPPER_FLAGS_PAIR_CONVERGENT (1) +#define MAPPER_FLAGS_PAIR_DIVERGENT (1 << 1) +#define MAPPER_FLAGS_PAIR_REARRANGED (1 << 2) + +#define MAPPER_FLAGS_PAIR (MAPPER_FLAGS_PAIR_CONVERGENT | MAPPER_FLAGS_PAIR_DIVERGENT | MAPPER_FLAGS_PAIR_REARRANGED) + + +/* Combine edit scripts into one. Returns the combined edit script, deletes + input scripts. */ +GapEditScript* GapEditScriptCombine(GapEditScript** edit_script, + GapEditScript** append); + +/* Combine two edits blocks into one. Returns the combined block, deletes input + blocks */ +JumperEditsBlock* JumperEditsBlockCombine(JumperEditsBlock** block, + JumperEditsBlock** append); + +/** Structure to save short unaligned subsequences outside an HSP */ +typedef struct SequenceOverhangs +{ + Int4 left_len; /**< Length of the left subsequence */ + Int4 right_len; /**< Length of the right subsequence */ + Uint1* left; /**< Left subsequence */ + Uint1* right; /**< Rught subsequence */ +} SequenceOverhangs; + +SequenceOverhangs* SequenceOverhangsFree(SequenceOverhangs* overhangs); + + +#ifdef __cplusplus +} +#endif + diff --git a/c++/src/algo/blast/core/link_hsps.c b/c++/src/algo/blast/core/link_hsps.c index 41d543fa..4ba0cec4 100644 --- a/c++/src/algo/blast/core/link_hsps.c +++ b/c++/src/algo/blast/core/link_hsps.c @@ -1,5 +1,5 @@ -/* $Id: link_hsps.c 371542 2012-08-09 14:41:30Z boratyng $ +/* $Id: link_hsps.c 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -32,11 +32,6 @@ * Functions to link with use of sum statistics */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: link_hsps.c 371542 2012-08-09 14:41:30Z boratyng $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include "blast_hits_priv.h" diff --git a/c++/src/algo/blast/core/lookup_util.c b/c++/src/algo/blast/core/lookup_util.c index dd38202c..a9f426dc 100644 --- a/c++/src/algo/blast/core/lookup_util.c +++ b/c++/src/algo/blast/core/lookup_util.c @@ -1,4 +1,4 @@ -/* $Id: lookup_util.c 94537 2006-12-01 16:52:58Z papadopo $ +/* $Id: lookup_util.c 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -28,11 +28,6 @@ * Utility functions for lookup table generation. */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: lookup_util.c 94537 2006-12-01 16:52:58Z papadopo $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include static void fkm_output(Int4 * a, @@ -73,7 +68,7 @@ iexp(Int4 x, } Int4 -ilog2(Int4 x) +ilog2(Int8 x) { Int4 lg = 0; diff --git a/c++/src/algo/blast/core/lookup_wrap.c b/c++/src/algo/blast/core/lookup_wrap.c index 94884a42..a289778f 100644 --- a/c++/src/algo/blast/core/lookup_wrap.c +++ b/c++/src/algo/blast/core/lookup_wrap.c @@ -1,4 +1,4 @@ -/* $Id: lookup_wrap.c 363884 2012-05-21 15:54:30Z morgulis $ +/* $Id: lookup_wrap.c 506102 2016-07-01 15:48:06Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -35,11 +35,6 @@ * megablast lookup table, etc. */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: lookup_wrap.c 363884 2012-05-21 15:54:30Z morgulis $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include @@ -54,7 +49,8 @@ Int2 LookupTableWrapInit(BLAST_SequenceBlk* query, const QuerySetUpOptions* query_options, BlastSeqLoc* lookup_segments, BlastScoreBlk* sbp, LookupTableWrap** lookup_wrap_ptr, const BlastRPSInfo *rps_info, - Blast_Message* *error_msg) + Blast_Message* *error_msg, + BlastSeqSrc* seqsrc) { Int2 status = 0; LookupTableWrap* lookup_wrap; @@ -121,7 +117,8 @@ Int2 LookupTableWrapInit(BLAST_SequenceBlk* query, BlastMBLookupTableNew(query, lookup_segments, (BlastMBLookupTable* *) &(lookup_wrap->lut), lookup_options, query_options, - num_table_entries, lut_width); + num_table_entries, lut_width, + seqsrc); } else if (lookup_wrap->lut_type == eSmallNaLookupTable) { status = BlastSmallNaLookupTableNew(query, lookup_segments, @@ -143,6 +140,13 @@ Int2 LookupTableWrapInit(BLAST_SequenceBlk* query, ASSERT( lookup_wrap->lut_type != eMixedMBLookupTable ); break; + case eNaHashLookupTable: + status = BlastNaHashLookupTableNew(query, lookup_segments, + (BlastNaHashLookupTable**) &(lookup_wrap->lut), + lookup_options, query_options, seqsrc); + break; + + case ePhiLookupTable: case ePhiNaLookupTable: { const Boolean kIsDna = @@ -210,6 +214,11 @@ LookupTableWrap* LookupTableWrapFree(LookupTableWrap* lookup) BlastNaLookupTableDestruct((BlastNaLookupTable*)lookup->lut); break; + case eNaHashLookupTable: + lookup->lut = (void*) + BlastNaHashLookupTableDestruct((BlastNaHashLookupTable*)lookup->lut); + break; + case eAaLookupTable: lookup->lut = (void*) BlastAaLookupTableDestruct((BlastAaLookupTable*)lookup->lut); @@ -251,6 +260,10 @@ Int4 GetOffsetArraySize(LookupTableWrap* lookup) offset_array_size = OFFSET_ARRAY_SIZE + ((BlastNaLookupTable*)lookup->lut)->longest_chain; break; + case eNaHashLookupTable: + offset_array_size = OFFSET_ARRAY_SIZE + + ((BlastNaHashLookupTable*)lookup->lut)->longest_chain; + break; default: offset_array_size = OFFSET_ARRAY_SIZE; break; diff --git a/c++/src/algo/blast/core/matrix_freq_ratios.c b/c++/src/algo/blast/core/matrix_freq_ratios.c index 8a47a7a9..7bd6c582 100644 --- a/c++/src/algo/blast/core/matrix_freq_ratios.c +++ b/c++/src/algo/blast/core/matrix_freq_ratios.c @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: matrix_freq_ratios.c 439568 2014-07-01 16:13:36Z madden $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/algo/blast/core/na_ungapped.c b/c++/src/algo/blast/core/na_ungapped.c index ed200a46..1c3d5b36 100644 --- a/c++/src/algo/blast/core/na_ungapped.c +++ b/c++/src/algo/blast/core/na_ungapped.c @@ -1,4 +1,4 @@ -/* $Id: na_ungapped.c 449473 2014-10-16 19:52:47Z fongah2 $ +/* $Id: na_ungapped.c 505619 2016-06-27 18:51:47Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -28,11 +28,6 @@ * Nucleotide ungapped extension routines */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: na_ungapped.c 449473 2014-10-16 19:52:47Z fongah2 $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include @@ -41,6 +36,7 @@ static char const rcsid[] = #include "index_ungapped.h" #include "masksubj.inl" +#include "jumper.h" /** Check to see if an index->q_pos pair exists in MB lookup table * @param lookup_wrap The lookup table wrap structure [in] @@ -640,7 +636,8 @@ s_BlastnDiagTableExtendInitialHit(BLAST_SequenceBlk * query, const BlastInitialWordParameters * word_params, Int4 ** matrix, BLAST_DiagTable * diag_table, - BlastInitHitList * init_hitlist) + BlastInitHitList * init_hitlist, + Boolean check_masks) { Int4 diag, real_diag; Int4 s_end, s_off_pos, s_end_pos; @@ -715,7 +712,7 @@ s_BlastnDiagTableExtendInitialHit(BLAST_SequenceBlk * query, hit_ready = 0; } } - } else { + } else if (check_masks) { /* check the masks for the word */ if(!s_TypeOfWord(query, subject, &q_off, &s_off, query_mask, query_info, s_range, @@ -807,7 +804,8 @@ s_BlastnDiagHashExtendInitialHit(BLAST_SequenceBlk * query, const BlastInitialWordParameters * word_params, Int4 ** matrix, BLAST_DiagHash * hash_table, - BlastInitHitList * init_hitlist) + BlastInitHitList * init_hitlist, + Boolean check_masks) { Int4 diag; Int4 s_end, s_off_pos, s_end_pos, s_l; @@ -883,8 +881,8 @@ s_BlastnDiagHashExtendInitialHit(BLAST_SequenceBlk * query, hit_ready = 0; } } - } else { - /* check the masks for the word */ + } else if (check_masks) { + /* check the masks for the word */ if (!s_TypeOfWord(query, subject, &q_off, &s_off, query_mask, query_info, s_range, word_length, lut_word_length, lut, FALSE, &extended)) return 0; @@ -973,11 +971,13 @@ s_BlastNaExtendDirect(const BlastOffsetPair * offset_pairs, Int4 num_hits, Int4 index = 0; Int4 hits_extended = 0; Int4 word_length; + Boolean check_masks = TRUE; if (lookup_wrap->lut_type == eMBLookupTable) { BlastMBLookupTable *lut = (BlastMBLookupTable *) lookup_wrap->lut; word_length = (lut->discontiguous) ? lut->template_length : lut->word_length; ASSERT(word_length == lut->lut_word_length || lut->discontiguous); + check_masks = !lut->stride; } else if (lookup_wrap->lut_type == eSmallNaLookupTable) { BlastSmallNaLookupTable *lut = @@ -1002,7 +1002,8 @@ s_BlastNaExtendDirect(const BlastOffsetPair * offset_pairs, Int4 num_hits, lookup_wrap, word_params, matrix, ewp->hash_table, - init_hitlist); + init_hitlist, + check_masks); } } else { @@ -1018,7 +1019,8 @@ s_BlastNaExtendDirect(const BlastOffsetPair * offset_pairs, Int4 num_hits, lookup_wrap, word_params, matrix, ewp->diag_table, - init_hitlist); + init_hitlist, + check_masks); } } return hits_extended; @@ -1058,12 +1060,14 @@ s_BlastNaExtend(const BlastOffsetPair * offset_pairs, Int4 num_hits, Int4 hits_extended = 0; Int4 word_length, lut_word_length, ext_to; BlastSeqLoc* masked_locations = NULL; + Boolean check_masks = TRUE; if (lookup_wrap->lut_type == eMBLookupTable) { BlastMBLookupTable *lut = (BlastMBLookupTable *) lookup_wrap->lut; word_length = lut->word_length; lut_word_length = lut->lut_word_length; masked_locations = lut->masked_locations; + check_masks = !lut->stride; } else { BlastNaLookupTable *lut = (BlastNaLookupTable *) lookup_wrap->lut; @@ -1148,7 +1152,8 @@ s_BlastNaExtend(const BlastOffsetPair * offset_pairs, Int4 num_hits, lookup_wrap, word_params, matrix, ewp->hash_table, - init_hitlist); + init_hitlist, + check_masks); } else { hits_extended += s_BlastnDiagTableExtendInitialHit(query, subject, q_offset, s_offset, @@ -1158,7 +1163,8 @@ s_BlastNaExtend(const BlastOffsetPair * offset_pairs, Int4 num_hits, lookup_wrap, word_params, matrix, ewp->diag_table, - init_hitlist); + init_hitlist, + check_masks); } } return hits_extended; @@ -1197,12 +1203,14 @@ s_BlastNaExtendAligned(const BlastOffsetPair * offset_pairs, Int4 num_hits, Int4 hits_extended = 0; Int4 word_length, lut_word_length, ext_to; BlastSeqLoc* masked_locations = NULL; + Boolean check_masks = TRUE; if (lookup_wrap->lut_type == eMBLookupTable) { BlastMBLookupTable *lut = (BlastMBLookupTable *) lookup_wrap->lut; word_length = lut->word_length; lut_word_length = lut->lut_word_length; masked_locations = lut->masked_locations; + check_masks = !lut->stride; } else { BlastNaLookupTable *lut = (BlastNaLookupTable *) lookup_wrap->lut; @@ -1294,7 +1302,8 @@ s_BlastNaExtendAligned(const BlastOffsetPair * offset_pairs, Int4 num_hits, lookup_wrap, word_params, matrix, ewp->hash_table, - init_hitlist); + init_hitlist, + check_masks); } else { hits_extended += s_BlastnDiagTableExtendInitialHit(query, subject, q_offset, s_offset, @@ -1304,7 +1313,8 @@ s_BlastNaExtendAligned(const BlastOffsetPair * offset_pairs, Int4 num_hits, lookup_wrap, word_params, matrix, ewp->diag_table, - init_hitlist); + init_hitlist, + check_masks); } } return hits_extended; @@ -1430,7 +1440,8 @@ s_BlastSmallNaExtendAlignedOneByte(const BlastOffsetPair * offset_pairs, lookup_wrap, word_params, matrix, ewp->hash_table, - init_hitlist); + init_hitlist, + TRUE); } else { hits_extended += s_BlastnDiagTableExtendInitialHit(query, subject, @@ -1441,7 +1452,8 @@ s_BlastSmallNaExtendAlignedOneByte(const BlastOffsetPair * offset_pairs, lookup_wrap, word_params, matrix, ewp->diag_table, - init_hitlist); + init_hitlist, + TRUE); } } return hits_extended; @@ -1559,7 +1571,8 @@ s_BlastSmallNaExtend(const BlastOffsetPair * offset_pairs, Int4 num_hits, lookup_wrap, word_params, matrix, ewp->hash_table, - init_hitlist); + init_hitlist, + TRUE); } else { hits_extended += s_BlastnDiagTableExtendInitialHit(query, subject, q_offset, s_offset, @@ -1569,7 +1582,8 @@ s_BlastSmallNaExtend(const BlastOffsetPair * offset_pairs, Int4 num_hits, lookup_wrap, word_params, matrix, ewp->diag_table, - init_hitlist); + init_hitlist, + TRUE); } } return hits_extended; @@ -1800,6 +1814,9 @@ void BlastChooseNaExtend(LookupTableWrap * lookup_wrap) else lut->extend_callback = (void *)s_BlastSmallNaExtend; } + else if (lookup_wrap->lut_type == eNaHashLookupTable) { + lookup_wrap->lookup_callback = NULL; + } else { BlastNaLookupTable *lut; lookup_wrap->lookup_callback = (void *)s_NaLookup; @@ -1814,3 +1831,489 @@ void BlastChooseNaExtend(LookupTableWrap * lookup_wrap) lut->extend_callback = (void *)s_BlastNaExtend; } } + + +MapperWordHits* MapperWordHitsFree(MapperWordHits* wh) +{ + if (wh) { + if (wh->pair_arrays) { + if (wh->pair_arrays[0]) { + sfree(wh->pair_arrays[0]); + } + sfree(wh->pair_arrays); + } + + if (wh->num) { + sfree(wh->num); + } + + if (wh->last_diag) { + sfree(wh->last_diag); + } + + if (wh->last_pos) { + sfree(wh->last_pos); + } + + sfree(wh); + } + + return NULL; +} + +MapperWordHits* MapperWordHitsNew(const BLAST_SequenceBlk* query, + const BlastQueryInfo* query_info) +{ + MapperWordHits* wh = NULL; + Int4 num_arrays; + Int4 array_size; + Int4 i; + + num_arrays = MAX(query_info->num_queries / 100, 1); + array_size = 1000; + + wh = calloc(1, sizeof(MapperWordHits)); + if (!wh) { + return NULL; + } + + wh->pair_arrays = calloc(num_arrays, sizeof(BlastOffsetPair*)); + if (!wh->pair_arrays) { + MapperWordHitsFree(wh); + return NULL; + } + + wh->pair_arrays[0] = + malloc(num_arrays * array_size * sizeof(BlastOffsetPair)); + if (!wh->pair_arrays[0]) { + MapperWordHitsFree(wh); + return NULL; + } + + for (i = 1;i < num_arrays;i++) { + wh->pair_arrays[i] = wh->pair_arrays[0] + (i * array_size); + } + + wh->num = calloc(num_arrays, sizeof(Int4)); + if (!wh->num) { + MapperWordHitsFree(wh); + return NULL; + } + + wh->num_arrays = num_arrays; + wh->array_size = array_size; + wh->divisor = query->length / wh->num_arrays + 1; + + wh->last_diag = calloc(query_info->last_context + 1, sizeof(Int4)); + if (!wh) { + MapperWordHitsFree(wh); + return NULL; + } + + wh->last_pos = malloc((query_info->last_context + 1) * sizeof(Int4)); + if (!wh) { + MapperWordHitsFree(wh); + return NULL; + } + for (i = 0;i < query_info->num_queries;i++) { + wh->last_pos[i] = INT4_MIN; + } + + return wh; +} + + +Int2 +JumperNaWordFinder(BLAST_SequenceBlk * subject, + BLAST_SequenceBlk * query, + BlastQueryInfo * query_info, + LookupTableWrap * lookup_wrap, + const BlastInitialWordParameters * word_params, + const BlastScoringParameters* score_params, + const BlastHitSavingParameters* hit_params, + BlastOffsetPair * offset_pairs, + MapperWordHits* word_hits, + Int4 max_hits, + BlastGapAlignStruct* gap_align, + BlastInitHitList* init_hitlist, + BlastHSPList** hsp_list_ptr, + BlastUngappedStats * ungapped_stats, + BlastGappedStats* gapped_stats) +{ + Int4 hitsfound, total_hits = 0; + Int4 hits_extended = 0; + TNaScanSubjectFunction scansub = NULL; + Int4 scan_range[3]; + Int4 word_length; + Int4 lut_word_length; + BlastHSPList* hsp_list = NULL; + Boolean read_is_query = query_info->max_length < subject->length; + SubjectIndex* s_index = NULL; + Int4 i; + + if (*hsp_list_ptr == NULL) { + *hsp_list_ptr = hsp_list = Blast_HSPListNew(BlastHspNumMax(TRUE, + hit_params->options)); + } + else { + hsp_list = *hsp_list_ptr; + } + + if (word_hits) { + memset(word_hits->num, 0, word_hits->num_arrays * sizeof(Int4)); + } + + if (lookup_wrap->lut_type == eSmallNaLookupTable) { + BlastSmallNaLookupTable *lookup = + (BlastSmallNaLookupTable *) lookup_wrap->lut; + word_length = lookup->word_length; + lut_word_length = lookup->lut_word_length; + scansub = (TNaScanSubjectFunction)lookup->scansub_callback; + } + else if (lookup_wrap->lut_type == eMBLookupTable) { + BlastMBLookupTable *lookup = + (BlastMBLookupTable *) lookup_wrap->lut; + if (lookup->discontiguous) { + word_length = lookup->template_length; + lut_word_length = lookup->template_length; + } else { + word_length = lookup->word_length; + lut_word_length = lookup->lut_word_length; + } + scansub = (TNaScanSubjectFunction)lookup->scansub_callback; + } + else if (lookup_wrap->lut_type == eNaHashLookupTable) { + BlastNaHashLookupTable *lookup = + (BlastNaHashLookupTable *) lookup_wrap->lut; + + word_length = lookup->word_length; + lut_word_length = lookup->lut_word_length; + scansub = (TNaScanSubjectFunction)lookup->scansub_callback; + } + else { + BlastNaLookupTable *lookup = + (BlastNaLookupTable *) lookup_wrap->lut; + word_length = lookup->word_length; + lut_word_length = lookup->lut_word_length; + scansub = (TNaScanSubjectFunction)lookup->scansub_callback; + } + + scan_range[0] = 0; /* subject seq mask index */ + scan_range[1] = 0; /* start pos of scan */ + scan_range[2] = subject->length - lut_word_length; /*end pos (inclusive) of scan*/ + + /* if sequence is masked, fall back to generic scanner and extender */ + if (subject->mask_type != eNoSubjMasking) { + if (lookup_wrap->lut_type == eMBLookupTable && + ((BlastMBLookupTable *) lookup_wrap->lut)->discontiguous) { + /* discontiguous scan subs assumes any (non-aligned starting offset */ + } else { + scansub = (TNaScanSubjectFunction) + BlastChooseNucleotideScanSubjectAny(lookup_wrap); + } + /* generic scanner permits any (non-aligned) starting offset */ + scan_range[1] = subject->seq_ranges[0].left + word_length - lut_word_length; + scan_range[2] = subject->seq_ranges[0].right - lut_word_length; + } + + ASSERT(scansub); + + if (getenv("MAPPER_USE_SMALL_WORDS")) { + s_index = SubjectIndexNew(subject, 10000, SUBJECT_INDEX_WORD_LENGTH); + } + while(s_DetermineScanningOffsets(subject, word_length, lut_word_length, scan_range)) { + + + hitsfound = scansub(lookup_wrap, subject, offset_pairs, max_hits, &scan_range[1]); + + if (hitsfound >= 0) { + + /* if the extended word hits structure is allocated */ + if (word_hits) { + + /* Distribute each word hit into lists that correspond to + a group of queries, ensuring that most word hits for each + query are extended in the same batch. */ + for (i = 0; i < hitsfound;i++) { + Int4 q_off = offset_pairs[i].qs_offsets.q_off; + Int4 s_off = offset_pairs[i].qs_offsets.s_off; + Int4 index = q_off / word_hits->divisor; + + Int4 context = BSearchContextInfo(q_off, query_info); + Int4 diag = s_off - q_off; + Int4 last_d = word_hits->last_diag[context]; + Int4 last_p = word_hits->last_pos[context]; + + word_hits->last_diag[context] = diag; + word_hits->last_pos[context] = s_off; + + /* Discard word hits on the same diagnol and with adjacent + positions, allowing up to 2 mismatches, as the last one + saved. All these word hits will produce the same + alignment. There is another check for this situation + before extension, but doing it here helps keeping + numer of word hits managable. The other check is still + necessary, because depending on extension more + word hits can be discarded. */ + if (last_d == diag && s_off - last_p < lut_word_length + 3) { + continue; + } + ASSERT(index < word_hits->num_arrays); + + + /* if the word hit list for the current word hit is full, + then extend hits from this list */ + if (word_hits->num[index] >= word_hits->array_size) { + Int4 range = word_hits->pair_arrays[index][ + word_hits->num[index] - 1].qs_offsets.s_off + + lut_word_length; + hits_extended += BlastNaExtendJumper( + word_hits->pair_arrays[index], + word_hits->num[index], + word_params, score_params, + hit_params, + lookup_wrap, + query, subject, + query_info, + gap_align, + hsp_list, + range, + s_index); + + word_hits->num[index] = 0; + + } + + /* add new word hit */ + word_hits->pair_arrays[index][word_hits->num[index]++] = + offset_pairs[i]; + } + } + else { + /* otherwise extend collected word hits */ + + total_hits += hitsfound; + hits_extended += BlastNaExtendJumper(offset_pairs, hitsfound, + word_params, score_params, + hit_params, + lookup_wrap, + query, subject, + query_info, + gap_align, + hsp_list, + scan_range[2] + lut_word_length, + s_index); + + } + } + + if (!read_is_query) { + break; + } + } + + if (word_hits) { + + /* extend word hits from all lists */ + for (i = 0;i < word_hits->num_arrays;i++) { + if (word_hits->num[i] > 0) { + Int4 range = word_hits->pair_arrays[i][ + word_hits->num[i] - 1].qs_offsets.s_off + + lut_word_length; + hits_extended += BlastNaExtendJumper(word_hits->pair_arrays[i], + word_hits->num[i], + word_params, score_params, + hit_params, + lookup_wrap, + query, subject, + query_info, + gap_align, + hsp_list, + range, + s_index); + + } + word_hits->num[i] = 0; + } + } + + Blast_UngappedStatsUpdate(ungapped_stats, total_hits, 0, 0); + + if (gapped_stats) { + gapped_stats->extensions = hits_extended; + /* this is needed for adaptive batch size */ + ungapped_stats->good_init_extends = hits_extended; + } + + if (s_index) { + s_index = SubjectIndexFree(s_index); + } + + return 0; + +} + + +/* read is a qurey, reference is a subject */ +Int2 ShortRead_IndexedWordFinder( + BLAST_SequenceBlk * subject, + BLAST_SequenceBlk * query, + BlastQueryInfo * query_info, + LookupTableWrap * lookup_wrap, + const BlastInitialWordParameters * word_params, + const BlastScoringParameters* score_params, + const BlastHitSavingParameters* hit_params, + BlastOffsetPair * offset_pairs, + MapperWordHits* word_hits, + Int4 max_hits, + BlastGapAlignStruct* gap_align, + BlastInitHitList* init_hitlist, + BlastHSPList** hsp_list, + BlastUngappedStats* ungapped_stats, + BlastGappedStats* gapped_stats) +{ + BlastInitHSP * hsp, /* *new_hsp,*/ * hsp_end; + ir_diag_hash * hash = 0; + ir_hash_entry * e = 0; + Uint4 word_size; + Uint4 q_off, s_off; + Uint4 diag, key; + Int4 oid = subject->oid; + Int4 chunk = subject->chunk; + T_MB_IdbCheckOid check_oid = + (T_MB_IdbCheckOid)lookup_wrap->check_index_oid; + T_MB_IdbGetResults get_results = + (T_MB_IdbGetResults)lookup_wrap->read_indexed_db; + Int4 last_vol_idx = LAST_VOL_IDX_NULL; + + /* In the case oid belongs to the non-indexed part of the + database, route the call to the original word finder. + */ + if( check_oid( oid, &last_vol_idx ) == eNotIndexed ) { + return JumperNaWordFinder( + subject, query, query_info, lookup_wrap, word_params, + score_params, hit_params, offset_pairs, word_hits, max_hits, + gap_align, init_hitlist, hsp_list, ungapped_stats, + gapped_stats); + } + + ASSERT(get_results); + word_size = get_results(oid, chunk, init_hitlist); + + if (*hsp_list == NULL) { + *hsp_list = Blast_HSPListNew(BlastHspNumMax(TRUE, + hit_params->options)); + } + + if( word_size > 0) { + + hash = ir_hash_create(); + hsp = init_hitlist->init_hsp_array; + hsp_end = hsp + init_hitlist->total; + + for( ; hsp < hsp_end; ++hsp ) { + q_off = hsp->offsets.qs_offsets.q_off; + s_off = hsp->offsets.qs_offsets.s_off; + + + diag = IR_DIAG( q_off, s_off ); + key = IR_KEY( diag ); + e = IR_LOCATE( hash, diag, key ); + + if( e != 0 ) { + + + Int4 context = BSearchContextInfo(q_off, query_info); + Int4 query_start = query_info->contexts[context].query_offset; + Int4 query_len = query_info->contexts[context].query_length; + Uint1* query_seq = query->sequence + query_start; + + if( q_off + word_size - 1 > e->diag_data.qend ) { + + Int4 num_identical = 0; + Int4 right_ungapped_ext_len = 0; + gapped_stats->extensions++; + + JumperGappedAlignmentCompressedWithTraceback(query_seq, + subject->sequence, + query_len, + subject->length, + q_off - query_start, + s_off, + gap_align, + score_params, + &num_identical, + &right_ungapped_ext_len); + + + if (JumperGoodAlign(gap_align, hit_params, num_identical, + &query_info->contexts[context])) { + + BlastHSP* new_hsp; + int status; + + gap_align->edit_script = + JumperPrelimEditBlockToGapEditScript( + gap_align->jumper->left_prelim_block, + gap_align->jumper->right_prelim_block); + + status = Blast_HSPInit(gap_align->query_start, + gap_align->query_stop, + gap_align->subject_start, + gap_align->subject_stop, + q_off - query_start, s_off, + context, + query_info->contexts[context].frame, + subject->frame, + gap_align->score, + &(gap_align->edit_script), + &new_hsp); + if (!new_hsp) { + return -1; + } + new_hsp->map_info = BlastHSPMappingInfoNew(); + if (!new_hsp->map_info) { + return -1; + } + new_hsp->num_ident = num_identical; + new_hsp->evalue = 0.0; + new_hsp->map_info->edits = JumperFindEdits(query_seq, + subject->sequence, + gap_align); + + if (hit_params->options->splice) { + JumperFindSpliceSignals(new_hsp, query_len, + subject->sequence, + subject->length); + } + + status = Blast_HSPListSaveHSP(*hsp_list, new_hsp); + if (status) { + break; + } + } + + if (e->diag_data.diag != diag) { + e->diag_data.diag = diag; + } + e->diag_data.qend = q_off + right_ungapped_ext_len - 1; + + } + + + } +/* + else { + if( new_hsp != hsp ) *new_hsp = *hsp; + ++new_hsp; + } +*/ + } + + hash = ir_hash_destroy( hash ); + } + + return 0; +} + + diff --git a/c++/src/algo/blast/core/ncbi_math.c b/c++/src/algo/blast/core/ncbi_math.c index 157bef4f..74592fdf 100644 --- a/c++/src/algo/blast/core/ncbi_math.c +++ b/c++/src/algo/blast/core/ncbi_math.c @@ -1,4 +1,4 @@ -/* $Id: ncbi_math.c 351814 2012-02-01 17:14:10Z ucko $ +/* $Id: ncbi_math.c 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -28,11 +28,6 @@ * Definitions for portable math library */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: ncbi_math.c 351814 2012-02-01 17:14:10Z ucko $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include double BLAST_Expm1(double x) diff --git a/c++/src/algo/blast/core/ncbi_std.c b/c++/src/algo/blast/core/ncbi_std.c index 3f39bd38..acfc1b28 100644 --- a/c++/src/algo/blast/core/ncbi_std.c +++ b/c++/src/algo/blast/core/ncbi_std.c @@ -1,4 +1,4 @@ -/* $Id: ncbi_std.c 72729 2005-11-16 14:31:37Z madden $ +/* $Id: ncbi_std.c 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -29,11 +29,6 @@ * A few utilities needed by code in algo/blast/core but not provided elsewhere. */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: ncbi_std.c 72729 2005-11-16 14:31:37Z madden $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include /* for sfree() macro */ #include diff --git a/c++/src/algo/blast/core/pattern.c b/c++/src/algo/blast/core/pattern.c index 8e579713..4d4b2acf 100644 --- a/c++/src/algo/blast/core/pattern.c +++ b/c++/src/algo/blast/core/pattern.c @@ -1,4 +1,4 @@ -/* $Id: pattern.c 134303 2008-07-17 17:42:49Z camacho $ +/* $Id: pattern.c 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -54,11 +54,6 @@ * */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: pattern.c 134303 2008-07-17 17:42:49Z camacho $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include "pattern_priv.h" diff --git a/c++/src/algo/blast/core/phi_extend.c b/c++/src/algo/blast/core/phi_extend.c index 9436a2a3..4b633631 100644 --- a/c++/src/algo/blast/core/phi_extend.c +++ b/c++/src/algo/blast/core/phi_extend.c @@ -1,4 +1,4 @@ -/* $Id: phi_extend.c 94064 2006-11-21 17:19:42Z papadopo $ +/* $Id: phi_extend.c 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -31,11 +31,6 @@ * Word finder functions for PHI-BLAST */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: phi_extend.c 94064 2006-11-21 17:19:42Z papadopo $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include diff --git a/c++/src/algo/blast/core/phi_gapalign.c b/c++/src/algo/blast/core/phi_gapalign.c index cc6a2f47..81a5df58 100644 --- a/c++/src/algo/blast/core/phi_gapalign.c +++ b/c++/src/algo/blast/core/phi_gapalign.c @@ -1,4 +1,4 @@ -/* $Id: phi_gapalign.c 134303 2008-07-17 17:42:49Z camacho $ +/* $Id: phi_gapalign.c 505944 2016-06-30 12:29:20Z madden $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -53,11 +53,6 @@ * */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: phi_gapalign.c 134303 2008-07-17 17:42:49Z camacho $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include @@ -861,7 +856,6 @@ Int2 PHIGappedAlignmentWithTraceback(Uint1* query, Uint1* subject, GapPrelimEditBlockReset(rev_prelim_tback); found_end = FALSE; - score_left = 0; score_left = Blast_SemiGappedAlign(query, subject, q_start, s_start, diff --git a/c++/src/algo/blast/core/phi_lookup.c b/c++/src/algo/blast/core/phi_lookup.c index ae380698..500f1bbd 100644 --- a/c++/src/algo/blast/core/phi_lookup.c +++ b/c++/src/algo/blast/core/phi_lookup.c @@ -1,4 +1,4 @@ -/* $Id: phi_lookup.c 94060 2006-11-21 17:14:28Z papadopo $ +/* $Id: phi_lookup.c 505944 2016-06-30 12:29:20Z madden $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -32,11 +32,6 @@ * @todo FIXME needs doxygen comments and lines shorter than 80 characters */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: phi_lookup.c 94060 2006-11-21 17:14:28Z papadopo $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include /* for NCBI2NA_UNPACK_BASE */ @@ -439,7 +434,6 @@ SPHIPatternSearchBlkNew(char* pattern_in, Boolean is_dna, BlastScoreBlk* sbp, wildcardProduct = 1; currentWildcardProduct = 1; - prevSetMask = 0; currentSetMask = 0; pattern_length = strlen(pattern_in); diff --git a/c++/src/algo/blast/core/split_query.c b/c++/src/algo/blast/core/split_query.c index 1593392d..b702251d 100644 --- a/c++/src/algo/blast/core/split_query.c +++ b/c++/src/algo/blast/core/split_query.c @@ -1,4 +1,4 @@ -/* $Id: split_query.c 195768 2010-06-25 17:12:38Z maning $ +/* $Id: split_query.c 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -30,11 +30,6 @@ /** @file split_query.c */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: split_query.c 195768 2010-06-25 17:12:38Z maning $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include /* needed for sfree */ #include "blast_dynarray.h" diff --git a/c++/src/algo/blast/dbindex/dbindex_factory.cpp b/c++/src/algo/blast/dbindex/dbindex_factory.cpp index a616bb59..88101745 100644 --- a/c++/src/algo/blast/dbindex/dbindex_factory.cpp +++ b/c++/src/algo/blast/dbindex/dbindex_factory.cpp @@ -1,4 +1,4 @@ -/* $Id: dbindex_factory.cpp 412159 2013-09-04 21:12:36Z ucko $ +/* $Id: dbindex_factory.cpp 506382 2016-07-07 13:47:26Z morgulis $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -997,7 +997,6 @@ class COffsetList class CDataPool { static const Uint4 BLOCK_SIZE = 1024*1024ULL; - static const Uint4 BLOCKS_RESERVE = 10*1024ULL; typedef vector< SDataUnit > TBlock; typedef vector< TBlock > TBlocks; @@ -1006,7 +1005,6 @@ class COffsetList CDataPool() : free_( 0 ) { - pool_.reserve( BLOCKS_RESERVE ); new_block(); } @@ -1053,6 +1051,8 @@ class COffsetList TBlocks pool_; }; + void SetDataPool( CDataPool * pool ) { data_.SetDataPool( pool ); } + private: class CData @@ -1140,9 +1140,12 @@ class COffsetList typedef CDataIterator const_iterator; typedef Uint4 size_type; - CData() : start_( 0 ), curr_( 0 ), last_( 0 ), size_( 0 ) + CData() : pool_( 0 ), + start_( 0 ), curr_( 0 ), last_( 0 ), size_( 0 ) {} + void SetDataPool( CDataPool * pool ) { pool_ = pool; } + const_iterator begin() const { return const_iterator( start_, 1, size_ ); } @@ -1155,14 +1158,14 @@ class COffsetList void push_back( const TWord & d ) { if( start_ == 0 ) { - start_ = curr_ = Pool_.alloc(); + start_ = curr_ = pool_->alloc(); start_->next = 0; } curr_->data[last_++] = d; if( last_ >= DATA_UNIT_SIZE ) { - SDataUnit * t = Pool_.alloc(); + SDataUnit * t = pool_->alloc(); t->next = 0; curr_->next = t; curr_ = t; @@ -1175,7 +1178,7 @@ class COffsetList void resize( Uint4 newsize ) { if( newsize == 0 ) { - Pool_.free( start_ ); + pool_->free( start_ ); start_ = curr_ = 0; size_ = last_ = 0; return; @@ -1191,17 +1194,15 @@ class COffsetList tn = tp->next; } - Pool_.free( tn ); + pool_->free( tn ); curr_ = tp; last_ = DATA_UNIT_SIZE - (t - newsize) - 1; size_ = newsize; } - static void Clear() { Pool_.clear(); } - private: - static CDataPool Pool_; + CDataPool * pool_; SDataUnit * start_; SDataUnit * curr_; @@ -1215,14 +1216,8 @@ class COffsetList TData data_; /**< Offset list data storage. */ unsigned long min_offset_; /**< Minimum offset used by the index. */ unsigned long mult_; /**< Max multiple to use in list pre-ordering. */ - - public: - - static void ClearAll() { TData::Clear(); } }; -COffsetList::CDataPool COffsetList::CData::Pool_; - //------------------------------------------------------------------------- inline void COffsetList::Save( CNcbiOstream & os) const { @@ -1307,7 +1302,8 @@ class COffsetData_Factory */ COffsetData_Factory( TSubjectMap & subject_map, - const CDbIndex::SOptions & options ) + const CDbIndex::SOptions & options, + COffsetList::CDataPool * pool ) : subject_map_( subject_map ), hash_table_( 1<<(2*options.hkey_width) ), report_level_( options.report_level ), @@ -1320,11 +1316,10 @@ class COffsetData_Factory for( THashTable::iterator i = hash_table_.begin(); i != hash_table_.end(); ++i ) { i->SetIndexParams( options_ ); + i->SetDataPool( pool ); } } - ~COffsetData_Factory() { COffsetList::ClearAll(); } - /** Get the total memory usage by offset lists in bytes. @return memory usage by this instance */ @@ -1669,8 +1664,11 @@ void CDbIndex_Factory::do_create_1_2( typedef CSubjectMap_Factory TSubjectMap; typedef COffsetData_Factory TOffsetData; + std::auto_ptr< COffsetList::CDataPool > pool( + new COffsetList::CDataPool ); + TSubjectMap subject_map( options ); - TOffsetData offset_data( subject_map, options ); + TOffsetData offset_data( subject_map, options, pool.get() ); TSeqNum i = start; diff --git a/c++/src/algo/blast/dbindex/makeindex/main.cpp b/c++/src/algo/blast/dbindex/makeindex/main.cpp index ecf1a545..7e532287 100644 --- a/c++/src/algo/blast/dbindex/makeindex/main.cpp +++ b/c++/src/algo/blast/dbindex/makeindex/main.cpp @@ -1,4 +1,4 @@ -/* $Id: main.cpp 473030 2015-07-15 19:29:59Z camacho $ +/* $Id: main.cpp 492284 2016-02-16 16:55:37Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -50,5 +50,5 @@ USING_NCBI_SCOPE; int main( int argc, char * argv[] ) { - return CMkIndexApplication().AppMain(argc, argv, 0, eDS_Default, ""); + return CMkIndexApplication().AppMain(argc, argv); } diff --git a/c++/src/algo/blast/format/blast_format.cpp b/c++/src/algo/blast/format/blast_format.cpp index 1721377d..774c14b7 100644 --- a/c++/src/algo/blast/format/blast_format.cpp +++ b/c++/src/algo/blast/format/blast_format.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = "$Id: blast_format.cpp 495288 2016-03-16 14:51:11Z ivanov $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - /* * =========================================================================== * @@ -43,6 +39,7 @@ Author: Jason Papadopoulos #include #include #include +#include #include #include // for FindBestChoice #include @@ -62,6 +59,7 @@ USING_NCBI_SCOPE; USING_SCOPE(blast); USING_SCOPE(objects); USING_SCOPE(align_format); +USING_SCOPE(sequence); #endif @@ -183,6 +181,12 @@ CBlastFormat::CBlastFormat(const blast::CBlastOptions& options, if (m_FormatType == CFormattingArgs::eSAM) { x_InitSAMFormatter(); } + + CNcbiApplication* app = CNcbiApplication::Instance(); + if (app) { + const CNcbiRegistry& registry = app->GetConfig(); + m_LongSeqId = (registry.Get("BLAST", "LONG_SEQID") == "1"); + } } CBlastFormat::CBlastFormat(const blast::CBlastOptions& opts, @@ -284,6 +288,12 @@ CBlastFormat::CBlastFormat(const blast::CBlastOptions& opts, if (m_FormatType == CFormattingArgs::eSAM) { x_InitSAMFormatter(); } + + CNcbiApplication* app = CNcbiApplication::Instance(); + if (app) { + const CNcbiRegistry& registry = app->GetConfig(); + m_LongSeqId = (registry.Get("BLAST", "LONG_SEQID") == "1"); + } } CBlastFormat::~CBlastFormat() @@ -473,6 +483,9 @@ CBlastFormat::x_ConfigCShowBlastDefline(CShowBlastDefline& showdef, flags |= CShowBlastDefline::eShowGi; if (num_descriptions_to_show == 0) flags |= CShowBlastDefline::eNoShowHeader; + if (m_LongSeqId) { + flags |= CShowBlastDefline::eLongSeqId; + } showdef.SetOption(flags); showdef.SetDbName(m_DbName); @@ -783,8 +796,74 @@ CBlastFormat::x_PrintTabularReport(const blast::CSearchResults& results, } } +static void s_SetCloneInfo(const CIgBlastTabularInfo& tabinfo, + const CBioseq_Handle& handle, + CBlastFormat::SClone& clone_info) { + + if (handle.GetSeqId()->Which() == CSeq_id::e_Local){ + CDeflineGenerator defline (handle.GetSeq_entry_Handle()); + clone_info.seqid = defline.GenerateDefline(handle).substr(0, 45); + + // clone_info.seqid = CDeflineGenerator.substr(0, 45); + } else { + string seqid; + CRef wid = FindBestChoice(handle.GetBioseqCore()->GetId(), CSeq_id::WorstRank); + wid->GetLabel(&seqid, CSeq_id::eContent); + clone_info.seqid = seqid.substr(0, 45); + } + tabinfo.GetIgInfo (clone_info.v_gene, clone_info.d_gene, clone_info.j_gene, + clone_info.chain_type, clone_info.na, clone_info.aa, clone_info.productive); + clone_info.identity = 0; + const vector& domains = tabinfo.GetIgDomains(); + int length = 0; + int num_match = 0; + for (unsigned int i=0; ilength > 0) { + length += domains[i]->length; + num_match += domains[i]->num_match; + } + } + if (length > 0){ + clone_info.identity = ((double)num_match)/length; + + } + +} + void -CBlastFormat::x_PrintIgTabularReport(const blast::CIgBlastResults& results) +CBlastFormat::x_PrintTaxReport(const blast::CSearchResults& results) +{ + CBioseq_Handle bhandle = m_Scope->GetBioseqHandle(*results.GetSeqId(), + CScope::eGetBioseq_All); + CConstRef bioseq = bhandle.GetBioseqCore(); + if(m_IsHTML) { + m_Outfile << "
";
+    }
+    else {
+        m_Outfile <<  "\n";
+    }
+    CBlastFormatUtil::AcknowledgeBlastQuery(*bioseq, kFormatLineLength,
+                                            m_Outfile, m_BelieveQuery,
+                                            m_IsHTML, false,
+                                            results.GetRID());
+
+    if(m_IsHTML) {
+        m_Outfile <<  "
"; + } + CConstRef aln_set = results.GetSeqAlign(); + if (m_IsUngappedSearch && results.HasAlignments()) { + aln_set.Reset(CDisplaySeqalign::PrepareBlastUngappedSeqalign(*aln_set)); + } + + CRef new_aln_set(const_cast(aln_set.GetPointer())); + CTaxFormat *taxFormatRes = new CTaxFormat (*new_aln_set,*m_Scope,m_IsHTML ? CTaxFormat::eHtml:CTaxFormat::eText, false,max(kMinTaxFormatLineLength,kFormatLineLength)); + taxFormatRes->DisplayOrgReport(m_Outfile); +} + +void +CBlastFormat::x_PrintIgTabularReport(const blast::CIgBlastResults& results, + SClone& clone_info, + bool fill_clone_info) { CConstRef aln_set = results.GetSeqAlign(); /* TODO do we support ungapped Igblast search? @@ -823,7 +902,9 @@ CBlastFormat::x_PrintIgTabularReport(const blast::CIgBlastResults& results) annots->m_ChainTypeToShow, &m_ScoringMatrix); tabinfo.SetIgAnnotation(annots, m_IgOptions); - + if (fill_clone_info) { + s_SetCloneInfo(tabinfo, bhandle, clone_info); + } tabinfo.PrintHeader(strProgVersion, *(bhandle.GetBioseqCore()), m_DbName, m_IgOptions->m_DomainSystem, @@ -999,6 +1080,13 @@ CBlastFormat::PrintOneResultSet(const blast::CSearchResults& results, x_PrintTabularReport(results, itr_num); return; } + if (m_FormatType == CFormattingArgs::eTaxFormat) { + string reportCaption = "Tax BLAST report"; + reportCaption = m_IsHTML ? "

" + reportCaption + "

" : CAlignFormatUtil::AddSpaces(reportCaption,max(kMinTaxFormatLineLength,kFormatLineLength),CAlignFormatUtil::eSpacePosToCenter | CAlignFormatUtil::eAddEOLAtLineStart | CAlignFormatUtil::eAddEOLAtLineEnd); + m_Outfile << reportCaption; + x_PrintTaxReport(results); + return; + } const bool kIsTabularOutput = false; if (is_deltablast_domain_result) { @@ -1027,6 +1115,7 @@ CBlastFormat::PrintOneResultSet(const blast::CSearchResults& results, m_Outfile, m_BelieveQuery, m_IsHTML, kIsTabularOutput, results.GetRID()); + if (m_IsBl2Seq && !m_IsDbScan) { m_Outfile << "\n"; // FIXME: this might be configurable in the future @@ -1081,10 +1170,16 @@ CBlastFormat::PrintOneResultSet(const blast::CSearchResults& results, display.SetDbName(m_DbName); display.SetDbType(!m_DbIsAA); display.SetLineLen(m_LineLength); + int kAlignToShow=2000000000; // Nice large number per SB-1817 + display.SetNumAlignToShow(kAlignToShow); // set the alignment flags display.SetAlignOption(flags); + if (m_LongSeqId) { + display.UseLongSequenceIds(); + } + if (m_Program == "blastn" || m_Program == "megablast") { display.SetMiddleLineStyle(CDisplaySeqalign::eBar); display.SetAlignType(CDisplaySeqalign::eNuc); @@ -1110,8 +1205,12 @@ CBlastFormat::PrintOneResultSet(const blast::CSearchResults& results, void CBlastFormat::PrintOneResultSet(blast::CIgBlastResults& results, CConstRef queries, + SClone& clone_info, + bool fill_clone_info, int index) { + clone_info.na = NcbiEmptyString; + clone_info.aa = NcbiEmptyString; // For remote searches, we don't retrieve the sequence data for the query // sequence when initially sending the request to the BLAST server (if it's @@ -1161,10 +1260,17 @@ CBlastFormat::PrintOneResultSet(blast::CIgBlastResults& results, m_FormatType == CFormattingArgs::eTabularWithComments || m_FormatType == CFormattingArgs::eCommaSeparatedValues) { m_FormatType = CFormattingArgs::eTabularWithComments; - x_PrintIgTabularReport(results); + x_PrintIgTabularReport(results, clone_info, fill_clone_info); return; } + if (m_FormatType == CFormattingArgs::eTaxFormat) { + string reportCaption = "Tax BLAST report"; + reportCaption = m_IsHTML ? "

" + reportCaption + "

" : CAlignFormatUtil::AddSpaces(reportCaption,max(kMinTaxFormatLineLength,kFormatLineLength),CAlignFormatUtil::eSpacePosToCenter | CAlignFormatUtil::eAddEOLAtLineStart | CAlignFormatUtil::eAddEOLAtLineEnd); + m_Outfile << reportCaption; + x_PrintTaxReport(results); + return; + } const bool kIsTabularOutput = false; @@ -1228,6 +1334,9 @@ CBlastFormat::PrintOneResultSet(blast::CIgBlastResults& results, annots->m_ChainTypeToShow, &m_ScoringMatrix); tabinfo.SetIgAnnotation(annots, m_IgOptions); + if (fill_clone_info) { + s_SetCloneInfo(tabinfo, bhandle, clone_info); + } m_Outfile << "Domain classification requested: " << m_IgOptions->m_DomainSystem << endl << endl; if (m_IsHTML) { tabinfo.PrintHtmlSummary(); @@ -1328,6 +1437,10 @@ CBlastFormat::PrintOneResultSet(blast::CIgBlastResults& results, display.SetDbType(!m_DbIsAA); display.SetLineLen(90); + if (m_LongSeqId) { + display.UseLongSequenceIds(); + } + if (annots->m_FrameInfo[0] >= 0 && m_IgOptions->m_Translate) { display.SetTranslatedFrameForLocalSeq((CDisplaySeqalign::TranslatedFrameForLocalSeq) (annots->m_FrameInfo[0]%3)); flags += CDisplaySeqalign::eShowTranslationForLocalSeq; @@ -1379,6 +1492,9 @@ CBlastFormat::PrintOneResultSet(blast::CIgBlastResults& results, void CBlastFormat::x_ReverseQuery(blast::CIgBlastResults& results) { + if (!results.HasAlignments()){ + return; + } // create a temporary seq_id CConstRef qid = results.GetSeqId(); string new_id = qid->AsFastaString() + "_reversed"; @@ -1486,6 +1602,15 @@ CBlastFormat::PrintPhiResult(const blast::CSearchResultSet& result_set, } return; } + if (m_FormatType == CFormattingArgs::eTaxFormat) { + string reportCaption = "Tax BLAST report"; + reportCaption = m_IsHTML ? "

" + reportCaption + "

" : CAlignFormatUtil::AddSpaces(reportCaption,max(kMinTaxFormatLineLength,kFormatLineLength),CAlignFormatUtil::eSpacePosToCenter | CAlignFormatUtil::eAddEOLAtLineStart | CAlignFormatUtil::eAddEOLAtLineEnd); + m_Outfile << reportCaption; + ITERATE(CSearchResultSet, result, result_set) { + x_PrintTaxReport(**result); + } + return; + } const CSearchResults& first_results = result_set[0]; @@ -1505,6 +1630,16 @@ CBlastFormat::PrintPhiResult(const blast::CSearchResultSet& result_set, m_IsHTML, false, first_results.GetRID()); + if (m_FormatType == CFormattingArgs::eTaxFormat) { + string reportCaption = "Tax BLAST report"; + reportCaption = m_IsHTML ? "

" + reportCaption + "

" : CAlignFormatUtil::AddSpaces(reportCaption,max(kMinTaxFormatLineLength,kFormatLineLength),CAlignFormatUtil::eSpacePosToCenter | CAlignFormatUtil::eAddEOLAtLineStart | CAlignFormatUtil::eAddEOLAtLineEnd); + m_Outfile << reportCaption; + ITERATE(CSearchResultSet, result, result_set) { + x_PrintTaxReport(**result); + } + return; + } + const SPHIQueryInfo *phi_query_info = first_results.GetPhiQueryInfo(); if (phi_query_info) @@ -1580,6 +1715,10 @@ CBlastFormat::PrintPhiResult(const blast::CSearchResultSet& result_set, // set the alignment flags display.SetAlignOption(flags); + if (m_LongSeqId) { + display.UseLongSequenceIds(); + } + if (m_Program == "blastn" || m_Program == "megablast") { display.SetMiddleLineStyle(CDisplaySeqalign::eBar); display.SetAlignType(CDisplaySeqalign::eNuc); diff --git a/c++/src/algo/blast/format/blastfmtutil.cpp b/c++/src/algo/blast/format/blastfmtutil.cpp index 90640845..c8abe654 100644 --- a/c++/src/algo/blast/format/blastfmtutil.cpp +++ b/c++/src/algo/blast/format/blastfmtutil.cpp @@ -1,4 +1,4 @@ -/* $Id: blastfmtutil.cpp 479455 2015-09-21 14:39:54Z fongah2 $ +/* $Id: blastfmtutil.cpp 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -29,11 +29,6 @@ * blast formatter utilities * */ - -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = "$Id: blastfmtutil.cpp 479455 2015-09-21 14:39:54Z fongah2 $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include @@ -100,7 +95,16 @@ CBlastFormatUtil::BlastPrintReference(bool html, size_t line_len, ostringstream str; if(html) { + CNcbiIfstream config_file(".ncbirc"); + CNcbiRegistry config_reg(config_file); + string httpProt = "https:"; + if(!config_reg.Empty()) { + if(config_reg.HasEntry("BLASTFMTUTIL","PROTOCOL")) { + httpProt = config_reg.Get("BLASTFMTUTIL","PROTOCOL"); + } + } str << "
" << reference << ":" << "\n"; diff --git a/c++/src/algo/blast/format/blastxml_format.cpp b/c++/src/algo/blast/format/blastxml_format.cpp index b1a1ea4c..50363ed0 100644 --- a/c++/src/algo/blast/format/blastxml_format.cpp +++ b/c++/src/algo/blast/format/blastxml_format.cpp @@ -1,4 +1,4 @@ -/* $Id: blastxml_format.cpp 401131 2013-05-28 18:34:25Z grichenk $ +/* $Id: blastxml_format.cpp 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -30,11 +30,6 @@ /// @file blastxml_format.cpp /// Formatting of BLAST results in XML form, using the BLAST XML specification. - -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = "$Id: blastxml_format.cpp 401131 2013-05-28 18:34:25Z grichenk $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include @@ -661,6 +656,7 @@ s_GetBlastPublication(EProgram program) switch (program) { case eMegablast: + case eMapper: publication = CReference::eMegaBlast; break; case ePHIBlastp: case ePHIBlastn: publication = CReference::ePhiBlast; break; diff --git a/c++/src/algo/blast/format/data4xmlformat.cpp b/c++/src/algo/blast/format/data4xmlformat.cpp index 4bc291f1..92b6e430 100644 --- a/c++/src/algo/blast/format/data4xmlformat.cpp +++ b/c++/src/algo/blast/format/data4xmlformat.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = "$Id: data4xmlformat.cpp 393164 2013-03-22 13:39:25Z fongah2 $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - /* * =========================================================================== * diff --git a/c++/src/algo/blast/format/sam.cpp b/c++/src/algo/blast/format/sam.cpp index 14f03bdd..45e46ca2 100644 --- a/c++/src/algo/blast/format/sam.cpp +++ b/c++/src/algo/blast/format/sam.cpp @@ -85,10 +85,13 @@ void CBlast_SAM_Formatter::x_ProcessCustomSpec(const string & custom_spec, const CSAM_Formatter::SProgramInfo & info) { vector format_tokens; - NStr::Tokenize(custom_spec, " ", format_tokens); + NStr::Split(custom_spec, " ", format_tokens); CSAM_Formatter::SetProgram(info); m_refRow = 1; ITERATE (vector, iter, format_tokens) { + if("SR" == *iter) { + m_refRow = 0; + } if ("SQ" == *iter) { CSAM_Formatter::SetFlag(CSAM_Formatter::fSAM_SeqData); } diff --git a/c++/src/algo/blast/format/vecscreen_run.cpp b/c++/src/algo/blast/format/vecscreen_run.cpp index cd5e58e6..2221dd00 100644 --- a/c++/src/algo/blast/format/vecscreen_run.cpp +++ b/c++/src/algo/blast/format/vecscreen_run.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = "$Id: vecscreen_run.cpp 384567 2012-12-28 04:20:22Z ucko $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - /* * =========================================================================== * diff --git a/c++/src/algo/blast/igblast/igblast.cpp b/c++/src/algo/blast/igblast/igblast.cpp index d0e1ddd6..8d9d1ba0 100644 --- a/c++/src/algo/blast/igblast/igblast.cpp +++ b/c++/src/algo/blast/igblast/igblast.cpp @@ -1,7 +1,3 @@ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: igblast.cpp 499246 2016-04-25 11:32:24Z ivanov $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ /* =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -133,13 +129,13 @@ CIgAnnotationInfo::CIgAnnotationInfo(CConstRef &ig_opt) } }; -void CIgBlast::x_ScreenV(CRef & results){ +void CIgBlast::x_ScreenByAlignLength(CRef & results, int length){ NON_CONST_ITERATE(CSearchResultSet, result, *results) { if ((*result)->HasAlignments()) { CSeq_align_set::Tdata & align_list = (*result)->SetSeqAlign()->Set(); CSeq_align_set::Tdata::iterator it = align_list.begin(); while (it != align_list.end()) { - if((*it)->GetAlignLength() - (*it)->GetTotalGapCount(0) < m_IgOptions->m_MinVLength){ + if((*it)->GetAlignLength() - (*it)->GetTotalGapCount(0) < length){ it = align_list.erase(it); } else { ++it; @@ -249,11 +245,12 @@ CIgBlast::Run() { x_SetupVSearch(qf, opts_hndl); CLocalBlast blast(qf, opts_hndl, m_IgOptions->m_Db[0]); + blast.SetNumberOfThreads(m_NumThreads); results[0] = blast.Run(); if (m_IgOptions->m_ExtendAlign){ x_ExtendAlign(results[0]); } - x_ScreenV(results[0]); + x_ScreenByAlignLength(results[0], m_IgOptions->m_MinVLength); x_ConvertResultType(results[0]); s_SortResultsByEvalue(results[0]); x_AnnotateV(results[0], annots); @@ -263,15 +260,19 @@ CIgBlast::Run() { opts_hndl->SetHitlistSize(20); // use a larger number to ensure annotation CLocalBlast blast(qf, opts_hndl, m_IgOptions->m_Db[3]); + blast.SetNumberOfThreads(m_NumThreads); results[3] = blast.Run(); if (m_IgOptions->m_ExtendAlign){ x_ExtendAlign(results[3]); } - x_ScreenV(results[3]); + x_ScreenByAlignLength(results[3], m_IgOptions->m_MinVLength); s_SortResultsByEvalue(results[3]); x_AnnotateDomain(results[0], results[3], annots); } + opts_hndl.Reset(CBlastOptionsFactory + ::Create((m_IgOptions->m_IsProtein)? eBlastp: eBlastn)); + /*** search DJ germline */ int num_genes = (m_IgOptions->m_IsProtein) ? 1 : 3; if (num_genes > 1) { @@ -280,7 +281,11 @@ CIgBlast::Run() x_SetupDJSearch(annots, qf, opts_hndl, gene); CLocalBlast blast(qf, opts_hndl, m_IgOptions->m_Db[gene]); try { + blast.SetNumberOfThreads(m_NumThreads); results[gene] = blast.Run(); + if (gene == 2){ + x_ScreenByAlignLength(results[gene], m_IgOptions->m_MinJLength); + } x_ConvertResultType(results[gene]); } catch(...) { num_genes = 1; @@ -332,7 +337,7 @@ CIgBlast::Run() x_SetChainType(final_results, annots); /*** attach annotation info back to the results */ - s_SetAnnotation(annots, final_results); + x_SetAnnotation(annots, final_results); return final_results; }; @@ -347,13 +352,13 @@ void CIgBlast::x_SetupVSearch(CRef &qf, int penalty = m_Options->GetOptions().GetMismatchPenalty(); opts.SetMatchReward(1); opts.SetMismatchPenalty(penalty); - opts.SetWordSize(9); + opts.SetWordSize(m_Options->GetOptions().GetWordSize()); if (penalty == -1) { opts.SetGapOpeningCost(4); opts.SetGapExtensionCost(1); } } - opts_hndl->SetEvalueThreshold(20.0); + opts_hndl->SetEvalueThreshold(m_Options->GetOptions().GetEvalueThreshold()); opts_hndl->SetFilterString("F"); opts_hndl->SetHitlistSize(15+ m_IgOptions->m_NumAlign[0]); qf.Reset(new CObjMgr_QueryFactory(*m_Query)); @@ -541,7 +546,14 @@ static bool s_CompareSeqAlignByEvalue(const CRef &x, int dx, dy; dx = x->GetAlignLength(); dy = y->GetAlignLength(); - return (ix*dy >= iy*dx); + if (ix*dy != iy*dx) { + return (ix*dy >= iy*dx); + } + string x_id = NcbiEmptyString; + string y_id = NcbiEmptyString; + x->GetSeq_id(1).GetLabel(&x_id, CSeq_id::eContent); + y->GetSeq_id(1).GetLabel(&y_id, CSeq_id::eContent); + return (x_id < y_id); }; // Compare two seqaligns according to their evalue and coverage @@ -556,6 +568,29 @@ static bool s_CompareSeqAlignByScore(const CRef &x, const CRef &x, const CRef &y) +{ + int sx, sy; + x->GetNamedScore(CSeq_align::eScore_Score, sx); + y->GetNamedScore(CSeq_align::eScore_Score, sy); + if (sx != sy) return (sx > sy); + x->GetNamedScore(CSeq_align::eScore_IdentityCount, sx); + y->GetNamedScore(CSeq_align::eScore_IdentityCount, sy); + if (sx != sy) { + return (sx <= sy); + } + + string x_id = NcbiEmptyString; + string y_id = NcbiEmptyString; + x->GetSeq_id(1).GetLabel(&x_id, CSeq_id::eContent); + y->GetSeq_id(1).GetLabel(&y_id, CSeq_id::eContent); + return (x_id < y_id); + +}; + + // Test if D and J annotation not compatible static bool s_DJNotCompatible(const CSeq_align &d, const CSeq_align &j, bool ms, int margin) { @@ -710,7 +745,7 @@ void CIgBlast::x_FindDJAln(CRef& align_D, else ++it; } /* sort according to score */ - align_list.sort(s_CompareSeqAlignByScore); + align_list.sort(s_CompareSeqAlignByScoreAndName); } /* preprocess J */ @@ -759,7 +794,7 @@ void CIgBlast::x_FindDJAln(CRef& align_D, else ++it; } /* sort according to score */ - align_list.sort(s_CompareSeqAlignByScore); + align_list.sort(s_CompareSeqAlignByScoreAndName); } /* which one to keep, D or J? */ @@ -1336,15 +1371,20 @@ void CIgBlast::s_AppendResults(CRef &results, } }; -void CIgBlast::s_SetAnnotation(vector > &annots, +void CIgBlast::x_SetAnnotation(vector > &annots, CRef &final_results) { int iq = 0; - ITERATE(CSearchResultSet, result, *final_results) { + NON_CONST_ITERATE(CSearchResultSet, result, *final_results) { CIgBlastResults *ig_result = dynamic_cast - (const_cast(&**result)); + (const_cast(&**result)); CIgAnnotation *annot = &*(annots[iq++]); ig_result->SetIgAnnotation().Reset(annot); + if (annot->m_GeneInfo[4] < 0 && m_IgOptions->m_MinJLength > 0) { //no J + if ((*result)->HasAlignments()){ + (*result)->SetSeqAlign()->Set().clear(); + } + } } }; diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.aalookup_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.aalookup_unit_test.app index 8f74aeee..0e070454 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.aalookup_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.aalookup_unit_test.app @@ -1,4 +1,4 @@ -# $Id: Makefile.aalookup_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.aalookup_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = aalookup_unit_test SRC = aalookup_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.aascan_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.aascan_unit_test.app index 6842eaee..b792c4f4 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.aascan_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.aascan_unit_test.app @@ -1,4 +1,4 @@ -# $Id: Makefile.aascan_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.aascan_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = aascan_unit_test SRC = aascan_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.bl2seq_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.bl2seq_unit_test.app index b754de4d..258b96c3 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.bl2seq_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.bl2seq_unit_test.app @@ -1,10 +1,10 @@ -# $Id: Makefile.bl2seq_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.bl2seq_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = bl2seq_unit_test SRC = bl2seq_unit_test CPPFLAGS = -DNCBI_MODULE=BLAST $(ORIG_CPPFLAGS) $(BOOST_INCLUDE) -LIB = blast_unit_test_util test_boost $(BLAST_INPUT_LIBS) ncbi_xloader_blastdb_rmt \ +LIB = blast_unit_test_util test_boost $(BLAST_INPUT_LIBS) \ $(BLAST_LIBS) xobjsimple $(OBJMGR_LIBS:ncbi_x%=ncbi_x%$(DLL)) LIBS = $(NETWORK_LIBS) $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.blast_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.blast_unit_test.app index da21ad2e..045ae44f 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.blast_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.blast_unit_test.app @@ -1,10 +1,10 @@ -# $Id: Makefile.blast_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.blast_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = blast_unit_test SRC = blast_unit_test CPPFLAGS = -DNCBI_MODULE=BLAST $(ORIG_CPPFLAGS) $(BOOST_INCLUDE) -LIB = blast_unit_test_util test_boost $(BLAST_INPUT_LIBS) ncbi_xloader_blastdb_rmt \ +LIB = blast_unit_test_util test_boost $(BLAST_INPUT_LIBS) \ $(BLAST_LIBS) xobjsimple $(OBJMGR_LIBS:ncbi_x%=ncbi_x%$(DLL)) LIBS = $(NETWORK_LIBS) $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.blast_unit_test_util.lib b/c++/src/algo/blast/unit_tests/api/Makefile.blast_unit_test_util.lib index 2392dd6b..37d4d837 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.blast_unit_test_util.lib +++ b/c++/src/algo/blast/unit_tests/api/Makefile.blast_unit_test_util.lib @@ -1,4 +1,4 @@ -# $Id: Makefile.blast_unit_test_util.lib 454210 2014-12-11 18:20:43Z camacho $ +# $Id: Makefile.blast_unit_test_util.lib 505858 2016-06-29 16:55:21Z elisovdn $ WATCHERS = camacho madden fongah2 diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.blastdiag_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.blastdiag_unit_test.app index dc622a33..ca946608 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.blastdiag_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.blastdiag_unit_test.app @@ -1,4 +1,4 @@ -# $Id: Makefile.blastdiag_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.blastdiag_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = blastdiag_unit_test SRC = blastdiag_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.blastengine_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.blastengine_unit_test.app index 2d7280ea..309aa85e 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.blastengine_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.blastengine_unit_test.app @@ -1,4 +1,4 @@ -# $Id: Makefile.blastengine_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.blastengine_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = blastengine_unit_test SRC = blastengine_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.blastextend_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.blastextend_unit_test.app index 9a147be5..b5978934 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.blastextend_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.blastextend_unit_test.app @@ -1,4 +1,4 @@ -# $Id: Makefile.blastextend_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.blastextend_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = blastextend_unit_test SRC = blastextend_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.blastfilter_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.blastfilter_unit_test.app index f175ec08..c2025de9 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.blastfilter_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.blastfilter_unit_test.app @@ -1,4 +1,4 @@ -# $Id: Makefile.blastfilter_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.blastfilter_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = blastfilter_unit_test SRC = blastfilter_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.blasthits_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.blasthits_unit_test.app index fdfd972c..9fdcea6e 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.blasthits_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.blasthits_unit_test.app @@ -1,4 +1,4 @@ -# $Id: Makefile.blasthits_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.blasthits_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = blasthits_unit_test SRC = blasthits_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.blastoptions_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.blastoptions_unit_test.app index 7bc65762..68337436 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.blastoptions_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.blastoptions_unit_test.app @@ -1,4 +1,4 @@ -# $Id: Makefile.blastoptions_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.blastoptions_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = blastoptions_unit_test SRC = blastoptions_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.blastsetup_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.blastsetup_unit_test.app index 242fd233..52c4680c 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.blastsetup_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.blastsetup_unit_test.app @@ -1,4 +1,4 @@ -# $Id: Makefile.blastsetup_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.blastsetup_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = blastsetup_unit_test SRC = blastsetup_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.delta_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.delta_unit_test.app index 7d9234cc..4c801d5b 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.delta_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.delta_unit_test.app @@ -1,4 +1,4 @@ -# $Id: Makefile.delta_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.delta_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = delta_unit_test SRC = delta_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.gapinfo_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.gapinfo_unit_test.app index 21ee6bf6..d8af43d2 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.gapinfo_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.gapinfo_unit_test.app @@ -1,4 +1,4 @@ -# $Id: Makefile.gapinfo_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.gapinfo_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = gapinfo_unit_test SRC = gapinfo_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.gencode_singleton_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.gencode_singleton_unit_test.app index 83ee07b4..d782c5a1 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.gencode_singleton_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.gencode_singleton_unit_test.app @@ -1,4 +1,4 @@ -# $Id: Makefile.gencode_singleton_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.gencode_singleton_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = gencode_singleton_unit_test SRC = gencode_singleton_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.hspfilter_besthit_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.hspfilter_besthit_unit_test.app index 247b2681..15971fe3 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.hspfilter_besthit_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.hspfilter_besthit_unit_test.app @@ -1,11 +1,11 @@ -# $Id: Makefile.hspfilter_besthit_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.hspfilter_besthit_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = hspfilter_besthit_unit_test SRC = hspfilter_besthit_unit_test CPPFLAGS = -DNCBI_MODULE=BLAST $(ORIG_CPPFLAGS) $(BOOST_INCLUDE) LIB = test_boost $(BLAST_LIBS) xobjsimple $(OBJMGR_LIBS:ncbi_x%=ncbi_x%$(DLL)) -LIBS = $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) +LIBS = $(NETWORK_LIBS) $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) CHECK_REQUIRES = MT in-house-resources CHECK_CMD = hspfilter_besthit_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.hspfilter_culling_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.hspfilter_culling_unit_test.app index 817a5ef3..1e58bc51 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.hspfilter_culling_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.hspfilter_culling_unit_test.app @@ -1,11 +1,11 @@ -# $Id: Makefile.hspfilter_culling_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.hspfilter_culling_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = hspfilter_culling_unit_test SRC = hspfilter_culling_unit_test CPPFLAGS = -DNCBI_MODULE=BLAST $(ORIG_CPPFLAGS) $(BOOST_INCLUDE) LIB = test_boost $(BLAST_LIBS) xobjsimple $(OBJMGR_LIBS:ncbi_x%=ncbi_x%$(DLL)) -LIBS = $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) +LIBS = $(NETWORK_LIBS) $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) CHECK_REQUIRES = MT in-house-resources CHECK_CMD = hspfilter_culling_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.hspstream_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.hspstream_unit_test.app index c3e314d8..3cd0537d 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.hspstream_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.hspstream_unit_test.app @@ -1,11 +1,11 @@ -# $Id: Makefile.hspstream_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.hspstream_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = hspstream_unit_test SRC = hspstream_unit_test hspstream_test_util CPPFLAGS = -DNCBI_MODULE=BLAST $(ORIG_CPPFLAGS) $(BOOST_INCLUDE) LIB = test_boost $(BLAST_LIBS) xobjsimple $(OBJMGR_LIBS:ncbi_x%=ncbi_x%$(DLL)) -LIBS = $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) +LIBS = $(NETWORK_LIBS) $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) CHECK_REQUIRES = MT in-house-resources CHECK_CMD = hspstream_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.in b/c++/src/algo/blast/unit_tests/api/Makefile.in index 5b7ae8ac..9be6ba84 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.in +++ b/c++/src/algo/blast/unit_tests/api/Makefile.in @@ -1,4 +1,4 @@ -# $Id: Makefile.in 498724 2016-04-19 13:36:57Z ivanov $ +# $Id: Makefile.in 505606 2016-06-27 18:14:44Z boratyng $ LIB_PROJ = blast_unit_test_util seqalign_util @@ -47,7 +47,8 @@ blastfilter_unit_test \ blastoptions_unit_test \ gencode_singleton_unit_test \ bl2seq_unit_test \ -stat_unit_test +stat_unit_test \ +magicblast_unit_test REQUIRES = Boost.Test.Included @@ -151,3 +152,5 @@ bl2seq_unit_test: lib ${MAKE} ${MFLAGS} -f Makefile.bl2seq_unit_test_app stat_unit_test: lib ${MAKE} ${MFLAGS} -f Makefile.stat_unit_test_app +magicblast_unit_test: + ${MAKE} ${MFLAGS} -f Makefile.magicblast_unit_test_app diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.linkhsp_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.linkhsp_unit_test.app index 92f3c0ea..5dbe3a1b 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.linkhsp_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.linkhsp_unit_test.app @@ -1,11 +1,11 @@ -# $Id: Makefile.linkhsp_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.linkhsp_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = linkhsp_unit_test SRC = linkhsp_unit_test CPPFLAGS = -DNCBI_MODULE=BLAST $(ORIG_CPPFLAGS) $(BOOST_INCLUDE) -I$(srcdir)/../../api LIB = blast_unit_test_util test_boost $(BLAST_LIBS) xobjsimple $(OBJMGR_LIBS:ncbi_x%=ncbi_x%$(DLL)) -LIBS = $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) +LIBS = $(NETWORK_LIBS) $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) CHECK_REQUIRES = MT in-house-resources CHECK_CMD = linkhsp_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.magicblast_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.magicblast_unit_test.app new file mode 100644 index 00000000..7a8dd07d --- /dev/null +++ b/c++/src/algo/blast/unit_tests/api/Makefile.magicblast_unit_test.app @@ -0,0 +1,16 @@ +# $Id: Makefile.magicblast_unit_test.app 507273 2016-07-18 13:56:27Z boratyng $ + +APP = magicblast_unit_test +SRC = magicblast_unit_test + +CPPFLAGS = -DNCBI_MODULE=BLAST $(ORIG_CPPFLAGS) $(BOOST_INCLUDE) +LIB = test_boost $(BLAST_INPUT_LIBS) \ + $(BLAST_LIBS) xobjsimple $(OBJMGR_LIBS:ncbi_x%=ncbi_x%$(DLL)) + +LIBS = $(NETWORK_LIBS) $(CMPRS_LIBS) $(ORIG_LIBS) + +CHECK_REQUIRES = MT in-house-resources +CHECK_CMD = magicblast_unit_test +CHECK_COPY = data magicblast_unit_test.ini + +WATCHERS = boratyng diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.msa2pssm_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.msa2pssm_unit_test.app index 95d5a5ba..4d9a68c5 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.msa2pssm_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.msa2pssm_unit_test.app @@ -1,11 +1,11 @@ -# $Id: Makefile.msa2pssm_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.msa2pssm_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = msa2pssm_unit_test SRC = msa2pssm_unit_test CPPFLAGS = -DNCBI_MODULE=BLAST $(ORIG_CPPFLAGS) $(BOOST_INCLUDE) LIB = test_boost $(BLAST_LIBS) xobjsimple $(OBJMGR_LIBS:ncbi_x%=ncbi_x%$(DLL)) -LIBS = $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) +LIBS = $(NETWORK_LIBS) $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) CHECK_REQUIRES = MT in-house-resources CHECK_CMD = msa2pssm_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.ntlookup_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.ntlookup_unit_test.app index f36b5bca..e13d2f43 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.ntlookup_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.ntlookup_unit_test.app @@ -1,14 +1,14 @@ -# $Id: Makefile.ntlookup_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.ntlookup_unit_test.app 507273 2016-07-18 13:56:27Z boratyng $ APP = ntlookup_unit_test SRC = ntlookup_unit_test CPPFLAGS = -DNCBI_MODULE=BLAST $(ORIG_CPPFLAGS) $(BOOST_INCLUDE) -I$(srcdir)/../../api LIB = blast_unit_test_util test_boost $(BLAST_LIBS) xobjsimple $(OBJMGR_LIBS:ncbi_x%=ncbi_x%$(DLL)) -LIBS = $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) +LIBS = $(NETWORK_LIBS) $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) CHECK_REQUIRES = MT in-house-resources CHECK_CMD = ntlookup_unit_test -CHECK_COPY = ntlookup_unit_test.ini +CHECK_COPY = data ntlookup_unit_test.ini WATCHERS = boratyng morgulis madden camacho fongah2 diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.ntscan_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.ntscan_unit_test.app index d7a1ef1b..6e61f35c 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.ntscan_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.ntscan_unit_test.app @@ -1,4 +1,4 @@ -# $Id: Makefile.ntscan_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.ntscan_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = ntscan_unit_test SRC = ntscan_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.optionshandle_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.optionshandle_unit_test.app index d7ac7b83..629348c9 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.optionshandle_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.optionshandle_unit_test.app @@ -1,11 +1,11 @@ -# $Id: Makefile.optionshandle_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.optionshandle_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = optionshandle_unit_test SRC = optionshandle_unit_test CPPFLAGS = -DNCBI_MODULE=BLAST $(ORIG_CPPFLAGS) $(BOOST_INCLUDE) LIB = test_boost $(BLAST_LIBS) xobjsimple $(OBJMGR_LIBS:ncbi_x%=ncbi_x%$(DLL)) -LIBS = $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) +LIBS = $(NETWORK_LIBS) $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) CHECK_REQUIRES = MT in-house-resources CHECK_CMD = optionshandle_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.phiblast_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.phiblast_unit_test.app index 3d55f562..39d995bf 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.phiblast_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.phiblast_unit_test.app @@ -1,11 +1,11 @@ -# $Id: Makefile.phiblast_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.phiblast_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = phiblast_unit_test SRC = phiblast_unit_test CPPFLAGS = -DNCBI_MODULE=BLAST $(ORIG_CPPFLAGS) $(BOOST_INCLUDE) -I$(srcdir)/../../api LIB = test_boost $(BLAST_LIBS) xobjsimple $(OBJMGR_LIBS:ncbi_x%=ncbi_x%$(DLL)) -LIBS = $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) +LIBS = $(NETWORK_LIBS) $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) CHECK_REQUIRES = MT in-house-resources CHECK_CMD = phiblast_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.prelimsearch_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.prelimsearch_unit_test.app index 84bb066e..65b1bd3b 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.prelimsearch_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.prelimsearch_unit_test.app @@ -1,4 +1,4 @@ -# $Id: Makefile.prelimsearch_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.prelimsearch_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = prelimsearch_unit_test SRC = prelimsearch_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.psibl2seq_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.psibl2seq_unit_test.app index 4d208242..7773a8fb 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.psibl2seq_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.psibl2seq_unit_test.app @@ -1,11 +1,11 @@ -# $Id: Makefile.psibl2seq_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.psibl2seq_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = psibl2seq_unit_test SRC = psibl2seq_unit_test CPPFLAGS = -DNCBI_MODULE=BLAST $(ORIG_CPPFLAGS) $(BOOST_INCLUDE) -I$(srcdir)/../../api LIB = test_boost $(BLAST_LIBS) xobjsimple $(OBJMGR_LIBS:ncbi_x%=ncbi_x%$(DLL)) -LIBS = $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) +LIBS = $(NETWORK_LIBS) $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) CHECK_REQUIRES = MT in-house-resources CHECK_CMD = psibl2seq_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.psiblast_iteration_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.psiblast_iteration_unit_test.app index 01106e4f..73e456a8 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.psiblast_iteration_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.psiblast_iteration_unit_test.app @@ -1,11 +1,11 @@ -# $Id: Makefile.psiblast_iteration_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.psiblast_iteration_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = psiblast_iteration_unit_test SRC = psiblast_iteration_unit_test CPPFLAGS = -DNCBI_MODULE=BLAST $(ORIG_CPPFLAGS) $(BOOST_INCLUDE) -I$(srcdir)/../../api LIB = test_boost $(BLAST_LIBS) xobjsimple $(OBJMGR_LIBS:ncbi_x%=ncbi_x%$(DLL)) -LIBS = $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) +LIBS = $(NETWORK_LIBS) $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) CHECK_REQUIRES = MT in-house-resources CHECK_CMD = psiblast_iteration_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.psiblast_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.psiblast_unit_test.app index d94e8f07..47fea7f9 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.psiblast_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.psiblast_unit_test.app @@ -1,10 +1,10 @@ -# $Id: Makefile.psiblast_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.psiblast_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = psiblast_unit_test SRC = psiblast_unit_test CPPFLAGS = -DNCBI_MODULE=BLAST $(ORIG_CPPFLAGS) $(BOOST_INCLUDE) -I$(srcdir)/../../api -LIB = seqalign_util test_boost $(BLAST_INPUT_LIBS) ncbi_xloader_blastdb_rmt \ +LIB = seqalign_util test_boost $(BLAST_INPUT_LIBS) \ $(BLAST_LIBS) xobjsimple $(OBJMGR_LIBS:ncbi_x%=ncbi_x%$(DLL)) LIBS = $(NETWORK_LIBS) $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.pssmcreate_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.pssmcreate_unit_test.app index b85eb305..bec0c9cb 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.pssmcreate_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.pssmcreate_unit_test.app @@ -1,4 +1,4 @@ -# $Id: Makefile.pssmcreate_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.pssmcreate_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = pssmcreate_unit_test SRC = pssmcreate_unit_test pssm_test_util pssmcreate_cdd_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.pssmenginefreqratios_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.pssmenginefreqratios_unit_test.app index 6852a518..2df1eab5 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.pssmenginefreqratios_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.pssmenginefreqratios_unit_test.app @@ -1,4 +1,4 @@ -# $Id: Makefile.pssmenginefreqratios_unit_test.app 464229 2015-04-07 14:51:55Z fongah2 $ +# $Id: Makefile.pssmenginefreqratios_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = pssmenginefreqratios_unit_test SRC = pssmenginefreqratios_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.querydata_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.querydata_unit_test.app index e4610be9..234d68c6 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.querydata_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.querydata_unit_test.app @@ -1,11 +1,11 @@ -# $Id: Makefile.querydata_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.querydata_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = querydata_unit_test SRC = querydata_unit_test CPPFLAGS = -DNCBI_MODULE=BLAST $(ORIG_CPPFLAGS) $(BOOST_INCLUDE) LIB = blast_unit_test_util test_boost $(BLAST_LIBS) xobjsimple $(OBJMGR_LIBS:ncbi_x%=ncbi_x%$(DLL)) -LIBS = $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) +LIBS = $(NETWORK_LIBS) $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) CHECK_REQUIRES = MT in-house-resources CHECK_CMD = querydata_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.queryinfo_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.queryinfo_unit_test.app index a5ff5428..0b1ada52 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.queryinfo_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.queryinfo_unit_test.app @@ -1,11 +1,11 @@ -# $Id: Makefile.queryinfo_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.queryinfo_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = queryinfo_unit_test SRC = queryinfo_unit_test CPPFLAGS = -DNCBI_MODULE=BLAST $(ORIG_CPPFLAGS) $(BOOST_INCLUDE) -I$(srcdir)/../../api LIB = blast_unit_test_util test_boost $(BLAST_LIBS) xobjsimple $(OBJMGR_LIBS:ncbi_x%=ncbi_x%$(DLL)) -LIBS = $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) +LIBS = $(NETWORK_LIBS) $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) CHECK_REQUIRES = MT in-house-resources CHECK_CMD = queryinfo_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.redoalignment_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.redoalignment_unit_test.app index 75431f4d..1e2c1974 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.redoalignment_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.redoalignment_unit_test.app @@ -1,15 +1,15 @@ -# $Id: Makefile.redoalignment_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.redoalignment_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = redoalignment_unit_test SRC = redoalignment_unit_test CPPFLAGS = -DNCBI_MODULE=BLAST $(ORIG_CPPFLAGS) $(BOOST_INCLUDE) -I$(srcdir)/../../api -I$(srcdir)/../../core -LIB = blast_unit_test_util test_boost $(BLAST_INPUT_LIBS) ncbi_xloader_blastdb_rmt \ +LIB = blast_unit_test_util test_boost $(BLAST_INPUT_LIBS) \ $(BLAST_LIBS) xobjsimple $(OBJMGR_LIBS:ncbi_x%=ncbi_x%$(DLL)) -LIBS = $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) +LIBS = $(NETWORK_LIBS) $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) CHECK_REQUIRES = MT in-house-resources CHECK_CMD = redoalignment_unit_test CHECK_COPY = redoalignment_unit_test.ini data -WATCHERS = boratyng madden +WATCHERS = boratyng madden diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.remote_blast_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.remote_blast_unit_test.app index 9aa515c8..a675b49c 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.remote_blast_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.remote_blast_unit_test.app @@ -1,4 +1,4 @@ -# $Id: Makefile.remote_blast_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.remote_blast_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = remote_blast_unit_test SRC = remote_blast_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.rps_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.rps_unit_test.app index 3b3193ed..d0f88a49 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.rps_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.rps_unit_test.app @@ -1,4 +1,4 @@ -# $Id: Makefile.rps_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.rps_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = rps_unit_test SRC = rps_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.scoreblk_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.scoreblk_unit_test.app index a10ceb40..939a7e44 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.scoreblk_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.scoreblk_unit_test.app @@ -1,4 +1,4 @@ -# $Id: Makefile.scoreblk_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.scoreblk_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = scoreblk_unit_test SRC = scoreblk_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.search_strategy_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.search_strategy_unit_test.app index 2a68bc7f..47fb260b 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.search_strategy_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.search_strategy_unit_test.app @@ -1,4 +1,4 @@ -# $Id: Makefile.search_strategy_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.search_strategy_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = search_strategy_unit_test SRC = search_strategy_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.seqalign_util.lib b/c++/src/algo/blast/unit_tests/api/Makefile.seqalign_util.lib index 25b55742..d61a2a3a 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.seqalign_util.lib +++ b/c++/src/algo/blast/unit_tests/api/Makefile.seqalign_util.lib @@ -1,4 +1,4 @@ -# $Id: Makefile.seqalign_util.lib 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.seqalign_util.lib 505858 2016-06-29 16:55:21Z elisovdn $ WATCHERS = camacho madden fongah2 diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.seqinfosrc_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.seqinfosrc_unit_test.app index 523060cf..8728d6f5 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.seqinfosrc_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.seqinfosrc_unit_test.app @@ -1,4 +1,4 @@ -# $Id: Makefile.seqinfosrc_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.seqinfosrc_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = seqinfosrc_unit_test SRC = seqinfosrc_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.seqsrc_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.seqsrc_unit_test.app index f89fb760..d95bbfa5 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.seqsrc_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.seqsrc_unit_test.app @@ -1,4 +1,4 @@ -# $Id: Makefile.seqsrc_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.seqsrc_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = seqsrc_unit_test SRC = seqsrc_unit_test seqsrc_mock mockseqsrc1_unit_test mockseqsrc2_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.setupfactory_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.setupfactory_unit_test.app index dad179e5..7c2f7107 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.setupfactory_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.setupfactory_unit_test.app @@ -1,4 +1,4 @@ -# $Id: Makefile.setupfactory_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.setupfactory_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = setupfactory_unit_test SRC = setupfactory_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.split_query_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.split_query_unit_test.app index c6fcc127..49bba314 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.split_query_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.split_query_unit_test.app @@ -1,4 +1,4 @@ -# $Id: Makefile.split_query_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.split_query_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = split_query_unit_test SRC = split_query_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.stat_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.stat_unit_test.app index 72de2e74..1eac3cbe 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.stat_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.stat_unit_test.app @@ -1,4 +1,4 @@ -# $Id: Makefile.stat_unit_test.app 498724 2016-04-19 13:36:57Z ivanov $ +# $Id: Makefile.stat_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = stat_unit_test SRC = stat_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.subj_ranges_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.subj_ranges_unit_test.app index c98812cc..02d53dbf 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.subj_ranges_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.subj_ranges_unit_test.app @@ -1,11 +1,11 @@ -# $Id: Makefile.subj_ranges_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.subj_ranges_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = subj_ranges_unit_test SRC = subj_ranges_unit_test CPPFLAGS = -DNCBI_MODULE=BLAST $(ORIG_CPPFLAGS) $(BOOST_INCLUDE) LIB = test_boost $(BLAST_LIBS) xobjsimple $(OBJMGR_LIBS:ncbi_x%=ncbi_x%$(DLL)) -LIBS = $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) +LIBS = $(NETWORK_LIBS) $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) CHECK_REQUIRES = MT in-house-resources CHECK_CMD = subj_ranges_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.traceback_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.traceback_unit_test.app index ce666f7a..b4a415e8 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.traceback_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.traceback_unit_test.app @@ -1,4 +1,4 @@ -# $Id: Makefile.traceback_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.traceback_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = traceback_unit_test SRC = traceback_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.tracebacksearch_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.tracebacksearch_unit_test.app index 190142fc..5eb2d98d 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.tracebacksearch_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.tracebacksearch_unit_test.app @@ -1,4 +1,4 @@ -# $Id: Makefile.tracebacksearch_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.tracebacksearch_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = tracebacksearch_unit_test SRC = tracebacksearch_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.uniform_search_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.uniform_search_unit_test.app index f14e4047..5cbaa040 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.uniform_search_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.uniform_search_unit_test.app @@ -1,4 +1,4 @@ -# $Id: Makefile.uniform_search_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.uniform_search_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = uniform_search_unit_test SRC = uniform_search_unit_test diff --git a/c++/src/algo/blast/unit_tests/api/Makefile.version_reference_unit_test.app b/c++/src/algo/blast/unit_tests/api/Makefile.version_reference_unit_test.app index c2df777d..780eb5ee 100644 --- a/c++/src/algo/blast/unit_tests/api/Makefile.version_reference_unit_test.app +++ b/c++/src/algo/blast/unit_tests/api/Makefile.version_reference_unit_test.app @@ -1,14 +1,14 @@ -# $Id: Makefile.version_reference_unit_test.app 454176 2014-12-11 16:00:59Z camacho $ +# $Id: Makefile.version_reference_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = version_reference_unit_test SRC = version_reference_unit_test CPPFLAGS = -DNCBI_MODULE=BLAST $(ORIG_CPPFLAGS) $(BOOST_INCLUDE) LIB = test_boost $(BLAST_LIBS) xobjsimple $(OBJMGR_LIBS:ncbi_x%=ncbi_x%$(DLL)) -LIBS = $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) +LIBS = $(NETWORK_LIBS) $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) CHECK_REQUIRES = MT in-house-resources CHECK_CMD = version_reference_unit_test CHECK_COPY = version_reference_unit_test.ini -WATCHERS = madden camacho +WATCHERS = madden camacho diff --git a/c++/src/algo/blast/unit_tests/api/aalookup_unit_test.cpp b/c++/src/algo/blast/unit_tests/api/aalookup_unit_test.cpp index 1fd2460f..d030ea83 100644 --- a/c++/src/algo/blast/unit_tests/api/aalookup_unit_test.cpp +++ b/c++/src/algo/blast/unit_tests/api/aalookup_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: aalookup_unit_test.cpp 347537 2011-12-19 16:45:43Z maning $ +/* $Id: aalookup_unit_test.cpp 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -193,6 +193,7 @@ struct AalookupTestFixture { sbp, &lookup_wrap_ptr, NULL /* RPS info */, + NULL, NULL); lookup = (BlastAaLookupTable*) lookup_wrap_ptr->lut; } diff --git a/c++/src/algo/blast/unit_tests/api/aascan_unit_test.cpp b/c++/src/algo/blast/unit_tests/api/aascan_unit_test.cpp index 7bb3a028..c6274200 100644 --- a/c++/src/algo/blast/unit_tests/api/aascan_unit_test.cpp +++ b/c++/src/algo/blast/unit_tests/api/aascan_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: aascan_unit_test.cpp 272713 2011-04-11 14:49:23Z camacho $ +/* $Id: aascan_unit_test.cpp 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -215,6 +215,7 @@ struct AascanTestFixture { sbp, &lookup_wrap_ptr, NULL /* RPS Info */, + NULL, NULL); BOOST_REQUIRE_EQUAL(0, status); diff --git a/c++/src/algo/blast/unit_tests/api/bl2seq_unit_test.cpp b/c++/src/algo/blast/unit_tests/api/bl2seq_unit_test.cpp index 427223db..df702dd3 100644 --- a/c++/src/algo/blast/unit_tests/api/bl2seq_unit_test.cpp +++ b/c++/src/algo/blast/unit_tests/api/bl2seq_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: bl2seq_unit_test.cpp 495292 2016-03-16 14:52:49Z ivanov $ +/* $Id: bl2seq_unit_test.cpp 507726 2016-07-21 14:42:04Z grichenk $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -1986,7 +1986,7 @@ BOOST_AUTO_TEST_CASE(ProteinBlast2Seqs) { CSeq_id id("gi|129295"); auto_ptr query(CTestObjMgr::Instance().CreateSSeqLoc(id)); - id.SetGi(GI_FROM(TIntId, 7662354)); + id.SetGi(GI_CONST(7662354)); auto_ptr subj(CTestObjMgr::Instance().CreateSSeqLoc(id)); CBl2Seq blaster(*query, *subj, eBlastp); @@ -2197,7 +2197,7 @@ BOOST_AUTO_TEST_CASE(ProteinBlastChangeQuery) { CSeq_id id("gi|129295"); auto_ptr query(CTestObjMgr::Instance().CreateSSeqLoc(id)); - id.SetGi(GI_FROM(TIntId, 7662354)); + id.SetGi(GI_CONST(7662354)); auto_ptr subj(CTestObjMgr::Instance().CreateSSeqLoc(id)); // Run self hit first @@ -3313,7 +3313,7 @@ BOOST_AUTO_TEST_CASE(testOneSubjectResults2CSeqAlign) int index; for (index = 0; index < num_subjects; ++index) { id.Reset(new CSeq_id(CSeq_id::e_Gi, (query_gi + gi_diff + index))); -cerr << query_gi + gi_diff + index << endl; + //cerr << query_gi + gi_diff + index << endl; sl.reset(CTestObjMgr::Instance().CreateSSeqLoc(*id, eNa_strand_both)); subjects.push_back(*sl); @@ -3325,7 +3325,7 @@ cerr << query_gi + gi_diff + index << endl; index = 0; ITERATE(TSeqAlignVector, itr, seqalign_v) { -cerr << index << endl; + //cerr << index << endl; BOOST_REQUIRE_EQUAL(results_size[index], (int) (*itr)->Get().size()); index++; } @@ -3593,7 +3593,7 @@ BOOST_AUTO_TEST_CASE(MultiIntervalLoc) { BOOST_AUTO_TEST_CASE(QueryMaskIgnoredInMiniExtension) { CRef qloc(new CSeq_loc()); - qloc->SetWhole().SetGi(GI_FROM(TIntId, 4505696)); + qloc->SetWhole().SetGi(GI_CONST(4505696)); CSeq_id sid("gi|29809252"); pair range(662070, 662129); diff --git a/c++/src/algo/blast/unit_tests/api/blastdiag_unit_test.cpp b/c++/src/algo/blast/unit_tests/api/blastdiag_unit_test.cpp index 576fdbfd..b3bc0616 100644 --- a/c++/src/algo/blast/unit_tests/api/blastdiag_unit_test.cpp +++ b/c++/src/algo/blast/unit_tests/api/blastdiag_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: blastdiag_unit_test.cpp 462040 2015-03-16 13:14:29Z vasilche $ +/* $Id: blastdiag_unit_test.cpp 506072 2016-07-01 13:01:25Z dicuccio $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -35,10 +35,8 @@ #include -#include "test_objmgr.hpp" using namespace ncbi; -using namespace ncbi::blast; BOOST_AUTO_TEST_SUITE(BlastDiag) diff --git a/c++/src/algo/blast/unit_tests/api/blastengine_unit_test.cpp b/c++/src/algo/blast/unit_tests/api/blastengine_unit_test.cpp index 077301a3..e8bc6d8f 100644 --- a/c++/src/algo/blast/unit_tests/api/blastengine_unit_test.cpp +++ b/c++/src/algo/blast/unit_tests/api/blastengine_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: blastengine_unit_test.cpp 498724 2016-04-19 13:36:57Z ivanov $ +/* $Id: blastengine_unit_test.cpp 507726 2016-07-21 14:42:04Z grichenk $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -148,8 +148,8 @@ void testShortMatchDiagnostics(BlastDiagnostics* diagnostics) BOOST_AUTO_TEST_CASE(testTBLASTNLongMatchBlastEngine) { const Int4 kNumHspsEnd=23; const Int8 kEffectiveSearchSpace = 1050668186940LL; - const TGi kQueryGi = GI_FROM(TIntId, 9790067); - const TGi kSubjectGi = GI_FROM(TIntId, 30698605); + const TGi kQueryGi = GI_CONST(9790067); + const TGi kSubjectGi = GI_CONST(30698605); const EBlastProgramType kProgramType = eBlastTypeTblastn; const EProgram kProgram = eTblastn; @@ -220,8 +220,8 @@ BOOST_AUTO_TEST_CASE(testTBLASTNLongMatchBlastEngine) { BOOST_AUTO_TEST_CASE(testTBLASTNShortMatchBlastEngine) { const Int4 kNumHspsEnd=8; const Int8 kEffectiveSearchSpace = 1050668186940LL; - const TGi kQueryGi = GI_FROM(TIntId, 9790067); - const TGi kSubjectGi = GI_FROM(TIntId, 38547463); + const TGi kQueryGi = GI_CONST(9790067); + const TGi kSubjectGi = GI_CONST(38547463); const EBlastProgramType kProgramType = eBlastTypeTblastn; const EProgram kProgram = eTblastn; @@ -282,8 +282,8 @@ BOOST_AUTO_TEST_CASE(testTBLASTNShortMatchBlastEngine) { // and hence has a large number of hits, even with an increased word size. BOOST_AUTO_TEST_CASE(testBlastnWithLargeWordSize) { - const TGi kQueryGi = GI_FROM(TIntId, 186279); // Short human sequence with repeats - const TGi kSubjectGi = GI_FROM(TIntId, 29791382); // Contig from human chromosome 1 + const TGi kQueryGi = GI_CONST(186279); // Short human sequence with repeats + const TGi kSubjectGi = GI_CONST(29791382); // Contig from human chromosome 1 const int kNumHsps = 330; const EBlastProgramType kProgramType = eBlastTypeBlastn; @@ -316,8 +316,8 @@ BOOST_AUTO_TEST_CASE(testBlastnWithLargeWordSize) // only 1 HSP is left. BOOST_AUTO_TEST_CASE(testBlastnWithRepeatsFiltering) { - const TGi kQueryGi = GI_FROM(TIntId, 186279); // Short human sequence with repeats - const TGi kSubjectGi = GI_FROM(TIntId, 29791382); // Contig from human chromosome 1 + const TGi kQueryGi = GI_CONST(186279); // Short human sequence with repeats + const TGi kSubjectGi = GI_CONST(29791382); // Contig from human chromosome 1 const int kNumHsps = 3; const int kMaskedLength = 389; const EBlastProgramType kProgramType = eBlastTypeBlastn; @@ -355,7 +355,7 @@ BOOST_AUTO_TEST_CASE(testBlastnWithRepeatsFiltering) BOOST_AUTO_TEST_CASE(testDiscMegaBlastPartialRun) { - const TGi kQueryGi = GI_FROM(TIntId, 14702146); + const TGi kQueryGi = GI_CONST(14702146); const string kDbName("data/seqn"); const size_t kNumHits = 2; const TIntId kGis[kNumHits] = { 46071158, 46072400 }; @@ -412,8 +412,8 @@ BOOST_AUTO_TEST_CASE(testDiscMegaBlastPartialRun) BOOST_AUTO_TEST_CASE(testBlastpPrelimSearch) { const string kDbName("data/seqp"); - const TGi kQueryGi1 = GI_FROM(TIntId, 21282798); - const TGi kQueryGi2 = GI_FROM(TIntId, 129295); + const TGi kQueryGi1 = GI_CONST(21282798); + const TGi kQueryGi2 = GI_CONST(129295); const int kNumHits = 31; const int kNumHitsToCheck = 3; const int kIndices[kNumHitsToCheck] = { 1, 4, 8 }; diff --git a/c++/src/algo/blast/unit_tests/api/blastfilter_unit_test.cpp b/c++/src/algo/blast/unit_tests/api/blastfilter_unit_test.cpp index ee5c0053..702d5653 100644 --- a/c++/src/algo/blast/unit_tests/api/blastfilter_unit_test.cpp +++ b/c++/src/algo/blast/unit_tests/api/blastfilter_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: blastfilter_unit_test.cpp 496425 2016-03-28 15:16:22Z ivanov $ +/* $Id: blastfilter_unit_test.cpp 507726 2016-07-21 14:42:04Z grichenk $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -413,9 +413,9 @@ BOOST_AUTO_TEST_CASE(TSeqLocVector2Packed_seqint_TestIntervals) { BOOST_AUTO_TEST_CASE(TSeqLocVector2Packed_seqint_TestNoIntervals) { typedef pair TGiLength; vector gis; - gis.push_back(make_pair(GI_FROM(TIntId, 6), 342U)); - gis.push_back(make_pair(GI_FROM(TIntId, 129295), 232U)); - gis.push_back(make_pair(GI_FROM(TIntId, 15606659), 443U)); + gis.push_back(make_pair(GI_CONST(6), 342U)); + gis.push_back(make_pair(GI_CONST(129295), 232U)); + gis.push_back(make_pair(GI_CONST(15606659), 443U)); TSeqLocVector input; input.reserve(gis.size()); @@ -545,14 +545,14 @@ BOOST_AUTO_TEST_CASE(WindowMasker) { 0, 79, 100, 122, 146, 169, - 225, 248, + 225, 247, 286, 329, 348, 366, 373, 688, 701, 1303, 1450, 1485, 2858, 2887, - 3086, 3212, + 3103, 3212, 3217, 3735, 4142, 4162, 5423, 5443, @@ -564,7 +564,8 @@ BOOST_AUTO_TEST_CASE(WindowMasker) 7170, 7189, 7604, 7623, 8454, 8476, - 8829, 8889 + 8829, 8851, + 8860, 8889 }; size_t num_locs = sizeof(intervals) / pair_size; diff --git a/c++/src/algo/blast/unit_tests/api/blasthits_unit_test.cpp b/c++/src/algo/blast/unit_tests/api/blasthits_unit_test.cpp index 1611e4ad..1e11c091 100644 --- a/c++/src/algo/blast/unit_tests/api/blasthits_unit_test.cpp +++ b/c++/src/algo/blast/unit_tests/api/blasthits_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: blasthits_unit_test.cpp 500125 2016-05-02 16:14:49Z ivanov $ +/* $Id: blasthits_unit_test.cpp 514847 2016-09-26 17:22:13Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -70,38 +70,38 @@ BOOST_AUTO_TEST_SUITE(blasthits) const int kNumLists = 3; const int kMaxHspCount = 6; const int kHspCounts[kNumLists] = { 6, 6, 4 }; - const int kSubjectOffsets[kNumLists][kMaxHspCount] = - { { 100, 9950, 5000, 9850, 3000, 9970 }, - { 9950, 9902, 9970, 10400, 19750, 19820 }, + const int kSubjectOffsets[kNumLists][kMaxHspCount] = + { { 100, 9950, 5000, 9850, 3000, 9970 }, + { 9950, 9902, 9970, 10400, 19750, 19820 }, { 19805, 25000, 19820, 22000 } }; - const int kQueryOffsets[kNumLists][kMaxHspCount] = - { { 100, 200, 300, 400, 500, 600 }, - { 200, 452, 600, 100, 200, 300 }, + const int kQueryOffsets[kNumLists][kMaxHspCount] = + { { 100, 200, 300, 400, 500, 600 }, + { 200, 452, 600, 100, 200, 300 }, { 255, 100, 300, 200 } }; - const int kLengths[kNumLists][kMaxHspCount] = - { { 100, 45, 100, 100, 100, 28 }, - { 100, 48, 100, 100, 100, 60 }, + const int kLengths[kNumLists][kMaxHspCount] = + { { 100, 45, 100, 100, 100, 28 }, + { 100, 48, 100, 100, 100, 60 }, { 45, 200, 60, 200} }; - const int kScores[kNumLists][kMaxHspCount] = - { { 60, 30, 70, 75, 65, 28 }, - { 80, 40, 62, 77, 72, 44 }, + const int kScores[kNumLists][kMaxHspCount] = + { { 60, 30, 70, 75, 65, 28 }, + { 80, 40, 62, 77, 72, 44 }, { 32, 120, 44, 111 } }; - const int contexts[kNumLists][kMaxHspCount] = - { { 0, 1, 2, 1, 3, 1 }, - { 1, 4, 1, 0, 1, 1 }, + const int contexts[kNumLists][kMaxHspCount] = + { { 0, 1, 2, 1, 3, 1 }, + { 1, 4, 1, 0, 1, 1 }, { 1, 0, 1, 4 } }; int index; BlastHSPList* hsp_list = *hsp_list_ptr; hsp_list->hspcnt = kHspCounts[chunk]; for (index = 0; index < kHspCounts[chunk]; ++index) { - hsp_list->hsp_array[index] = + hsp_list->hsp_array[index] = (BlastHSP*) calloc(1, sizeof(BlastHSP)); hsp_list->hsp_array[index]->query.offset = kQueryOffsets[chunk][index]; hsp_list->hsp_array[index]->subject.offset = kSubjectOffsets[chunk][index]; - hsp_list->hsp_array[index]->query.end = + hsp_list->hsp_array[index]->query.end = kQueryOffsets[chunk][index] + kLengths[chunk][index]; - hsp_list->hsp_array[index]->subject.end = + hsp_list->hsp_array[index]->subject.end = kSubjectOffsets[chunk][index] + kLengths[chunk][index]; hsp_list->hsp_array[index]->score = kScores[chunk][index]; hsp_list->hsp_array[index]->context = contexts[chunk][index]; @@ -113,7 +113,7 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) { CAutomaticGenCodeSingleton instance; CSeq_id sid("CU856286"); // DNA sequence - auto_ptr subj(CTestObjMgr::Instance().CreateSSeqLoc(sid)); + auto_ptr subj(CTestObjMgr::Instance().CreateSSeqLoc(sid)); Int2 status = 0; SBlastSequence subj_sequence( @@ -126,8 +126,8 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) BLAST_SequenceBlk* subject_blk; BlastSeqBlkNew(&subject_blk); status = BlastSeqBlkSetSequence(subject_blk, - subj_sequence.data.release(), - sequence::GetLength(*subj->seqloc, subj->scope)); + subj_sequence.data.release(), + sequence::GetLength(*subj->seqloc, subj->scope)); SBlastTargetTranslation* target_t = NULL; @@ -138,16 +138,19 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) BOOST_REQUIRE_EQUAL(0, status); BOOST_REQUIRE(target_t); - // HSP is NULL so nothing returned. + // HSP is NULL so nothing returned. const Uint1* null_sequence = Blast_HSPGetTargetTranslation(target_t, NULL, NULL); BOOST_REQUIRE(null_sequence == NULL); const int kNumTests = 6; BlastHSP* hsp; Blast_HSPInit(1, 2000, 2000, 3000, 1, 2000, 0, 0, -3, 2000, NULL, &hsp); - // These are values that come out for this case. kLength could change if - // heuristic for allocating buffers in Blast_HSPGetTargetTranslation changes. - const int kLength[kNumTests] = {3899, 4099, 4300, 4500, 4699, 4899 }; + // The following line must match the value in blast_hits.c + const int kMaxTranslation = 99; + const int kMaxDiv3 = kMaxTranslation / 3; + // These are values that come out for this case. kLength could change if + // heuristic for allocating buffers in Blast_HSPGetTargetTranslation changes. + const int kLength[kNumTests] = {3199, 3399, 3600, 3800, 3999, 4199}; const int kValues[2*kNumTests] = {6, 16, 18, 10, 10, 6, 8, 4, 18, 17, 1, 6}; int index = 0; for (index=0; indexsubject.offset+5]); Int4 i, n = 0; - for (i = hsp->subject.offset-701; i < hsp->subject.offset - 693; ++i) { - if (sequence[i] == 201) ++n; + for (i = hsp->subject.offset-(kMaxDiv3 + 1); i < hsp->subject.offset - (kMaxDiv3 - 7); ++i) { + if (sequence[i] == 201) ++n; } BOOST_REQUIRE(n!=0); n = 0; - for (; i < hsp->subject.end + 693; ++i) { - if (sequence[i] == 201) ++n; + for (; i < hsp->subject.end + (kMaxDiv3 - 7); ++i) { + if (sequence[i] == 201) ++n; } BOOST_REQUIRE(n==0); n = 0; - for (; i < hsp->subject.end + 701 && n == 0; ++i) { - if (sequence[i] == 201) ++n; + for (; i < hsp->subject.end + (kMaxDiv3 + 1) && n == 0; ++i) { + if (sequence[i] == 201) ++n; } BOOST_REQUIRE(n!=0); hsp->subject.offset += 200; hsp->subject.end += 200; sequence = Blast_HSPGetTargetTranslation(target_t, hsp, &length); - BOOST_REQUIRE_EQUAL(kLength[index], length); + BOOST_REQUIRE_EQUAL(kLength[index] + kMaxDiv3, length); BOOST_REQUIRE_EQUAL(kValues[2*index+1], (int) sequence[hsp->subject.offset+5]); n = 0; - for (i = hsp->subject.offset-701; i < hsp->subject.offset - 693; ++i) { - if (sequence[i] == 201) ++n; + for (i = hsp->subject.offset-(kMaxDiv3 + 1); i < hsp->subject.offset - (kMaxDiv3 - 7); ++i) { + if (sequence[i] == 201) ++n; } BOOST_REQUIRE(n!=0); n = 0; - for (; i < hsp->subject.end + 693; ++i) { - if (sequence[i] == 201) ++n; + for (; i < hsp->subject.end + (kMaxDiv3 - 7); ++i) { + if (sequence[i] == 201) ++n; } BOOST_REQUIRE(n==0); n = 0; - for (; i < hsp->subject.end + 701 && n == 0; ++i) { - if (sequence[i] == 201) ++n; + for (; i < hsp->subject.end + (kMaxDiv3 + 1) && n == 0; ++i) { + if (sequence[i] == 201) ++n; } BOOST_REQUIRE(n!=0); @@ -222,12 +225,12 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) const int kNumChunks = 3; const int kOffsetIncrement = 9900; const int kTotalNumHsps = 12; - const int kFinalScores[kTotalNumHsps] = + const int kFinalScores[kTotalNumHsps] = { 120, 111, 80, 77, 75, 72, 70, 70, 65, 60, 44, 40 }; - const int kFinalOffsets[kTotalNumHsps] = - { 25000, 22000, 9950, 10400, 9850, 19750, 5000, 9970, 3000, 100, + const int kFinalOffsets[kTotalNumHsps] = + { 25000, 22000, 9950, 10400, 9850, 19750, 5000, 9970, 3000, 100, 19820, 9902 }; - const int kFinalLengths[kTotalNumHsps] = + const int kFinalLengths[kTotalNumHsps] = { 200, 200, 100, 100, 100, 100, 100, 100, 100, 100, 60, 48 }; Int4 offset = 0, hsp_num_max = INT4_MAX; int chunk; @@ -236,9 +239,9 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) for (chunk = 0; chunk < kNumChunks; ++chunk) { BlastHSPList* hsp_list = Blast_HSPListNew(0); setupHSPList(&hsp_list, chunk); - Blast_HSPListsMerge(&hsp_list, &combined_hsp_list, + Blast_HSPListsMerge(&hsp_list, &combined_hsp_list, hsp_num_max, &offset, INT4_MIN, - DBSEQ_CHUNK_OVERLAP, TRUE); + DBSEQ_CHUNK_OVERLAP, TRUE, FALSE); offset += kOffsetIncrement; } @@ -250,7 +253,7 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) BlastHSP* hsp = combined_hsp_list->hsp_array[index]; BOOST_REQUIRE_EQUAL(kFinalScores[index], hsp->score); BOOST_REQUIRE_EQUAL(kFinalOffsets[index], hsp->subject.offset); - BOOST_REQUIRE_EQUAL(kFinalLengths[index], + BOOST_REQUIRE_EQUAL(kFinalLengths[index], hsp->subject.end - hsp->subject.offset); } @@ -272,7 +275,7 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) Check that the hspcnt is reset to zero at the end. */ BOOST_AUTO_TEST_CASE(testPurgeOfEmptyHSPList) { BlastHSPList* hsp_list = Blast_HSPListNew(0); - const int kNumNullHsps=5; + const int kNumNullHsps=5; hsp_list->hspcnt = kNumNullHsps; Blast_HSPListPurgeNullHSPs(hsp_list); /* Nothing was put on list, nothing should be purged off. */ @@ -345,7 +348,7 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) hsp_list->hsp_array[7] = Blast_HSPFree(hsp_list->hsp_array[7]); hsp_list->hsp_array[17] = Blast_HSPFree(hsp_list->hsp_array[17]); hsp_list->hsp_array[24] = Blast_HSPFree(hsp_list->hsp_array[kNumHsps-1]); // last - + /* Purge, this should remove the "holes" in the array. */ Blast_HSPListPurgeNullHSPs(hsp_list); @@ -360,7 +363,7 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) { BOOST_REQUIRE_EQUAL((BlastHSP*)0, hsp_list->hsp_array[index]); } - + hsp_list = Blast_HSPListFree(hsp_list); BOOST_REQUIRE(hsp_list == NULL); } @@ -373,14 +376,14 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) GapEditScript * kPtrValue = edit_script; - Int2 rv = Blast_HSPInit(kOffset, 2*kOffset, 3*kOffset, 4*kOffset, - 5*kOffset, 6*kOffset, 0, 0, 0, 10*kOffset, + Int2 rv = Blast_HSPInit(kOffset, 2*kOffset, 3*kOffset, 4*kOffset, + 5*kOffset, 6*kOffset, 0, 0, 0, 10*kOffset, &edit_script, &new_hsp); BOOST_REQUIRE_EQUAL((Int2)0, rv); BOOST_REQUIRE_EQUAL((GapEditScript *) 0, edit_script); // this was NULL'ed out // HSP got the pointer to edit_script - BOOST_REQUIRE_EQUAL(kPtrValue, new_hsp->gap_info); + BOOST_REQUIRE_EQUAL(kPtrValue, new_hsp->gap_info); BOOST_REQUIRE_EQUAL(kOffset, new_hsp->query.offset); BOOST_REQUIRE_EQUAL(2*kOffset, new_hsp->query.end); BOOST_REQUIRE_EQUAL(3*kOffset, new_hsp->subject.offset); @@ -403,30 +406,30 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) BOOST_REQUIRE(new_hsp == NULL); } - static void + static void s_SetupQueryInfoForReevaluateTest(EBlastProgramType program_number, BLAST_SequenceBlk* query_blk, Uint4 subj_length, BlastQueryInfo* * query_info_ptr) { BlastQueryInfo* query_info = BlastQueryInfoNew(program_number, 1); - + query_info->contexts[0].eff_searchsp = (Int8) query_blk->length*subj_length; query_info->contexts[0].query_length = query_blk->length; - + /* mark the other contexts as invalid so they are not used. */ for (int i=1; i<=query_info->last_context; i++) query_info->contexts[i].is_valid = false; - + *query_info_ptr = query_info; } - static void + static void s_SetupScoringOptionsForReevaluateHSP(BlastScoringOptions* * options_ptr, bool gapped, bool is_prot) { - BlastScoringOptions* options = + BlastScoringOptions* options = (BlastScoringOptions*) calloc(1, sizeof(BlastScoringOptions)); if (gapped) { options->gapped_calculation = TRUE; @@ -442,42 +445,42 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) *options_ptr = options; } - static void + static void s_SetupHSPForUngappedReevaluateNucl(BlastHSP* * hsp_ptr) { BlastHSP* hsp; - + if (*hsp_ptr != NULL) { hsp = *hsp_ptr; } else { *hsp_ptr = hsp = Blast_HSPNew(); } - hsp->query.offset = 0; + hsp->query.offset = 0; hsp->query.end = 20; hsp->subject.offset = 0; hsp->subject.end = 20; hsp->score = 20; } - static void - s_SetupSequencesForUngappedReevaluateNucl(BLAST_SequenceBlk* * query_blk, + static void + s_SetupSequencesForUngappedReevaluateNucl(BLAST_SequenceBlk* * query_blk, Uint1* * subject_seq_ptr) { const int kLength = 22; const Uint1 kQuerySeq[kLength+2] = { 15, 0, 1, 2, 3, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 0, 1, 2, 2, 1, 1, 0, 0, 15 }; - const Uint1 kSubjectSeq[kLength] = { 0, 1, 2, 2, 14, 14, 1, 1, 2, 2, 3, + const Uint1 kSubjectSeq[kLength] = { 0, 1, 2, 2, 14, 14, 1, 1, 2, 2, 3, 3, 3, 3, 0, 1, 8, 2, 1, 1, 14, 0 }; BlastSeqBlkNew(query_blk); - BlastSeqBlkSetSequence(*query_blk, - (Uint1*) BlastMemDup(kQuerySeq, kLength+2), + BlastSeqBlkSetSequence(*query_blk, + (Uint1*) BlastMemDup(kQuerySeq, kLength+2), kLength); *subject_seq_ptr = (Uint1*) BlastMemDup(kSubjectSeq, kLength);; } - static void + static void checkReevaluateResultsUngappedNucl(BlastHSP* hsp) { const int kScore = 11; @@ -501,7 +504,7 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) const Uint4 kSubjLength = 100000; const Uint4 kDbLength = 100000000; BlastHSP* hsp = NULL; - BLAST_SequenceBlk* query_blk = NULL; + BLAST_SequenceBlk* query_blk = NULL; Uint1* subject_seq = NULL; BlastQueryInfo* query_info = NULL; EBlastProgramType program_number = eBlastTypeBlastn; @@ -518,19 +521,19 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) s_SetupScoringOptionsForReevaluateHSP(&scoring_options, false, false); Blast_Message* blast_msg = NULL; - BOOST_REQUIRE_EQUAL(0, - (int) BlastSetup_ScoreBlkInit(query_blk, query_info, - scoring_options, program_number, + BOOST_REQUIRE_EQUAL(0, + (int) BlastSetup_ScoreBlkInit(query_blk, query_info, + scoring_options, program_number, &sbp, 1.0, &blast_msg, &BlastFindMatrixPath)); BOOST_REQUIRE(blast_msg == NULL); BlastExtensionOptions* ext_options = NULL; - BlastExtensionOptionsNew(program_number, &ext_options, + BlastExtensionOptionsNew(program_number, &ext_options, scoring_options->gapped_calculation); BlastHitSavingOptionsNew(program_number, &hit_options, scoring_options->gapped_calculation); - hit_options->expect_value = kEvalue; + hit_options->expect_value = kEvalue; BlastHitSavingParametersNew(program_number, hit_options, sbp, query_info, kDbLength, 0, &hit_params); @@ -540,15 +543,15 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) QuerySetUpOptions* query_options = NULL; BlastQuerySetUpOptionsNew(&query_options); LookupTableWrap* lookup_wrap = NULL; - LookupTableOptions* lookup_options = NULL; + LookupTableOptions* lookup_options = NULL; BlastSeqLoc* blast_seq_loc = BlastSeqLocNew(NULL, 0, query_info->contexts[0].query_length-1); LookupTableOptionsNew(program_number, &lookup_options); - LookupTableWrapInit(query_blk, lookup_options, query_options, blast_seq_loc, sbp, &lookup_wrap, NULL, NULL); + LookupTableWrapInit(query_blk, lookup_options, query_options, blast_seq_loc, sbp, &lookup_wrap, NULL, NULL, NULL); query_options = BlastQuerySetUpOptionsFree(query_options); BOOST_REQUIRE(query_options == NULL); BlastInitialWordOptionsNew(program_number, &word_options); - BlastInitialWordParametersNew(program_number, word_options, hit_params, + BlastInitialWordParametersNew(program_number, word_options, hit_params, lookup_wrap, sbp, query_info, kSubjLength, &word_params); blast_seq_loc = BlastSeqLocFree(blast_seq_loc); @@ -562,8 +565,8 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) s_SetupHSPForUngappedReevaluateNucl(&hsp); - BOOST_REQUIRE(Blast_HSPReevaluateWithAmbiguitiesUngapped(hsp, - query_blk->sequence, subject_seq, word_params, + BOOST_REQUIRE(Blast_HSPReevaluateWithAmbiguitiesUngapped(hsp, + query_blk->sequence, subject_seq, word_params, sbp, FALSE) == FALSE); checkReevaluateResultsUngappedNucl(hsp); @@ -581,47 +584,47 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) BlastScoreBlkFree(sbp); } - static void + static void s_SetupHSPListForUngappedReevaluateTransl(BlastHSPList* * hsplist_ptr) { BlastHSP* hsp = Blast_HSPNew(); - hsp->query.offset = 0; + hsp->query.offset = 0; hsp->query.end = 12; hsp->subject.offset = 0; hsp->subject.frame = 1; hsp->subject.end = 12; hsp->score = 45; - + *hsplist_ptr = Blast_HSPListNew(1); (*hsplist_ptr)->hsp_array[0] = hsp; (*hsplist_ptr)->hspcnt = 1; } - static void - s_SetupSequencesForUngappedReevaluateTransl(BLAST_SequenceBlk* * query_blk, + static void + s_SetupSequencesForUngappedReevaluateTransl(BLAST_SequenceBlk* * query_blk, BLAST_SequenceBlk* * subject_blk) { const int kLength = 12; const Uint1 kQuerySeq[kLength + 2] = { 0, 11, 19, 13, 1, 9, 22, 6, 10, 7, 12, 20, 10, 0 }; - const Uint1 kSubjectSeq[3*kLength] = + const Uint1 kSubjectSeq[3*kLength] = { 2, 8, 4, 4, 8, 4, 1, 1, 10, 8, 15, 2, 1, 8, 1, 8, 8, 15, 8, 8, 8, 1, 5, 1, 4, 4, 2, 1, 1, 1, 8, 4, 4, 4, 1, 4 }; BlastSeqBlkNew(query_blk); - BlastSeqBlkSetSequence(*query_blk, + BlastSeqBlkSetSequence(*query_blk, (Uint1*) BlastMemDup(kQuerySeq, kLength+2), kLength); BlastSeqBlkNew(subject_blk); - BlastSeqBlkSetSequence(*subject_blk, - (Uint1*) BlastMemDup(kSubjectSeq, 3*kLength), + BlastSeqBlkSetSequence(*subject_blk, + (Uint1*) BlastMemDup(kSubjectSeq, 3*kLength), 3*kLength); (*subject_blk)->sequence = (*subject_blk)->sequence_start; } - static void + static void checkReevaluateResultsUngappedTransl(BlastHSPList* hsp_list) { const int kScore = 38; @@ -648,8 +651,8 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) const Uint4 kSubjLength = 50000; const Uint4 kDbLength = 100000000; BlastHSPList* hsp_list = NULL; - BLAST_SequenceBlk* query_blk = NULL; - BLAST_SequenceBlk* subject_blk = NULL; + BLAST_SequenceBlk* query_blk = NULL; + BLAST_SequenceBlk* subject_blk = NULL; BlastQueryInfo* query_info = NULL; EBlastProgramType program_number = eBlastTypeTblastn; BlastScoringOptions* scoring_options = NULL; @@ -664,19 +667,19 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) query_blk, kDbLength, &query_info); s_SetupScoringOptionsForReevaluateHSP(&scoring_options, false, true); - BlastScoringParameters* score_params = + BlastScoringParameters* score_params = (BlastScoringParameters*) calloc(1, sizeof(BlastScoringParameters)); score_params->options = scoring_options; Blast_Message* blast_msg = NULL; - BOOST_REQUIRE_EQUAL(0, - (int) BlastSetup_ScoreBlkInit(query_blk, query_info, - scoring_options, program_number, + BOOST_REQUIRE_EQUAL(0, + (int) BlastSetup_ScoreBlkInit(query_blk, query_info, + scoring_options, program_number, &sbp, 1.0, &blast_msg, &BlastFindMatrixPath)); BlastExtensionOptions* ext_options = NULL; - BlastExtensionOptionsNew(program_number, &ext_options, + BlastExtensionOptionsNew(program_number, &ext_options, scoring_options->gapped_calculation); BlastHitSavingOptionsNew(program_number, &hit_options, scoring_options->gapped_calculation); @@ -689,15 +692,15 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) QuerySetUpOptions* query_options = NULL; BlastQuerySetUpOptionsNew(&query_options); LookupTableWrap* lookup_wrap = NULL; - LookupTableOptions* lookup_options = NULL; + LookupTableOptions* lookup_options = NULL; BlastSeqLoc* blast_seq_loc = BlastSeqLocNew(NULL, 0, query_info->contexts[0].query_length-1); LookupTableOptionsNew(program_number, &lookup_options); - LookupTableWrapInit(query_blk, lookup_options, query_options, blast_seq_loc, sbp, &lookup_wrap, NULL, NULL); + LookupTableWrapInit(query_blk, lookup_options, query_options, blast_seq_loc, sbp, &lookup_wrap, NULL, NULL, NULL); query_options = BlastQuerySetUpOptionsFree(query_options); BOOST_REQUIRE(query_options == NULL); BlastInitialWordOptionsNew(program_number, &word_options); - BlastInitialWordParametersNew(program_number, word_options, hit_params, + BlastInitialWordParametersNew(program_number, word_options, hit_params, lookup_wrap, sbp, query_info, kSubjLength, &word_params); blast_seq_loc = BlastSeqLocFree(blast_seq_loc); @@ -714,19 +717,19 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) Uint1* gen_code_string = (Uint1*) BlastMemDup(FindGeneticCode(1).get(), 64); - Blast_HSPListReevaluateUngapped(program_number, - hsp_list, query_blk, subject_blk, - word_params, hit_params, query_info, sbp, + Blast_HSPListReevaluateUngapped(program_number, + hsp_list, query_blk, subject_blk, + word_params, hit_params, query_info, sbp, score_params, NULL, gen_code_string); checkReevaluateResultsUngappedTransl(hsp_list); - // Now check identity and length test: the percent identity for the + // Now check identity and length test: the percent identity for the // first HSP is below 80%. hit_params->options->percent_identity = 80; - BOOST_REQUIRE(Blast_HSPTestIdentityAndLength(program_number, - hsp_list->hsp_array[0], query_blk->sequence, - subject_blk->sequence, score_params->options, + BOOST_REQUIRE(Blast_HSPTestIdentityAndLength(program_number, + hsp_list->hsp_array[0], query_blk->sequence, + subject_blk->sequence, score_params->options, hit_params->options)); sfree(gen_code_string); @@ -744,25 +747,25 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) BlastScoreBlkFree(sbp); } - static void + static void s_SetupHSPForGappedReevaluateTest(BlastHSP* * hsp_ptr) { const int kNumSegs = 5; - const EGapAlignOpType kEditScriptOpType[kNumSegs] = - { eGapAlignSub, eGapAlignDel, eGapAlignSub, eGapAlignDel, + const EGapAlignOpType kEditScriptOpType[kNumSegs] = + { eGapAlignSub, eGapAlignDel, eGapAlignSub, eGapAlignDel, eGapAlignSub }; const Int4 kEditScriptNum[kNumSegs] = { 4, 1, 11, 1, 5 }; int index; GapEditScript* esp = NULL; BlastHSP* hsp; - + if (*hsp_ptr != NULL) { hsp = *hsp_ptr; } else { *hsp_ptr = hsp = Blast_HSPNew(); } - hsp->query.offset = 0; + hsp->query.offset = 0; hsp->query.end = 20; hsp->subject.offset = 2; hsp->subject.end = 24; @@ -779,29 +782,29 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) } } - static void - s_SetupSequencesForGappedReevaluateTest(BLAST_SequenceBlk* * query_blk, - Uint1* * subject_seq_ptr, + static void + s_SetupSequencesForGappedReevaluateTest(BLAST_SequenceBlk* * query_blk, + Uint1* * subject_seq_ptr, Uint4* subj_length) { const int kQueryLength = 20; const int kSubjectLength = 25; - const Uint1 kQuerySeq[kQueryLength+2] = { 15, 0, 1, 2, 3, 0, 0, 1, 1, - 2, 2, 3, 3, 3, 3, 2, 2, 1, 1, + const Uint1 kQuerySeq[kQueryLength+2] = { 15, 0, 1, 2, 3, 0, 0, 1, 1, + 2, 2, 3, 3, 3, 3, 2, 2, 1, 1, 0, 0, 15 }; - const Uint1 kSubjectSeq[kSubjectLength] = { 1, 2, 0, 1, 2, 3, 3, 2, - 14, 1, 1, 2, 2, 3, 3, 3, 3, + const Uint1 kSubjectSeq[kSubjectLength] = { 1, 2, 0, 1, 2, 3, 3, 2, + 14, 1, 1, 2, 2, 3, 3, 3, 3, 2, 0, 2, 1, 14, 0, 0, 3 }; BlastSeqBlkNew(query_blk); - BlastSeqBlkSetSequence(*query_blk, - (Uint1*) BlastMemDup(kQuerySeq, kQueryLength+2), + BlastSeqBlkSetSequence(*query_blk, + (Uint1*) BlastMemDup(kQuerySeq, kQueryLength+2), kQueryLength); *subj_length = kSubjectLength; *subject_seq_ptr = (Uint1*) BlastMemDup(kSubjectSeq, kSubjectLength);; } - static void + static void checkReevaluateResultsGapped(BlastHSP* hsp) { const int kScore = 10; @@ -810,7 +813,7 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) const int kSubjectStart = 9; const int kSubjectEnd = 24; const int kNumSegs = 3; - const Uint1 kEditScriptOpType[kNumSegs] = + const Uint1 kEditScriptOpType[kNumSegs] = { eGapAlignSub, eGapAlignDel, eGapAlignSub }; const Uint1 kEditScriptNum[kNumSegs] = { 9, 1, 5 }; @@ -834,7 +837,7 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) BOOST_AUTO_TEST_CASE(testReevaluateWithAmbiguitiesGapped) { BlastHSP* hsp = NULL; - BLAST_SequenceBlk* query_blk = NULL; + BLAST_SequenceBlk* query_blk = NULL; Uint1* subject_seq = NULL; BlastQueryInfo* query_info = NULL; BlastHitSavingOptions* hit_options = NULL; @@ -845,35 +848,35 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) EBlastProgramType program_number = eBlastTypeBlastn; Uint4 subj_length = 0; - s_SetupSequencesForGappedReevaluateTest(&query_blk, &subject_seq, + s_SetupSequencesForGappedReevaluateTest(&query_blk, &subject_seq, &subj_length); s_SetupQueryInfoForReevaluateTest(program_number, query_blk, subj_length, &query_info); s_SetupScoringOptionsForReevaluateHSP(&scoring_options, true, false); BlastExtensionOptions* ext_options = NULL; - BlastExtensionOptionsNew(program_number, &ext_options, + BlastExtensionOptionsNew(program_number, &ext_options, scoring_options->gapped_calculation); BlastHitSavingOptionsNew(program_number, &hit_options, scoring_options->gapped_calculation); - hit_options->expect_value = 1; - BOOST_REQUIRE_EQUAL(0, - (int) BlastSetup_ScoreBlkInit(query_blk, query_info, - scoring_options, program_number, + hit_options->expect_value = 1; + BOOST_REQUIRE_EQUAL(0, + (int) BlastSetup_ScoreBlkInit(query_blk, query_info, + scoring_options, program_number, &sbp, 1.0, &blast_message, &BlastFindMatrixPath)); - BOOST_REQUIRE_EQUAL(0, + BOOST_REQUIRE_EQUAL(0, (int) BlastScoringParametersNew(scoring_options, sbp, &scoring_params)); - BlastHitSavingParameters* hit_params = (BlastHitSavingParameters*) + BlastHitSavingParameters* hit_params = (BlastHitSavingParameters*) calloc(1, sizeof(BlastHitSavingParameters)); BOOST_REQUIRE(query_blk); BOOST_REQUIRE(sbp->kbp_gap[0]); - BLAST_Cutoffs(&hit_params->cutoff_score_min, - &hit_options->expect_value, + BLAST_Cutoffs(&hit_params->cutoff_score_min, + &hit_options->expect_value, sbp->kbp_gap[0], subj_length*query_blk->length, FALSE, 0); hit_params->options = hit_options; hit_params->cutoffs = (BlastGappedCutoffs *)calloc(1, @@ -884,35 +887,35 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) Blast_HSPReevaluateWithAmbiguitiesGapped(hsp, query_blk->sequence, query_blk->length, subject_seq, subj_length, hit_params, scoring_params, sbp); - // With e-value 1, the low-scoring front piece of the alignment is + // With e-value 1, the low-scoring front piece of the alignment is // cut off. checkReevaluateResultsGapped(hsp); - + hit_options->expect_value = 10; hit_params->cutoff_score_min = 1; - BLAST_Cutoffs(&hit_params->cutoff_score_min, - &hit_options->expect_value, + BLAST_Cutoffs(&hit_params->cutoff_score_min, + &hit_options->expect_value, sbp->kbp_gap[0], subj_length*query_blk->length, FALSE, 0); hit_params->cutoffs[0].cutoff_score = hit_params->cutoff_score_min; - + s_SetupHSPForGappedReevaluateTest(&hsp); Blast_HSPReevaluateWithAmbiguitiesGapped(hsp, query_blk->sequence, query_blk->length, subject_seq, subj_length, hit_params, scoring_params, sbp); - // With e-value 10, the front piece of the alignment is left, and the + // With e-value 10, the front piece of the alignment is left, and the // remainder is cut off. checkReevaluateResultsGapped(hsp); - // Now check identity and length test: the percent identity for the + // Now check identity and length test: the percent identity for the // First HSP identity is above 80%. hit_params->options->percent_identity = 80; - BOOST_REQUIRE_EQUAL(0, - (int) Blast_HSPTestIdentityAndLength(program_number, + BOOST_REQUIRE_EQUAL(0, + (int) Blast_HSPTestIdentityAndLength(program_number, hsp, query_blk->sequence, subject_seq, scoring_params->options, hit_params->options)); // But its length is less than 20. hit_params->options->min_hit_length = 20; - BOOST_REQUIRE_EQUAL(1, - (int) Blast_HSPTestIdentityAndLength(program_number, + BOOST_REQUIRE_EQUAL(1, + (int) Blast_HSPTestIdentityAndLength(program_number, hsp, query_blk->sequence, subject_seq, scoring_params->options, hit_params->options)); @@ -935,9 +938,9 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) const int kLength = 22; const int kGappedStart = 1; const int kCutoff = 4; - Uint1 query[kLength] = { 2, 0, 1, 3, 2, 0, 2, 1, 2, 0, 1, 3, 3, 1, 0, 1, + Uint1 query[kLength] = { 2, 0, 1, 3, 2, 0, 2, 1, 2, 0, 1, 3, 3, 1, 0, 1, 3, 3, 3, 1, 0, 1 }; - Uint1 subject[kLength] = { 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + Uint1 subject[kLength] = { 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14 }; BlastHSP* hsp = (BlastHSP*) calloc(1, sizeof(BlastHSP)); hsp->query.end = hsp->subject.end = kLength; @@ -945,7 +948,7 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) hsp->gap_info = GapEditScriptNew(1); hsp->gap_info->op_type[0] = eGapAlignSub; hsp->gap_info->num[0] = kLength; - + BlastScoringOptions* score_opts = NULL; BlastScoringOptionsNew(kProgram, &score_opts); BlastScoreBlk* sbp = BlastScoreBlkNew(BLASTNA_SEQ_CODE, 1); @@ -954,7 +957,7 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) BlastScoringParametersNew(score_opts, sbp, &score_params); BlastHitSavingOptions* hit_opts = NULL; BlastExtensionOptions* ext_options = NULL; - BlastExtensionOptionsNew(kProgram, &ext_options, + BlastExtensionOptionsNew(kProgram, &ext_options, score_opts->gapped_calculation); BlastHitSavingOptionsNew(kProgram, &hit_opts, score_opts->gapped_calculation); @@ -966,7 +969,7 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) sizeof(BlastGappedCutoffs)); hit_params->cutoffs[0].cutoff_score = hit_params->cutoff_score_min; - Boolean delete_hsp = + Boolean delete_hsp = Blast_HSPReevaluateWithAmbiguitiesGapped(hsp, query, kLength, subject, kLength, hit_params, score_params, sbp); @@ -991,13 +994,13 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) BOOST_AUTO_TEST_CASE(testGetOOFNumIdentities) { const char* query = "ADADADADADBADADADADADADADAADADAD"; - const char* subject = + const char* subject = "ABCDBCABCDBCEABCDBCABCDBCABCDBCABCDBCABCDBABCDBCABCDABCDBCABCDBCFFABCDBCABCDBCABCDBCABCDBCGBCDBC"; const int kNumSegs = 13; - const EGapAlignOpType kEditScriptOp[kNumSegs] = - { eGapAlignSub, eGapAlignIns1, eGapAlignSub, eGapAlignDel, + const EGapAlignOpType kEditScriptOp[kNumSegs] = + { eGapAlignSub, eGapAlignIns1, eGapAlignSub, eGapAlignDel, eGapAlignSub, eGapAlignDel1, eGapAlignSub, eGapAlignDel2, - eGapAlignSub, eGapAlignIns2, eGapAlignSub, eGapAlignIns, + eGapAlignSub, eGapAlignIns2, eGapAlignSub, eGapAlignIns, eGapAlignSub }; const int kEditScriptNum[kNumSegs] = { 4, 1, 6, 1, 4, 1, 4, 1, 4, 1, 4, 1, 6 }; const int kGoodNumIdent = 30; @@ -1006,7 +1009,7 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) Int4 num_ident = 0, align_length = 0; BlastHSP* hsp = Blast_HSPNew(); - hsp->query.offset = 0; + hsp->query.offset = 0; hsp->query.end = 32; hsp->subject.offset = 0; hsp->subject.end = 96; @@ -1022,7 +1025,7 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) BlastScoringOptionsNew(eBlastTypeTblastn, &scoring_opts); scoring_opts->is_ooframe = TRUE; - Blast_HSPGetNumIdentities((Uint1*)query, (Uint1*)subject, hsp, + Blast_HSPGetNumIdentities((Uint1*)query, (Uint1*)subject, hsp, scoring_opts, &align_length); num_ident = hsp->num_ident; Blast_HSPFree(hsp); @@ -1031,56 +1034,77 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) BOOST_REQUIRE_EQUAL(kGoodAlignLength, align_length); } - BOOST_AUTO_TEST_CASE(testHSPListSort) - { - const int kHspCount = 10; - const int kScores[kHspCount] = - { 10, 20, 15, 100, 21, 40, 55, 30, 90, 40 }; - const double kEvalues[kHspCount] = - { 1, 0.1, 0.5, 0, 0.11, 0.01, 0.001, 0.05, 0, 0.01 }; - - const int kScoresSorted[kHspCount] = - { 100, 90, 55, 40, 40, 30, 21, 20, 15, 10 }; - const double kEvaluesSorted[kHspCount] = - { 0, 0, 0.001, 0.01, 0.01, 0.05, 0.1, 0.11, 0.5, 1 }; - - BlastHSPList* hsp_list = Blast_HSPListNew(kHspCount); - int index; - - hsp_list->hspcnt = kHspCount; - - for (index = 0; index < kHspCount; ++index) { - hsp_list->hsp_array[index] = Blast_HSPNew(); - hsp_list->hsp_array[index]->query.offset = index; - hsp_list->hsp_array[index]->query.end = index + kScores[index]; - hsp_list->hsp_array[index]->subject.offset = 10 - index; - hsp_list->hsp_array[index]->subject.end = - 10 - index + kScores[index]; - hsp_list->hsp_array[index]->score = kScores[index]; - hsp_list->hsp_array[index]->evalue = kEvalues[index]; - } - - Blast_HSPListSortByScore(hsp_list); - for (index = 0; index < kHspCount; ++index) { - BOOST_REQUIRE_EQUAL(kScoresSorted[index], - hsp_list->hsp_array[index]->score); - } - Blast_HSPListSortByEvalue(hsp_list); - for (index = 0; index < kHspCount; ++index) { - BOOST_REQUIRE_EQUAL(kEvaluesSorted[index], - hsp_list->hsp_array[index]->evalue); - } - /* Check that subject offset tie breaker was correctly applied - between HSP's #5 and #9. */ - BOOST_REQUIRE_EQUAL(5, hsp_list->hsp_array[4]->subject.offset); - - Blast_HSPListFree(hsp_list); - } + BOOST_AUTO_TEST_CASE(testHSPListSort) + { + /* + * Evalues < 1.0e-180 are considered "equal" to zero. + * (see blast_hits.c:s_EvalueComp) + */ + const int kHspCount = 16; + const int kScores[kHspCount] = { + 10, 20, 15, 100, 21, 40, 55, 30, 90, 40, + 150, 40, 100, 200, 250, + 45 + }; + const double kEvalues[kHspCount] = { + 1, 0.1, 0.5, 0, 0.11, 0.01, 0.001, 0.05, 0, 0.01, + 1.0e-181, 1.0e-140, 1.0e-250, 2.0e-180, 5.0e-181, + 1.000000001e-140 + }; + + const int kScoresSorted[kHspCount] = { + 250, 200, 150, 100, + 100, 90, 55, 45, 40, 40, 40, 30, 21, 20, 15, 10 + }; + const double kEvaluesSorted[kHspCount] = { + 5.0e-181, 1.0e-181, 1.0e-250, /* these two rows... */ + 0, 0, /* ... are "zeroes" */ + 2.0e-180, 1.0e-140, + 1.000000001e-140, + 0.001, 0.01, 0.01, 0.05, 0.1, 0.11, 0.5, 1 + }; + + BlastHSPList* hsp_list = Blast_HSPListNew(kHspCount); + int index; + + hsp_list->hspcnt = kHspCount; + + for (index = 0; index < kHspCount; ++index) { + hsp_list->hsp_array[index] = Blast_HSPNew(); + hsp_list->hsp_array[index]->query.offset = index; + hsp_list->hsp_array[index]->query.end = index + kScores[index]; + hsp_list->hsp_array[index]->subject.offset = kHspCount - index; + hsp_list->hsp_array[index]->subject.end = + kHspCount - index + kScores[index]; + hsp_list->hsp_array[index]->score = kScores[index]; + hsp_list->hsp_array[index]->evalue = kEvalues[index]; + } + + Blast_HSPListSortByScore(hsp_list); + for (index = 0; index < kHspCount; ++index) { + BOOST_REQUIRE_EQUAL(kScoresSorted[index], + hsp_list->hsp_array[index]->score); + } + Blast_HSPListSortByEvalue(hsp_list); + for (index = 0; index < kHspCount; ++index) { + BOOST_REQUIRE_EQUAL(kEvaluesSorted[index], + hsp_list->hsp_array[index]->evalue); + } + /* + * Check that subject offset tie breaker was correctly applied + * between HSP's #5 and #9 in the unsorted arrays. They should now be + * in array offsets 10 and 9 respectively. + */ + BOOST_REQUIRE_EQUAL((kHspCount - 5), hsp_list->hsp_array[10]->subject.offset); + BOOST_REQUIRE_EQUAL((kHspCount - 9), hsp_list->hsp_array[9]->subject.offset); + + Blast_HSPListFree(hsp_list); + } static void s_AddNextHSP(BlastHSPList* hsp_list, int& score) { BlastHSP* hsp = Blast_HSPNew(); - if (score == 0) + if (score == 0) score = 19; hsp->score = score = (31 * score) % 100; Blast_HSPListSaveHSP(hsp_list, hsp); @@ -1093,7 +1117,7 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) const int kMaxScore = 99; int index; int score = 0; - + BlastHSPList* hsp_list = Blast_HSPListNew(kHspNumMax); BOOST_REQUIRE_EQUAL(100, hsp_list->allocated); @@ -1139,15 +1163,15 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) BOOST_AUTO_TEST_CASE(testCheckHSPCommonEndpoints) { const int kHspCountStart = 9; const int kHspCountEnd = 3; - const int kScores[kHspCountStart] = + const int kScores[kHspCountStart] = { 1044, 995, 965, 219, 160, 125, 110, 107, 103 }; - const int kQueryOffsets[kHspCountStart] = + const int kQueryOffsets[kHspCountStart] = { 2, 2, 2, 236, 88, 259, 278, 259, 278 }; - const int kQueryEnds[kHspCountStart] = + const int kQueryEnds[kHspCountStart] = { 322, 336, 300, 322, 182, 322, 341, 341, 341 }; - const int kSubjectOffsets[kHspCountStart] = + const int kSubjectOffsets[kHspCountStart] = { 7, 7, 7, 194, 2, 194, 197, 194, 197 }; - const int kSubjectEnds[kHspCountStart] = + const int kSubjectEnds[kHspCountStart] = { 292, 293, 301, 292, 96, 292, 260, 260, 266 }; const int kSurvivingIndices[kHspCountEnd] = { 4, 0, 6 }; EBlastProgramType program; @@ -1158,7 +1182,7 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) BlastHSP* hsp; Blast_HSPInit(kQueryOffsets[index], kQueryEnds[index], kSubjectOffsets[index], kSubjectEnds[index], - 0, 0, + 0, 0, 0, 0, 0, kScores[index], NULL, &hsp); Blast_HSPListSaveHSP(hsp_list, hsp); @@ -1167,31 +1191,31 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) // Check first that if program is set to PHI BLAST, nothing will be done. program = eBlastTypePhiBlastp; - BOOST_REQUIRE_EQUAL(kHspCountStart, - Blast_HSPListPurgeHSPsWithCommonEndpoints(program, + BOOST_REQUIRE_EQUAL(kHspCountStart, + Blast_HSPListPurgeHSPsWithCommonEndpoints(program, hsp_list, FALSE)); // Now check that for a non-PHI program the routine works properly. program = eBlastTypeBlastp; - BOOST_REQUIRE_EQUAL(kHspCountEnd, - Blast_HSPListPurgeHSPsWithCommonEndpoints(program, + BOOST_REQUIRE_EQUAL(kHspCountEnd, + Blast_HSPListPurgeHSPsWithCommonEndpoints(program, hsp_list, FALSE)); BlastHSP** hsp_array = hsp_list->hsp_array; for (int index = 0; index < kHspCountEnd; ++index) { int index_orig = kSurvivingIndices[index]; BOOST_REQUIRE_EQUAL(kScores[index_orig], hsp_array[index]->score); - BOOST_REQUIRE_EQUAL(kQueryOffsets[index_orig], + BOOST_REQUIRE_EQUAL(kQueryOffsets[index_orig], hsp_array[index]->query.offset); - BOOST_REQUIRE_EQUAL(kSubjectOffsets[index_orig], + BOOST_REQUIRE_EQUAL(kSubjectOffsets[index_orig], hsp_array[index]->subject.offset); - BOOST_REQUIRE_EQUAL(kQueryEnds[index_orig], + BOOST_REQUIRE_EQUAL(kQueryEnds[index_orig], hsp_array[index]->query.end); - BOOST_REQUIRE_EQUAL(kSubjectEnds[index_orig], + BOOST_REQUIRE_EQUAL(kSubjectEnds[index_orig], hsp_array[index]->subject.end); sfree(hsp_array[index]); } - + hsp_list = Blast_HSPListFree(hsp_list); BOOST_REQUIRE(hsp_list == NULL); } @@ -1204,7 +1228,7 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) BlastScoringOptionsNew(kProgram, &scoring_options); BlastExtensionOptions* ext_options = NULL; - BlastExtensionOptionsNew(kProgram, &ext_options, + BlastExtensionOptionsNew(kProgram, &ext_options, scoring_options->gapped_calculation); BlastHitSavingOptions* hit_options = NULL; @@ -1220,7 +1244,7 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) ext_options = BlastExtensionOptionsFree(ext_options); BOOST_REQUIRE(ext_options == NULL); - BOOST_REQUIRE_EQUAL(blasthit_params->prelim_hitlist_size, + BOOST_REQUIRE_EQUAL(blasthit_params->prelim_hitlist_size, hit_options->hitlist_size+50); ext_options = BlastExtensionOptionsFree(ext_options); @@ -1240,7 +1264,7 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) scoring_options->gapped_calculation = FALSE; BlastExtensionOptions* ext_options = NULL; - BlastExtensionOptionsNew(kProgram, &ext_options, + BlastExtensionOptionsNew(kProgram, &ext_options, scoring_options->gapped_calculation); BlastHitSavingOptions* hit_options = NULL; @@ -1248,7 +1272,7 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) scoring_options->gapped_calculation); SBlastHitsParameters* blasthit_params=NULL; - SBlastHitsParametersNew(hit_options, ext_options, scoring_options, + SBlastHitsParametersNew(hit_options, ext_options, scoring_options, &blasthit_params); scoring_options = BlastScoringOptionsFree(scoring_options); @@ -1256,7 +1280,7 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) ext_options = BlastExtensionOptionsFree(ext_options); BOOST_REQUIRE(ext_options == NULL); - BOOST_REQUIRE_EQUAL(blasthit_params->prelim_hitlist_size, + BOOST_REQUIRE_EQUAL(blasthit_params->prelim_hitlist_size, hit_options->hitlist_size); ext_options = BlastExtensionOptionsFree(ext_options); @@ -1275,7 +1299,7 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) BlastScoringOptionsNew(kProgram, &scoring_options); BlastExtensionOptions* ext_options = NULL; - BlastExtensionOptionsNew(kProgram, &ext_options, + BlastExtensionOptionsNew(kProgram, &ext_options, scoring_options->gapped_calculation); BlastHitSavingOptions* hit_options = NULL; @@ -1294,7 +1318,7 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) ext_options = BlastExtensionOptionsFree(ext_options); BOOST_REQUIRE(ext_options == NULL); - BOOST_REQUIRE_EQUAL(blasthit_params->prelim_hitlist_size, + BOOST_REQUIRE_EQUAL(blasthit_params->prelim_hitlist_size, (2*hit_options->hitlist_size)+50); ext_options = BlastExtensionOptionsFree(ext_options); @@ -1308,14 +1332,14 @@ BOOST_AUTO_TEST_CASE(BlastTargetSequence) BOOST_AUTO_TEST_CASE(testAdjustOddBlastnScores) { const int kHspCnt = 10; const bool kGapped = TRUE; - + BlastHSPList* hsp_list = Blast_HSPListNew(kHspCnt); BlastScoreBlk sb; // sb.kbp_gap = (Blast_KarlinBlk**) calloc(1, sizeof(Blast_KarlinBlk*)); // sb.kbp_gap[0] = (Blast_KarlinBlk*) calloc(1, sizeof(Blast_KarlinBlk)); sb.round_down = true; - + // Check that NULL input or hsp_list with no HSPs do not cause trouble. Blast_HSPListAdjustOddBlastnScores(NULL, kGapped, &sb); Blast_HSPListAdjustOddBlastnScores(hsp_list, kGapped, &sb); diff --git a/c++/src/algo/blast/unit_tests/api/blastoptions_unit_test.cpp b/c++/src/algo/blast/unit_tests/api/blastoptions_unit_test.cpp index d002cb00..c0ca089d 100644 --- a/c++/src/algo/blast/unit_tests/api/blastoptions_unit_test.cpp +++ b/c++/src/algo/blast/unit_tests/api/blastoptions_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: blastoptions_unit_test.cpp 462040 2015-03-16 13:14:29Z vasilche $ +/* $Id: blastoptions_unit_test.cpp 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -306,7 +306,7 @@ s_GetInitialWordParameters(EBlastProgramType program_number, LookupTableOptionsNew(program_number, &lookup_options); LookupTableWrapInit(query_blk, lookup_options, query_options, blast_seq_loc, - sbp, &lookup_wrap, NULL, NULL); + sbp, &lookup_wrap, NULL, NULL, NULL); BlastInitialWordParametersNew(program_number, word_options, hit_params, lookup_wrap, sbp, query_info, subject_length, &word_params); @@ -1321,7 +1321,6 @@ BOOST_AUTO_TEST_CASE( testInitialWordParamNewSomeInvalidKbp ) BOOST_AUTO_TEST_CASE( testRemoteFilterString) { - typedef ncbi::objects::CBlast4_parameters TBlast4Opts; CBlastOptions opts(CBlastOptions::eRemote); opts.SetProgram(eBlastn); diff --git a/c++/src/algo/blast/unit_tests/api/blastsetup_unit_test.cpp b/c++/src/algo/blast/unit_tests/api/blastsetup_unit_test.cpp index ed722069..c25e5c5f 100644 --- a/c++/src/algo/blast/unit_tests/api/blastsetup_unit_test.cpp +++ b/c++/src/algo/blast/unit_tests/api/blastsetup_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: blastsetup_unit_test.cpp 500367 2016-05-04 12:06:01Z ivanov $ +/* $Id: blastsetup_unit_test.cpp 512603 2016-09-01 16:55:07Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -741,12 +741,12 @@ BOOST_AUTO_TEST_CASE(GetSequenceProteinWithSelenocysteine) { // Check that there are no warning BOOST_REQUIRE(warnings.empty()); - // Check that the sequence has its selenocysteine residues replaced by - // C's (positions 10 and 15, without counting sentinels); + // Check that the sequence has its selenocysteine residues unchanged + // U's (positions 10 and 15, without counting sentinels); const TSeqPos kReplacedPositions[] = { 10+1, 15+1 }; - const Uint1 kCresidue = AMINOACID_TO_NCBISTDAA[(int)'C']; + const Uint1 kUresidue = AMINOACID_TO_NCBISTDAA[(int)'U']; for (TSeqPos i = 0; i < DIM(kReplacedPositions); i++) { - BOOST_REQUIRE_EQUAL((int)kCresidue, + BOOST_REQUIRE_EQUAL((int)kUresidue, (int)seq.data.get()[kReplacedPositions[i]]); } @@ -834,8 +834,8 @@ BOOST_AUTO_TEST_CASE(testCalcEffLengths) const EProgram kProgram[kNumPrograms] = { eBlastn, eBlastp, eBlastx, eTblastn, eTblastx, eRPSBlast, eRPSTblastn }; - const TGi kNuclGi = GI_FROM(TIntId, 555); - const TGi kProtGi = GI_FROM(TIntId, 129295); + const TGi kNuclGi = GI_CONST(555); + const TGi kProtGi = GI_CONST(129295); // Use values for database length and number of sequences that // approximate the real ones for nt.00 and nr as of 12/17/2004. const Int8 kNuclDbLength = (Int8) 39855e+5; diff --git a/c++/src/algo/blast/unit_tests/api/data/magicblast_paired.asn b/c++/src/algo/blast/unit_tests/api/data/magicblast_paired.asn new file mode 100644 index 00000000..8465cd9c --- /dev/null +++ b/c++/src/algo/blast/unit_tests/api/data/magicblast_paired.asn @@ -0,0 +1,50 @@ +Bioseq-set ::= { + seq-set { + seq { + id { + local str "SRR2833414.2.1" + }, + descr { + title "lcl|SRR2833414.2.1", + user { + type str "Mapping", + data { + { + label str "has_pair", + data int 1 + } + } + } + }, + inst { + repr raw, + mol na, + length 75, + seq-data iupacna "NACGGAATTCAGCAACGGATCTCTTGGCTCTCGCATCGATGAAGAACGCAGCGAAATGCGATACGTAATGTGAAT" + } + }, + seq { + id { + local str "SRR2833414.2.2" + }, + descr { + title "lcl|SRR2833414.2.2", + user { + type str "Mapping", + data { + { + label str "has_pair", + data int 2 + } + } + } + }, + inst { + repr raw, + mol na, + length 75, + seq-data iupacna "NATGACACTCAAACAGGCATGCCTTTGGTAGAACCCAAAGGCGCAATGTGCGTTCAAAGATTCGATGATTCACGG" + } + } + } +} diff --git a/c++/src/algo/blast/unit_tests/api/data/magicblast_queries.asn b/c++/src/algo/blast/unit_tests/api/data/magicblast_queries.asn new file mode 100644 index 00000000..7f4de89e --- /dev/null +++ b/c++/src/algo/blast/unit_tests/api/data/magicblast_queries.asn @@ -0,0 +1,74 @@ +Bioseq-set ::= { + seq-set { + seq { + id { + local str "SRR1561624.14400126" + }, + descr { + title "lcl|SRR1561624.14400126" + }, + inst { + repr raw, + mol na, + length 49, + seq-data iupacna "CAAAGTTCTCGGACGTACTGGATCTCGTGGTGGTGTTACTCAAGTCCGT" + } + }, + seq { + id { + local str "SRR1561624.14400656" + }, + descr { + title "lcl|SRR1561624.14400656" + }, + inst { + repr raw, + mol na, + length 49, + seq-data iupacna "CTTATACTGAAATATGGGATCTACTTCTTGAAACAAACACAAAATACTG" + } + }, + seq { + id { + local str "SRR1561624.14401073" + }, + descr { + title "lcl|SRR1561624.14401073" + }, + inst { + repr raw, + mol na, + length 49, + seq-data iupacna "CAACATGTCTCTGGTTGTTCCCGACAATTTCCAACACATTCTCCGTCTC" + } + }, + seq { + id { + local str "SRR1561624.14401077" + }, + descr { + title "lcl|SRR1561624.14401077" + }, + inst { + repr raw, + mol na, + length 49, + seq-data iupacna "GGTTGTTCCCGACAATTTCCAACACATTCTCCGTCTCCTCAACACCAAC" + } + }, + seq { + id { + local str "SRR1561624.14401721" + }, + descr { + title "lcl|SRR1561624.14401721" + }, + inst { + repr raw, + mol na, + length 49, + seq-data iupacna "GTTCTGGTTCTAAATTGTCTAAGATTAAGACTACCCGCAAGGACATTGC" + } + } + } +} diff --git a/c++/src/algo/blast/unit_tests/api/data/pombe.nhr b/c++/src/algo/blast/unit_tests/api/data/pombe.nhr new file mode 100644 index 0000000000000000000000000000000000000000..28bd577e73171295e888eb10dfb6a2c41d19a41a GIT binary patch literal 124 zcmXqLFlboNAmtdGoRL|TU!0hnoRL_RpIe!nTC7lzpPQ7bU}6_SjKre++{)zCVugbI+@w?mOLL7@SlayC!o`R9Fj)IYap_zh$iItI&LVz#SI0nYaxvCJhYVKsHU=5IFWZ;Z$0^&3f F4FIb)8utJI literal 0 HcmV?d00001 diff --git a/c++/src/algo/blast/unit_tests/api/data/pombe.nog b/c++/src/algo/blast/unit_tests/api/data/pombe.nog new file mode 100644 index 0000000000000000000000000000000000000000..e4342d3b5eb4173360f9ee6286514d5721507544 GIT binary patch literal 36 YcmZQzU|?i`02UwxV?%`)82$qR01C7O0{{R3 literal 0 HcmV?d00001 diff --git a/c++/src/algo/blast/unit_tests/api/data/pombe.nsd b/c++/src/algo/blast/unit_tests/api/data/pombe.nsd new file mode 100644 index 00000000..3b8485b5 --- /dev/null +++ b/c++/src/algo/blast/unit_tests/api/data/pombe.nsd @@ -0,0 +1,2 @@ +nc_0034210 +nc_003421.20 diff --git a/c++/src/algo/blast/unit_tests/api/data/pombe.nsi b/c++/src/algo/blast/unit_tests/api/data/pombe.nsi new file mode 100644 index 0000000000000000000000000000000000000000..1e9e1c47f6986c54d6191593ac9da19660707306 GIT binary patch literal 64 tcmZQzU|?imU|<4bDJTu%J1{T^04Wpzk~aZjhrHx?0|R3dBSR(w1^_W;1B(Cv literal 0 HcmV?d00001 diff --git a/c++/src/algo/blast/unit_tests/api/data/pombe.nsq b/c++/src/algo/blast/unit_tests/api/data/pombe.nsq new file mode 100644 index 0000000000000000000000000000000000000000..aaba660d77214eeb98292272994e93fbce2ab5b7 GIT binary patch literal 613250 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 MfX2`{Q*^3KKtV9=U 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⩔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�^#xA*hKB`Is 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

epP% zmP*fvLw;AwOZ+>xM}1Bx!M<^<#K-fTb;OfB51^+5;PJKfQ*VN-4;~lYomzltS(CwX zl6Se`??|drv~MAxoZ|j)Y9&z+=E}EjGkMT*Jy=Iv<<2VZ z4>(>z%ew8*R9CWW@IHyd^i6rxooz%ckj;)^F3ORDV=(Z z9TWWD*M?UoT{tbuA{TXVqx$6(i3}XE6dyk|FgX3FJ06cbBt@^>t&Xt}O>2NIBqm~5(lK}g6&V!Qhs(h6&ct=PcExD*hb5}auVVc)Ugtpbx^Qe0KC@#@?}e_eO>0CMdAa-y+bq) z=bU+K$neQ8@9VawzCL;D#$6nCZIwj{kr>yrLgBFeBb8$B1_)= zxJfs}r=kYcmrwx#W4yAc_)U))ucR~Fl`f)m>X>qyy5V-skImc}tMu3t=NY;$IWfKE zbP#m-nJ|ctFMwE0VUj^Vd7V7Boq$uhzpxK!@53pt5K7Ox?o#$9F2|nUhnNf>Q1j(V zUe4U&sTMzb-_4g9!$snYVcos^MP1m%Td$u7H9hGO_K`v*`v8d<+m}S``o&6elGf1@ z(^X~6nQG!}b=$4J53Z{k{tY=U@VP#{&~%G(^;X}tQj;RY9W{-=Wy|8eqv2eoy0EQBK`YhAsW7 z$7bPQJx>0Hu$H~nN7>(8WkoqiJzZSv$Kemhum8lm8bcBl0;8Np^QIvY-C4x|~{s4$ZiDXl=GtS?m z!H-X#)SX@v_y6y8{r8GS{`c;}waEY1hyU4XxEAt{75_i2cxfXO>(yS3n*NErhcxq(R002JDVr!DPOsQlf~ z@WZC09Z85=);&=w`KKxJTb$Tt-m!c@7Gvej4?ApC6Ap?q4o72$B+?=2kj!SYxh(uq zNvwy_G;`s1a%rc&7Pc4-~vKfi+kMg?20Bt=;AMB7X4zVH} zOc8gbAjgci@OR^0+N+1A%K<*IM(s=yIJTx)6tbtK$))6EoZt3}{cS zsA9g@U*Vc0yf6-J?#%Jh?tc$Gx=oumIg_I@dH^|Y=pLNL@<`!-M_SXJ>fz4#SaEU5 zg4;dKM^fc#wQnC_Bj5<;*BAbLKv>e=*U}QzKrmd9;rW~dxIpXUn*R{VMNn0oRX_mu zw5%t+7`Jv?L{S5e6;oS>%G7E?D%q9&8hA}9OA0cXnfpko`N^swRX}wACxZD+lm>m; z6>S)ANgK(`ja>08W&Bvr6#4T{Ny7&6hzp;qb&A~Sbwfjw>Dv+%Oyu%_-pWu~t`CEJS1aP12sdOk?>wmJZy~wrGn7*B{ zDSF_y1-xG4v#Mprv8yd6`7Tk*;$_Y-D*dsCEd1+vj>Sm2*z?pq*#yRzhD0Ofiv0Fc7Po4Rdy1i5q>3=FgT@jF4wv`BoqAr4EUQbKKuckC-H4Hq7d(0iuZu=YqS^zK>BMHGXaM1+BDixy5{k2f<0z%lV{fGDDn8fkBV z&y-<$H?sV}gNqP-VvAm-MuHkZFzPoF{Tn)OZ#nKg0p0;ufg!$9rh1hr^hM^b&JC>JoRpo@f6_<2MP3pvQ~v@dYRC&nd59 z+4cw6T40DaB}aKWy&(#zcd4Bd%I#lHGh0|G3gY311xE|8(=_g_4-f9IxI-Dn(tDTjIpPg_||CbZZDloX6o3kE&$yfB%RW&)%v`huCbM z!$VNEj*{Bw0rQY9X&Q=!=z47Z#0jnNMR4O)KzS9apg&6#6>Ple8uZLZMQMsrp&MC0 zL5p%{Sv%Au5YzB++**{$B%*qsZDfV@VhRXWwh=D#-J_Z-j3MN0dNQOT#$d+YMpWI_ zs^&LFRabx_(f@9$?~f0s;Rai|$(RnMgH9w;M2y|^Uf2z{nYf}&*R`J)_^qCQcWqmA zynq1Y+GufYt0LIQuburSWS3P!w1+5PT|xuuC)LtKhNApC%=h}%{BymB?py3EU|bXEzVUl~eZ2-eUsm^+|m@m=|y!Vg1k7LiVV zR#b4b_VXt@CXSFVow5}+@z?dc%m7n1&5$M~KeAfSnmc}V*Xb+LYyWElv;V<2o0;JH z+WDeeCZgnnsx_+CeEmfd{rrZSFgL6#$*qai!C~88&%wHTp79Cz;FF%Y#+z#q_#szp>dW}+w%y^vI?ZFO@nF1Gos%$2U`LJ#dHG z9i5v%j)$+1wTuC@i8zzprS510d2)E2!9aayNO#w?(vuj){#U)a$z~Bob*iBI%ib6% zG7=qA>Fv%Kub@tY>qr$})cj^6in6T4b;MxSOJ>{pxd7ZI+B-dk#SQ&Vz#DD1$ozhp znyaGsX>DRfFiZbh^A)uk$2~|;>0y3{)B-Q5MQ==I)38Y#homA+PUA0guk^|#1{nHW z1Oi^f!&dS=_voxrQMi{c>y?VbEEZ*L(Ev)ClK_1{!g%s0HJNYj*FET}Esq@zH(7sv zmJxK|uj1z}V$}!pY*roL((}+|$X3&tw+9>Jfe6245v@{-@p_tf0oVH;j&-RNuE0OB zgmD#e3SP!fz#3b$(Mr1*%Fabk2p((J~53@zBGLU(14f~7`QQc|zv`zi!_ zBCDq#48Eel=J?)Vyz-l%*c2sil%i$z)Hpg{Bg&f1M7%nWmasG2;jNY#oA~L#7TqfA zRUqdGA0i*#aMAG4!<97c#9o}|m@@j;cRA&w!A&YHhbq$zWwCLZrU^*VJ3kMASrXUd z7RX{wfQMj8^+M8C#Xt_%1A7`RTiCo!BOWqqwVZ+l zf6+&JR4^w{O#l^RN82`RTt zKvx%?Nn?6+|1i?)jELun06P&XZUT%^F}%4+7jYnz+3Opfe#*`Ymo(8Zsg+f$ZbAKF z^U!0E#b%|mWm;G)vfm=9MG*PB<;Qa@*R7gERpHi|>o(XJXa5;s)>Q&`1y#stdps*# z)&Tb4Shve5L(Mbi;?C5mm(DPY|6vl)op5a%#_ud;fbj9A?Jy4H#H0>QBj3L8MK&uSMChk`3}{>rcNFqi#^_8ppk$6hsxmx;R6~(7 zJ@yu7iaLPkG3cdVg(ubK1FQ!%c)B$3*^~B6E&7Ik?9)@jJUBo6P)iQkH z8km5-4ASiy1(Bh1muwhx00jksoGIfv8_>`HyD|aRQY;yB%8P69Cz1|Q zmx(e{q9)aX&7KPL(O0q30=7kg*8>lw20K2_CdL$mbD<|z7su<%z7~cgqf``3Nan%xI8U{g4xK(>vs{!dWkto%LE|x>@j0uNWGrjgv{AoPI8RQOch%1;?JOgq;MSX zkr590m*O=VjmBoSb?pYL5b^G)p~qNtHMk3gH)vuz`ZL3Cl=hOXE|u+CCj>8EC(%*X zkL05?7_J8xTAx;0sMSfDl4MZ0OcXTIK?rgK)3;b{8ot?elQM&f-1)9;>Dy``eb^q+ zTE(w%N!{T#)#9^s0b6O82vMlNnh4ZcoiIOj0!iojPExOO$6ry?*gintGeXSUrdG^2 z*QR`GA0|?i&L(>Spa|ASkDYf~>qHD|xTyYD9TQCEJ3S^yXzqpiQPFMj7lh&?>eyNKpA$chh$zQQdiwwEHd-MyFhSC{;FQf zHYI8rYwUAsDGvhH2AhqSot>g61zQ%t%|SI?gHX)PdQgPn&nRTpK!JMPr<6qhN7O$~ z|2Xh@NM3mKs()Y6saRtCCwEHU-14Iz-h*hGc{rW+NsrxbYW=f)Y{Z1uq+WeI5@(LC zAHg;Fx4EhgSb6+K(>g*yDN?F%@iHJ`$C=lZiZHMjY-E{ga&3Jmz-GrEe#61sQZ3di~g!1V??LUkje&>*It1B->}n346C zk>5(~uNEQXIpww<$wj<3n6f2w(_&e8v`RND@;9lf7GbJG zIg?jdtlWUuH-?NkoWvv=zd(6nt8h zK=ovZBJ2$O+%Atpcs(k%t$?c!`&7m&(LOdKH=QkTVXCutan(TQU#5lz+fSi@zw*~W zGiM{-Z4c3s%V(%(rQ>ZF*{<>ZTwNFRrRefCkq54uZphrd(a_^G~*9 z5diV045$}SnW>9N3V$OIeowx@r>LRXjXnc|EQ$Szrq&8+B9Z-A$<+oQByzXm;SYI zr^Ye+)v;i~=)?A+)~6GYmXXdKpZhBE`YT0ynrc7U zbz9qVVx|^%AVxbz=cv?F6*#~ma{qS>y2leLzX(OS(sx7@$;;$&Mru4&`-@7w~yZ1m0wKk zb8->FaXu8FQ?V_M(AE`u++p!!V}G`Bi&TSM&x4LnUvnS~hoiOy09;)@Y{Q~B{Kp;6 zQ9<0S7LSq;I>y;DoU_@etpA*9$u)^&rp=mXT4x|*l0+fKs}XwXZJ*l^|k#MKl3Q( za%3d0!&WcMEOI%El%VZD80|UVM%Sxz+pL9m-E%0rP-|w1sG~zbB;m*j;Q(?^9m^tA zz1Z`V<=0?*e$kzcEBX^uVL7DEeVjq@ykJmLsZMwW7WM(LstvQf!m?1%8-Z;g3t)7H zNxc~=8-hHaPw1@b*`V~+=%u53P_Egp+Sj?X$EUY5j~ z<1?hyb>O2*-Yz|{IvS0`!DL$7IEReTFy=ZM2$Ey;&VjDDN>~a zUrBYk=!=2?V+^Q>2ewtfb5+@;?JExYibuh9o0deIKTYJVR6D7HRiS2PDYkjwvv$Fi zz4ORj4<{}go3HL0Rc8ozL;oobFXP{Z>@s9@_3yspC|nA)rybpk(I!XoM#~ROmi|*2 za(FwurZKAn@#0S9=?`ls7YftjqD#|S@Um3$v= z0A7!7{85*5!?IJAMAEMXqpvci_AHjYm>0QTN=%8)JUh!MrX*h)%*%_A?9XW9yQdDvztkK9 zGu~ZKfDYCFb8%$uHZs-KU1-Rh+>|r!{N2&SOl1dKtm(HQPax@FisEvDPsq$bS)w># z=VPlomwJVE15uivXdllB=;w}*_pMXgf2a+)TH%PPLo%DU*`ETg@p7VzD7Ea|A9%tQ zFKCI*xU|aQa@U2#M3dE@C&?yKMyS53$4-mqM-)MQ?UoqJ7Hb22#QHSNyu`R%R{D08 zqL0tzuOF;7+_31IS{I0f&6Oxrp{rJ^)kJ&zN-joUN-V#$G5AYE^7uVOS*i{0*Cgs> z(aO5p)=oIXrA8w@B`KFY#>WH1g_4x>Jpr?>^Ep?zRKO{<+EIO7U+>y`HQbGUpOPI_ zef0;!%c_AW%m&=EH!k8)M*iY3XTo~vsQue#*1d}b*EB7MR`Hb4XMfJ+*ZNvhO7D|c zA|qIrdI|rl5SG7)Fe2{Lz2~?9AzxV@z6-f=h?$uPv3)7Qo{^B_`FtIi1Dqj559HE24!y+zX zGmE{uQvE>7Q|>;_2R$1kk6L;j-+@oMSbX>cMNJD0$RaXKaXSa|1CwFmGTVT{0D(XN zg5{I)$;poql*l1iJyPzIsTE>@D-*==N)Yb_q2Nd7_CTxQsp@Y=;q0|p=a;C9n`sywSWBhBqT$9d;{P2X2*B3JBsE-ArkFl+B;l=iJ&g(jb1 z{kl=&v}ZMsuEVBMSU@~+;Is+W4 zwbp)D+M}^cH6JlBy=(eGrHUJQ71pK_Ljn{+K?m>J5vL7@jZTs4<*rE?^2yOiWf)2X zK+k|CMonWbX5~@{%b4D$G>pAf%=W*X2$477y>`ziD;EgN04CA<0-+?#L-9!66|0ys zG$*Rrk=z<<)PjY-BVp~j?U5B3-onlSmu2xL;#DB;r)8KG`_YD#{X#-%Z>N4cy*?yd zv{TJ5)f+`u3D$K(N<|=0D*nbM#|v&n^+;=Qzk;Nc2#j$)s`P3`pI>ud%ahy50k@N5 z>cpJ;$+4erFCh+$~q1;)pCap@X=tHh7JL>ic~()af)8pHKe8AB6Cm&4Wy2G z*R2zd9WQ@wE1X-{1O`>`BpGSH_;I$3#N@kG*2d%4C24U#%hKEawM0Iqjf5Qn%aAed z*c`P@TRmA(Oxb?x0kOJ(&wELqJ){%}z1J=gpI}bBpR^2^Un3TH>vBrz=LlqAcImz3 z%k`&RG6ChBek1yYZFNg&(~(3ug_=`~P~+LG)iR+NsWq&KF2D*|_A_-D@3Z&8{!N>< z=|w#)E-xKucZqZw>!>zqQL;w5P)CZ&6V#+PCu}%ukQ>n_;5B|&m}w!^NgUEHxqNLt zf~LPPzuCbt*!}!d6RxAICO7twz+uGmkjcXiCBB2SlkJM0Wy+Q|om;J>OZOC3^*D)4 zN^#bV&{5`7YA?Ju#Kyjj7rFSE6TY3s+Jqd|Ch{pm<)xWX2uqF&v}Bz*1>$WwTr<^{ zuL`Jhrpa*4jG<66De>*F7x%~JerDwUIe?hf{C`I#*8d5aF8l|XDF1^@C;x*?wf}=m zD}Nx|t;dnvbiVZvR3*Un;y1XeYxGITD$m0DlMP!}3 zzdv}xy#!^jaVarcI-zFPUak-{%pioOdYq8*2 zCD$Pu$YxRzo1_f~L>tm>%??x=MTr2HPQ8!3|Dl~Y2gE|TqaK}oQZRcwV&FPMbX9t04m!B{K4$xosaI-bf5EBJU+~M0qcI? zrKaW4KEi~fk|zVEw&^x>EAyqfu~Yg^e9F?#xUA67msg!GpMf4UZNcv1vZmO9+Zb+l z`G`sk@ku?#oZy(wfsplIt_#`#Znz7;5v=u`C=EYD9T2Rx4CmV?ZJP23R(Ry=ui+I_ z>of$eRclCJsct>@m(wA?^eala}w z+uS;dW<{dIGMOAo0~O*-h8QZpW?vBY8KqG2RuE+a)Snle<;oHxe|3DMB>iGzxIYn` zE+1CmIt{??5AE$xnrdF^=HPIh?x4)%#MJ=@{>7!rekBv`WR=S4AV+xUU8p;&o}D7% z(otuq8K58{ZMuZL%y`T&ZerOwT&x~2r;QCS3wJ0Z><1s;A-(zNwu4^^2#v(-jrL-V zWGf3$88=A+F82_A^?En3_@SGn+HZ*5^6_y(*2IoSA2%-MS4PK>5H{A0+rOss-;W_u z#8eI%6`;aNAqg@7Wer}pW;G0qxWa@Zd3lrSSwpKOEoGPnQ^2_suy}mHOwu?Cn{BKP zR$x?du~_jgaRd$P!#7gBx7VK(rP0hhn&mz-iP5XH0;g_XS!<3u2K;D0?g{54G@ZU9 zs=4&oYAM&g82mkR9H6R_VYtz(Nh2qsb%bzYwla9;ue)=ZLvGC-tOXQBaxXF@%^SgH zKA=t1{nV;ryTSOo{}tkKy#R8f+Vy5iaUGbtd8|XsvU9TbUYNQm;HK@2&jS38#l$2E0gANRn>$6o2r8_BpgQoxVJae-vt)qN%0h3URh(-| zazk6E2Dkeb=_i|P{pG)sEf+=Eui~pUDzZoK^r6i?6OyTHQLOeFl+A_T>V6$+aSuF(uav(b@=iAfg=ZG25 zXSj<4+kcGiIQ`VkDb2U!B-@E9eOyYTL+HUK#qKsN{4!A_LDNF;h=fM{g}hEm!Wk{m zqolr<#8DsUVfZ%R*J$uN0&<7pa|AUl0e_a5le5JSxt372>{4wFpBj81}wy+7JeGE))00D~MNyC(iu!p9mhJ#8# z?pAe&O+nAG8&HXv4urXXHVotek=%S*P}OyQfEw7HcBj&9sU9eV#Oup~pf z8~?;axUlu{l1a7~DF2_I2c) zEkrB}*uNW@PJESi`_mnLB&tODd(@=9Q4JP)2U*MRzdNy57G`;y2xbRk8I~(*3m8gP z>|eu-KVFb^S_={gAKQWT1KGlS?!ADDK$^EczC)BedN*_q-bRURRSHSGpsEX-Y5w`{ z`xpyCjgRpkIF4zLP0!<8Vh#+TIK`$^iH+p|GK8&sW%$8;cF`n8dTQbTJvu7Ue*#Yy zHu!D^E*b&wDU&HA<2R`X)}M1Je%xlLy^#RwufJ^Q5PeDZ(4>0vSiohT2Q zw(`oEjR&J4Pc)Gzi zeQESxR5ZwG2Gk0MyzNj1JU&oG|#`;VgKNa^_$yXjdNpBg*`tUA6<52UZe6^ zQq4Dj-rJ({`bZJ2dn4s9Cyb)$AGOaxqwltI>3XVv=NY^z&S5m7e7@-f2(AljZ9*+ZeP)pia#@$lsVk#hj)iv0U?ux|E?;F!? z{c$1jp|%g-@KxB1D(7QL=rsOP^4>(Iw}9jgsYl))(mtS@ik`UtLi=`_#74*8AqAcu zrHiCBOZ>5%JY6Q4KPq%%A@e8N!f~swqI*(e<|0$hk8Lqa`Kn}A=P-wQ)!X-~W%O?a zf*I%EBk)>R0HP^wPsBH{PHCcdm|OKpZ5Va+ck_HX-v3AaY(&Y}Q(mokSRR1GI=EiaicJFy|nsEB2 zfb)*0)LFY0-|(AAtWVpUD-OP%uGx8{_pL_#`nUC7i~RK4>y~mi z*zvB0hfCy_$K;bgAV=DXdxr@gtybw8(0KS<_qz<24NrdI;$FQ)Jaukwdz3}Ca-$un zZvl`!^)n9TwpUHr`gO9obI~KqZtdmsc`=t;m~Cyl<<511 z*gK4dGhSI*ju&-mpONygf9&G+!{wh*h9sB1U>`es?*{7D)116i3TN!y*Y=Zq=Tcr=UYdQWU0Qu@9ay-b01U~4TM~NL%P{{P?EzIi>|F;#N*0Cvzn2eH zW&3X8X1w~33FM%VawVrfZ`kFP*~A>0gsy{mjrsh)k*yn9c|#HQ-Lv1nM$D`5W-&%6 z&39u;Hm#TchSz5lohQglC5*A&sK+IE^;uY{a}%9#p({ z!|{q4dr3Xk(oWo%<8SZ3nw?eR9`ljFz{}Ad&7a@uT~yiYMd*(!~b2# zzT8f_Ef9Z0pI+TfGa-Z%6RHxtH>z5Adk> z0Jn2CV&?=YA4@RO%pND%e&~Z>^nBC^4j4ticTsgykRA*DKBY)h#h$~Gizz||+y@>CZ=Kvrb(2rTsZ8+Qoy&lp=$no%q{b!T32fawhU|37yWj5>M>92s! zLZVG(&A%(vCNj&~x%;+H`QXs?f7V}#xBUJHZ&0?g#jUL6UoEmn&wqlob8$nHRQvq# zIxBB|B)_(o3T7W`ta%%L6y`i0x~S|2R#!Wf`H#GNh_9|V11I-n@gaYA(^lCSlwG4M zQy#p$v$qjE&{e6~2tmprBWL4Vx<#(+n;dg}4gRm~qNqf4sMqd&hhNdbsgVN8em;@x znDh2{s@$G^ZyfKtqGEqim8Np@akz z?`GKouLfAQT=0dF1c@s8VO(uBLPrDyBVS+-k1!HJ$S$NFc~9Ja^k~Y0!mc*nPbUgQ zCMm2k;jH=;Xd((dJB2(Z81Z{C=Lrevar*KGVt09Fk6o)h)fdr}adn80nKEjI`r!eZ zpM;Kp-h9SS3Nh}Pr(N&Am}m~5{v;WXr-q~}j||tUdWGAD1(FQH;caht-?fH#@t>2f zxJf|h85izZv)NnLIx_z!@~a<)`UvN+ze2`|DcZlNF)MD=ePz1-pe9#16tDeVBM@c^ z;db~5x2**ynd`m`4ZT~rtQkHlK^;eQx3*24+xG%7o!?3P@sqwFU~9@JIp$m4;uqg~ zM(n86dhYDmQp-_w?JR!TyR74%yAXT4o9_3T&6J{6@Tc7~0# zdO^g2H*+1E*@?it(mAaddcJkj7&_;+899vX+$5J(4!_hdIv4HzW))QHd06;7g4esX zXxo050r0NKzZ03H>m8f#r{sr|vmx!yDIgS(G zV^^g{oNKkMxi|NnrL&~(2U*cf%uSEqJfGc81b=TGCmbdPJATsbjE}SIB4aP9BMxkY06j z;KTE{Bjt=a6M3LYO)@tf%x%n0$jB=r?!}Jca#I8Cg1(%sRz25x6ud5cZJDmeE-;~f2M;$^vox()R&f2=S1M?OX{VsEQ=K# zMwMa5hSsKj%T6g=^ZEh){?Nhti4s6DYtxGy;0kv(m^HC6yfFAiIQ1x6GCl77o0xir za$ml})Zm{MwQM}K@OxAeqeCp>j0a_0F#)z-F8HE`dU$zYlBxvbELW z%VVGOr|^_-7tbj~yflJaEy{&xiSc#jbVXR%1s~-(u`$afkaeX zpF}hJcr*A7u>t%Guu5|b2Z7QZ^48*Z6{_Cs`RJuz3y64<@<|&OXQQZd(9`8B%T#d3 zQCh-{Ug+Gt)fc{=EHUN;^n|Q|zNK#M0vLO|ciV?F72Q!P(~<=;N1+3hyQx>dv%f4w ztiZ@tw<3-S&9X21{Dql$nON4dr6Sb4=ZvuTm_~y#<3yKvntP2RU;nU5KdKH{D189NOe9XT}J3hDHNf zT`y`J1WH%cqe8rQ64Q#(r+iYLt8|uP*`bw^A;~en&ko|NgIV^vDh4VvQW-iX%vFDz zT5o@tbMO(29NYXYQhZlmx*|$>MedQc+D$M^&E9`+jEZ`mx>Cs|VxplN5_6D^v(tTx z-#h1g*v_eo4nj{j!=z3*UYq0%!=Y4oze8*eH1)(hgzw-*QIElw`0ol>F=xUfiTQiz z$x;JyU+V4tw)|fhz6^h}3Ln1}uMK(UxUm55vPY*xSFFu<$i8R4LALLGv&HSacTs+w z2>#PvemN7~)LUQVfRpU5*sQ^ws~9peYVts`w<5E-qsWstbut}Zx5sYbBl4$D07a{g zu~+X@-@b^zT||Bt`A923UQ2+3g(oa$Nbu>%$}_<`z+UvivW51bW3;?*AbvHtu5s?} zufN@Ys=I8l`TCkZ)DzsM>rWk|&t}cg{;}$=eg9^}%E~(;B%`HI^HoveC)!sB(2{dj zste|-fN-LR9xwx?nntC+@SRP1KY#)lLrlb-MZe8cZwjl|4tgRUw!OOou_@q&0bivR z=Yy$dfG%2zyIOk;w510rU4W6 zR(>Da08XCQTk;+b!c#qi?+-S8w!G(g-wQ{NkD0*H-QzydBiavP-hYi`WXS*Suw3i? zDUlo7ezXrZN2O!2-Uo2-jj6o?Kl<+eVb0RxcVelERbm>5_^y$fWC zw5x*F2k(F4t2A{LQ?SwiEmei>HB2|mc;c!FC4O$F>0S+f>5E-p{Yi}mwNpc)4YO2Y zoT$1~&vgT4#|M8sabQRO$#&<1bwBTYS@Gr7kFpz`BS%6f&9v2BQO@aB?PXi#JM8`3 z8fEfH^^u1957yF7L&p#28@{|-y=FQ1rYu_66r9xYzbHEUN2d4x|G(@t44Vl>C0i)U z)fgGJy~b4JvUE=8e7c~E_c@(+7j!7ZY@t#vrgTo{oMaAl>b#G#qI7|cDP(M!jxMle zigK~BvCS@CU*A9B_0#L|xIgcY+l~A)r5Yk0klsrRvvkM4T%ro zvbic4i^K}knZSh!6(bhqddoen9{EGiaV&J z7tb}D0ktFxFpCy>+X}&TH1fPs6%JEGU+32K!#^?_cG!%|iquNnq9~rZnL>MK^r7U} zKOY>2zSmfu)v$V!!i}pb@be$Dnx*vp%EHI6*7jz$&)GhwixWR867CG|-4GaW5V3>a z&N1Kw+Qr%~V|!L@n#au;&wZ~v*N$HF>?|GW!Vo)%J9Dj*;f|;gd%u||8;4SL*0k2y z>Eh1|Z-@?sgl1_{vpWY{LH(gYpe?2zt`x(&5xMyAgrD|D;*;-Cbm>y^J!t0V=Tu>Ql6eBgXBnIft5y%EKkn=VBcK#9|J;NY!w=ha z&`f1*+6Qonw#7i#8K4*dua=8it??is;;x`nP!q7S$-jbYRhE7g?Kw=#bijD!twSCN z)?QC3tsM6p5_44tT&|zc+L<=ECo_rP+ZgO_3=|s%O9+I-U5y9v`mtSSt@5?=O~Z+} z*NVp;m^cCD2kTyfY94t#e*B8w3WH*DD|EbHv7bU|8;nX(duWI?260I-qiBzBk2By7nUXG?<#J&QO>ANuBJsIkEdjMTRB%;vId$D zfB588nRLzn(#Tt#$MAHW^ca|2bphveKY=bg8xv_O~Pe{ z4(6#nt8+9;{MDEn>+`)C3m8J`UcT}GT(xPVHok-npGpFM_^+A1$EI_w?G#o2S^rbQ zXQdO`E#U?dps)I1`ZCLMZrNqEgwJov6i^(yOMUgLj48|Uxz z{|_+PwU(#k0{Zr3=nK~ zhttoUOk&@RapI$6TpEecvHuY1V3&O0X)3p)>lG>7r5u#`D>h&WNN{;bbTpBop>)_l z?6T?8+RaNIT|QIPj-2opBDOmyUfc8WUD2Y%PE~u*$NU2TIorK!H+Y~$b$8=pj2S09 zDPw%?KU2kD0k`!6lS?W>YjCAr&&aq`Zhn+O@2}~e?aZu+OTYc~9*ug|qnxKOwf{@E zo2m;Q4_1QLyLak?4o!vu-@|Nf)zs}UuUhKFJ4+xzcg(0PKlJXpmh+hhbm?cEJaum@=?c zufqaE$hmRiyrju2bP9%%qd2Kcm({@@N2cfb+ggbOl39T>)at>td1C;DFq*D@;z@Z9 zrwQ?hB0(39Wyw)!bKAosf&R{@>Bp)<^tj53EDsy`$9GfKxx5#?odJCf^Nl#!UD#i} z-r^>D+xmVm#0+fjHn|jo53yZUlusaYwsjwzm+<6e$l3WL!A5EG?!X(*u5z&hmIuurZq(Y!hJ<5WlLEXDg}xTvA~?3#f$h)pxc z7ril$6%K>mmXkwBn0RYjDp|YXcv1~%(A{+TsF`&JS!uc#CR%ZJ1`{oB?#7&~=7b&L7?wjBe87@OVNluZ01$I>^3hghYB!m)gMsZMMnEu^X zc~8}_$=C3YkI2`lW}ZI5@u%`t`aDcR!Kq~^f+>4}*xXX!z~%>G6KqoY0rR#X2(KSyX)PkA@;x)1>4BkbPSYR?qCxJTr8h^>;q2pR2wp+tYD7TMSmE6@z3%fx;H^pV<9kx^B z_>yT~sf?QlE7fyz7;i;B{6S58emq#8b~uojNg!6-8A`BnB71EBzYdiq#ceu)Pb!== z;#FsyeLlf@gb@aeBtz9orvI>CMl7^6cNXu&(~r&n>=1k|>12RdxO^dH?ax4sVNsq1{44c?#w1QvzpS6VTvDj~|x_nTDd&SL;KdaNv zfAP7}Wp6cAWjEnrUKtv-60rI}UOqSi<&GJjnieK(6D8ZHUV{tmgHOfOK_967tq^3)ahD9QF_XKS?h`)th@ny#Gm^kr!=p6jOG(%b8d4{;fi znbO^;U_5LG+&w62DcW2X>VA7VgRDIYPfp-|SpeH%pZ%)RXhY4o#vtb(c(&}D8Q?r$ zz;4l~m1%2!4l38A)oGm4@=dHdY#HjBvTvWA4%np1oPQBC2eam(iN|fF@yb1AHi~}W zT-h%9XTvOye>Cm0n(8I{q2Nb+rXL&EUJ?e>+RxTn;zLCs=Bka)9{Ad#eANFAu#mbE z7I0<^zQGf1JbOJ2OQl7VAWj~EHas~QiWKi80a2CR>w1Kb80x_trc8}-1mNIut4CFL zZH^T@n75N2GhBl1nuS8Xjeol@OVwKT`Guqwq2&RBfXCUI`(I-?4HdY`9XqmfLmZ^l zR)=Z9Ahnoy2`Qy!6o_-Wt^Iv<>Tg(VUGk26yNh93lyk~Is$YVVA6c%ZUX)va!8F2H zl{chx5FVoW(4fkG&RZJ?`J_jF{ILg-sULnp#jtfBe%@sbJp-=kaIH&U?_cV^Wvtjz zIozM-R&W-ZtWBg|HuqWDUrCCjPOc$-BybE*K`SzLWMr{E3@80kq$8UewvwLE(^x2=G z@cR2L{iV2~=FEP2qW5n%F{Whs!-q2Vw}+C(RkbVp{(Zjmi(GTKZqTs6cSswOe34Nw z@AC2#F3&&PKS6LY$w^|YI6s4#E`+m;J+ub8phkpBv&2`S9HB4W5|~8tvD{KLO`2g7{k1$ zIXz>*{^;Gj^W|K^vYm0x{K%$)u4Yl*McS>TI5wW@AzcH zbK4(@PuSKirKuMCmVq}rjeaxj(IHf5%FC_)ji{Ky+TcI^1&;7ni>T2ppWEVwlz;Qq zI*0Lb3I-vM5 zZ20Z_39Gl)14R_lv`K$E@p^C4!3XeEi@@RFFDFm>3?m>!oNt1GM_YN%GJxTjE}%d`A_}9 z@>1LDZ56G*=(^@IExyn?rPn{|`KlSzT~t#-uu6@7G<7L+>e`Zmuw7QFa=Rp$x(tfS z&D?p!!;kDX>2~?w$J5!S!s8RkX-7;x8Fy}~BR5#YBskrGWnSBz&l3sFir>e06a%jj^L^R{|!Jy6X|)7&-RcOvnDC6 zem|?@s09kawL+mURI{mApB%Z9-0?Y?o|dAJ=-F&2L)DR&p-&!5;w$k~mIt!)8(7h+ zcRk#@ti<5(*>gao0Y&oUDUKfCIv511Z>tTD*ej^nBB+ojK9%#*yg!4}f4u4tdJbCp zAKb1|!t=yp6oLA0qSmF6_52Ncyu$;FU_ix&HMx24lJg9Ya!5`_-TKj5Ug8rnfta=d zSNOZzH}K+Is0axtkp*<-fjO^i(LX*I`gi}Z-ea}DoXBhUIsV}Dla`cO2%^&0dLtsn zg!L*Hp=G1ODTp4R!kUf!dBJ-?>zSd#EC|xbDyAwhgs78ZGnb_U=fxx#+1D5-Uv1GF zWb;s=k{4wd$gxyo>wA$#vn@J`t@#bwOE`;!%iED3E;DgqlV~4 zSZVYEZ49okkhOHL{@|x2wn;7T=QxhiwY4E+w{cw8aQE@HMU>$IG;PM z=ruD7?hwkJr>uWMRx%SMYHem*pJf(#VY=NVpfOO@b*m^w&^JM^Ad@ycpKZh{Xw8P*O4XKyF=T6==+8LOd7h=j(atxQfOTMmlJ$^^ zm;~7D3#>_gG3ONOjK&b#rRr|PYJ_6I7?=!X=A&1{()_l!o5M+)bT~eWb!Gr2kEMt} z(ZWC3X=Z)JF`YsY5ovIkTzA2f(l&0#-R>aHJb?_5uPv&qRLUhTg<^paQeOj}?o1anK z@=1CaABjH(k0k~hARYQYd4UyZggZPJ;fB;}JxcOmUd*}9ZbqTnC*&of^TyQp%_J<= z!q*0_H>35>@@-qnkB#e8%kEZ)2*?m!K7`h5ge#E_G)U|CGn}rpmTHP}Bg{xy9vbx8 zkHEQy0+pv7qT$Lv<8eFNJH9vhsk@8=Nk1c0?N!jL5pP7QN&HkdhjwURVQ}r{pYi;Zv2H9WqBFX0pjjvfdz6uj_q=yjj?!<*3NT>JPt1j+KsRZmF| z@`raCID#H(^!>VNfzEAmipH-1GBxDHbB+Xj%ug;tbQM~uEc4uniu z8JS$KCXPKaK>r?>SC1L5IANvM4EvzHSjv#p%B#Oagg;E%Wr?!NFNB?Rav=8>maRqq z-}163-NotzY5WDm8E!-CmfUb zT*00E#c^7;j=a*9LALqvPqR|L9ZVT?t)!fG0l_NG&<4UozRBv>boTzAvOc0q-Vl@%C2LYWcc+BuBwja^!KA{`6PFK!9H-UxwP^W+$w@lxKd=S|%q-cq;na#z?N}7*C?pWR*HY52f zR516k>+s7=@n35pBW#ZnNrx`N1tS_`*~mrpEd9aj9-qbbEon&<={<9n*>2w=}UR zvoC|L;q#jl)fcx{KqwHW;5ArRU>zuo(1`=8jra=LPCE}mDt|~cZ0j&%`!iwPTFvi& zP=$-pOg?w=K5essY6S}eh{@fE3Y2T9+aR-5){mtGp~znt>^3(zZk=U`)}o>VnrM;P z$A)u^aU}l*WlOqVv^f1c@Pu7AS$mituF|oWLh`t;&asrKo}==uit9!}et~Csk$P*B zbLcfJu@I6up6}7hyr~29lLcPi!knXhU}4w)oiM(S1k_T~*Q0MmIUOCGH+u>!N@|k~ zCyQ0+T#0n4;Gt#H&iJU^#y?Y|_e+9kX37_;xe3u-Q*7hY!IeW`mxo_K-ada}dCb%( z-M;c|2(c4fE2ZD{HQPs*C#~y|bZJ;OHjmunn9xbgXc_z8mK_-ex*m>_Cq5QWLYCAGXzvj)+PyR&q=11qAFoc3g?tN$ zSe5{dB;T&RXOF_-cE(}T(W5{`F=4sHCS0;X4nG2<*`P0Qb-=v~*y#0NQcbzJ=Db?H zA>BI3Z1Qp#o+=_p_~JQ-@KV3L7Wvo!FfHsA@Z>+Agr`5}2|-{k81}i;#dR-K>s9i9 zz?XT3bl0dvxTp=C7Nww*%qaXOEDWjbLXiZke}q2KxCQjv$pMHJo!1E!*`*augW>QE z$ZT*Zh=NXUYS$T(9phHuLHU(_yX=b}0Dh0mG6#DV5YYftkgdNh#M<8c0V=@I1-<_! zBodiw0s5 zQ0T@wxE@!DT9vZac9olRG~y}3j$p?M!1FmxjomClOW>(aYZyFldGYlRh1#fBpVQNQ}$55`)cL;qTDI;o=o`*#@^?hzeTxT%n;irdPtakkrB29GV{9W7ipa zZQ1J3W$?W+$AGm4Q|?G>gT`ou@7U-My?4Jip7)=>Q@LkHg*4$@OSOy2 zzmO$5H+Rg8rUN4rB1Y|FrNpyG99Mu^-ohsM_6@0OXR7;jByWrcJ4hed+)42bI7cj; z`Nhma9X&CLjR<~2(W_KJDNBQ64rJC5inL+^W8(Ku-B;qqy=z{gm>qTm>`7n+0V^R9 z6Zyk5q0mK1aR~6UzKY7=7IGM{bJS)I&ojC4$bUKYvm4HZ69vX zz6Y0q;w^7QoIy%}wBFM?mBeN7YTuSp+5eW}T4gLK&B)?JfnwiLTvw8kp$4u#X5kFf zP*Abm#>m?6&6zbLg27!FY--(c-Fm6`MUA`MIvH0urCo-SZB)e}C9)p|XdcTg!+X5T z`q4=PdK|ZFIyT#5Nn=~SP=Y^=d|CpC+q3}vA|u{_)|irYJ}tWUHkI&_FiVM2=ZN_c zFjguKa)?eGlJbAGV@hcp1HAB|dXr=Lk}^%5?s-EgX%=g&noq6uYOo0s5nDEbA5~WK z&YN}%5@y7y)iYlH*{e&5XxA5h4v~&OJ=%C8x^h;S^?wDZ*EOvt;zQx*t5{}R*}6@{ zxs_Dfy@4Jxe9BhyEG z^>O%HV<~4L+@C?al-Q&bYHYs=%rb-7?tV<$`!>YDloLdr{+boGlH%#I7v8n~{#XnW z72UMkh?0XFhD?C!kQ%{ia!X#QIi#0iHPojr8K;nAam@{!P#dvN!5`hM!yM*}w@+CR z6dgW~ErREtOT?M7sUn+~luPh-O>c0b@qc2<7B#l%@#IXkq-MjJTJy8Va22#<#wy{Z zMD@|BcR9k!gFz+npYYbUIz4CSxk3q?TF(1`viw*GGp6NX z{P>}C-}j}N!bgUF!9vDv7_MNZ4nA5W+^Mx@0O3In$Nf36rJ48t6?+9qRfEG6tSY62 zmDBY>K0X|2C~)|*oa%G`&n0g6u#X}!IQ+;@0sl^sfH{#}(rfT>u(KT)d z2~e_9iJ@4gyKM#|O{I|zO`n2fb=}#hpJI;#AX)?;F?%RhT3Nj-eD(95uE~9zDO-B* zj`L5T?I>aY7`7XQCZIvA1I~akStA-(ZLC+Lt&$iWqUVp+}zfp0waqie0K}o{xUx>^y_+W zv%cFds3e=%i!ue$*w(SU9`Pb6JpQ-X z$i$yJ(mTY7Sc08u7#qRzu~et-;5isl!SF`uFz$^?Y&MQ)8JRa`NXuUu);&}Z(D{h; z@Ei4Xlspy>hAtES4IoJ1EAkhp`SH^Vjd{50Dc7zWg(yX#u&)7PU>p`!0w`S=QCCEpl)J*uKg0vB9)2T`4PvTHWz^V+g|AuprseWaq?4*jo=*CYS)&RSFLw*t2Y%HQYANfWJ{r{IlI)CZgiD%s73xemL6N( z5kQQxrRAk(2jsmfot~wB>EcxKTy<8EXM$2spti40xMh1VE%3rw0sQ(!*ZoB%ju!y^ z-Srhw+HIx+l(Dew5@6lRRl3X;uXqRXvoS5;z?04M>j=oyOpsxq0em;G=&giyM6kUH zW&+{gLk>{}%-HyrAwKz%0aKB?41iJfV^9&G%RT4 z8<6XsysnQZT$lB3XMXs^V6xRFkM+*4BkrvJs=dZ@8d4CxPx*HZh&;%svou;{jdCwbPmY&F`u15j-3mDiZjdVRtWr50q*A?g#p1 z8K(S(NlYc{CW{&mn}!r_L0U##i?H4U28t`@N! zTzGxN@B&{U_B&yEZnAZ==`|uOS#uBsVNHNv zp;2LSo4dfO#JhDdVWG*;hXk{=kc0|8?}M0yPvI!Xl9*%k{0NiCGC&THd5&_vkrITwPk3iT=)W@7$2q2gl=JK5o<7ck@Gw zHtTEqddmI*gs=WfYdA|tZ>0ilzp9eaY0GNrAd_u{`;ExF?yeFN%OgYS7TB8p?JFB% zHukAWskVdVRNh6?fGFj*^dmo*njg`YFhS)J1Jsga2XS_#0m4bdgUjZ^*S5}Ym)3(5 z*U-7YY;mt|96HCOksSvaI1l1x(M)-;d=xKj^1jsAJx{y+=~}$^X5~EzZ~n1Z}U1={5GS zt~rRR@$P;h{@3=tL!6!94eRjV?AmYD7Yfxl{M?@R-|1E2J?brp%&p!H`@hs$Pv~DI zTA#R|U+L{foc!nTtC5@^kzpLu^>_OoOAHB@n?^4_pYX$bSTVH zu{e!~H<&Nwlg2+N977M>7|`w6XLb{@Bn*A{(NZt=al-MJ5wzQKy8i(iy z+J%t|Vit+NjV1a&Y$5E%e8zPaNx<$fy{)bf-N;B%QUG>6# z5_pCom=Jqd$mmg=JPZ47_rBlANjm8;?;7^$WKibYPFS&AX}UOV5b0W;&UAFnNjthY zdCZWGVNBTf{6kt#YcdUyGlA=Mzb-v|J~yY?NgsEr@SFz(V9VFI^Gb-*{YMfhf26cd z`u+t?)EEtuU!Cp}63VHKgPIS1ys-Z$8_l|pUVhw>CZ!i@hA85X&Q=F`GPjeYWNE#r zIee<=D(%u{#2x52E7jOOX?w_T0|m`{LLj%d*Q9Y<1|eq$6I<~DX%m98JZYC?y&x@C zu}_+ht-?fBBW-@$z^~5gUA6;q4o?)@xHV+`*cjh+z?A)4$UfCuxY9hMU5Zf}At|(L zA3K$jH>eItUtus(b+cqw50J0*tTvL5W}Pz=imXu@#RIZR8G ze;%>r{`n(rKo)1qEV-Uu5>fZLWWk2~ zwjj81|9Q*&1WjAaQm%=I%lgx4a#eXCfZoop%=X}3DXCgtQm}r)EMB&**!{j=;c7mJ z>%Lu{c`k2k(g;@3E-bw^XSp0)hdNr1K-zJln)c@6|H8|5o%I2@va0lJqwRPW3SseG z1$yHL7CR*5NIW;&^%~y2pwFgoN05d4N!xTXK&r^62-I1o^5fETKPtA4r*=i6hF2Ig zQk9PGA5J$BO~dkNY>+Y4( zq||S6u8&58W*b6yjFl{Wt#8iO#4be3l8tZPY-^w(E{X2Y{t@A;DcdOnIYgy)MMV8l z+l@_MWZyfyFfTi8rlw8Q?UWzTx$Vxe%lY)?Li6~fRu107Zb-Ojh>n8)-gO`qNnf<& z%%Q}^VMi`xoa`C;_9)0QzvB3-B|1kvVvKRfc8?r*kxL;r__!j}3c&Unh>E@rJ(ezqRbZ}Wi2F+&;pSauQ`{U`>SxQLH3f-` z0vFbP0_U`bN$+n+Odb-f6ogD{*Tt3Qeo4ht@2WiL*!}geJI@n31s;Kdl1NdFd@kUI za4X%Hc%~1V{?YiTQu~PHps$Xq{xxK9{RW=9C%82KU9lk1+S%YP>Vw~blZYu{`0E9R zovc{ez@zyHeMX;{`1w})xiqj>gWZ?AeU1!`s$4!8H4+tFNBI+^Qkud|gG{g!VHFSRkKWO&7y;hz2OE43IiLt!wF1nRJZp-+D2tPcKTWgyafm_tn z^xp<=e=)Q8x&#-adibOLW#pF;S@OS+sf4%FY(= zH*@LqU2I*Y7D!v@zArh}G&eX2?a2o3sA{TPV?-5y2tM~3%ouL---Jo7%NDn@$GtW- zd^&s|E^LuZj&j}JUmDM=mh5x?)Yk*qm*rReAAnL-R_Dmj`frtcWcmN=c%6lYp1A)J zqB)Z>G#bOKf|(d=+4TpXIcH2;)G|L^T|w8EJG~_Z>HKuTq%FH{zm56QFVjyd%wx3x zb^a6u<4GWSP1{aCe1_XyCZk!a3=1n)iC)@{TSnQjCyQ%BmaaGV%%T#L?MOA1lWkR` ztimu{!~ZGZQ{X{o1FB>s(Yol)7P=BieBPyBNK^P z=cBj-oSI!>GJpsYU-F4@Mveh8v2V*orRt5QI$(n$fzq^t6+;(1sR+0oYPM(z-O#PT|8bZE#ZW6(FCx&Gu&kK@#w}0Kf-zrlYA!6U+ z%o;Pv(_^UxBs}vjt}NEgpr#46ef=aOHb>r;qdqn?3-)X=t6&M!66!Szi@QDs%aUGx zuil?71A^a0qr9&y_P6Cs4^!fq>F3_$j^C13u!m-DuI>L8+qEHfO7t@1P`->Leh)`u z*|l=;2uB+lup`!lZ5Ee08xD+NBXbO#amT#RlC$0`%2nro311ncs=y3EXH#WuL^-EV zGd)>j>d+XP4k@?7oG5A)5_cqk(d5}5X_jyS)3vHwZd#YuM&iHK-Jw<*&{?r|a)a;N zb8ECSb5F1Z^gITgjn$J&?GjCE8?XBFSgOMfS71(hE%6&s`2SA!100%n8^ZSs)qnc( zCd&gUHkPVw{m&4Ex`h+jsx5o_+lYOkHZc0PD`)r8&p%(}a9vhe8bXz-lh;jU=-C5l zqRYA|j1oDf>Bvtxk8dn0wK$Q-tJV8=y~(^nt8yje~rvRX&AjZHA(uigyT&XR5;+E#l1Z-{*_Ls~@NS4dSTXmT}O zzC88<67&myG_ysl8nzsR|0z(O?;v^wEIaYgUtPXQx1_@BZT}94 z<9pWWylZS`J5YY{Yw4hRS~>@-tDJjbKk#2H?}9tcy~dsle=RKh5;5(}v}4*Cul|() z)W<-iyN#lkND#Dh?>D4(`TS2bl{|R`Z@)L};*{-?aPKFRP99&@irLhg#dTCBeth(jG%p93_{{9#KRh zH*z=nmw(+1cD=+xK!GIlMa=`WyoME**h0c0eA5)+%`{x(Wrtc~Q>xjvCU6p~2sM36 zj&Wr<)DabKL;($Si?A_aj9@W4At0KpGVUHFrUpE@b9ce*4@rgJ>z&4IFkq9dP7Aip zp=(*W;KETO0hJLio4Z$iB}VYohR@SF4FroO7Q%o{A#tDDF1Z%|MnJD?9qWpAsHMe` zwgFy+gzndgN=v%!S0$9eu)}66eYb<4e!;hD`OOwV6awyEBrrC>h5#ye2I`x|7cuNUePyGkl?1gSh52vwtkEUY*UCMdeo*SQaw!J6cHS-)y zrL0TvNzkOzw3RO3!j0Gn;sgWy8q4QseBq&Bno85QK`;4xSu3$83Xbrx%0u&g5LzWk zi0x7e2*d~OkPv1BhQFZ8K6ELo`Tn=TaqdXT$E}XYbWyV@)dz_x6zulgG(vV`VZarF z`Hp9~jtSgdCqj?ciwKXVO>J>ySOJzBUir9>j)!MLDL1S&o zb{4VEZs#7eAj_7yJz(5Bo4vqMr9=5?v8|WrfTZB>FW-o@MdAhM*`} zv`z2lyuyH@2dGWZerPWY)z$sB+fOGsBm-#bilt``ZR=Y#JHVDqMMdoUszG<&v5x+9 z`*Oi{>z^yK9SWd({VY$N`HdEUXguV(it_7(kU z8i!AwKgC>IS=7@G**OJB*B0IazF#=FdF{}bgUpksda1uYPu4rJXpJWZx(0po+tR`F z9%P+`y)Vk~om_e{b&+JXpvx8xuJ~`rSz9FS1&**4Esj{3X?e{!N#5=5@QsG>CpZ(7 zyF@w`YPF@l*ItafIGSTSNYGR*p00m7;kR&~OBdWN?z`&GvT78?0L{1LU#wlSgjVGY zyKTM}EXs5D-^{;=o`5rVStbHpnAvya>Z|wy-mm!fQiy+EE6dfTv|7AT-gX}YdiFMp zp)U@v;qB;`TgE?&p07Bqx@vsS7IY3z&t}XqnQ+Ju1L~aa8V=M8#R%gX1DtKx)tA(= z>?!n9Nd*3)|Jn4$x8=#^UVIs&ku(zmL=j9#n}-bNj&;p^v^>$J&Jt|I10j9bMhHaq z5lCcutUw8I3|q)#JIba9Ppt!*i(wcB7uo9wLP^O81Zgfl1VIm2W$2EB^QhT21k6U* z^~Fyk|H&oZP;OLMgg@;yJ|6wyGZK=<3~>XM0M*K6Z>LHj&RNckpN7@SRpcepdfLuv*s%+4cI>?)6P{Ocy2=c`m7a=0^X@{u~`RtCr_#NLNO+qtnRG8 zhSg%(_a4if&HDE|Qke8#s{~UnVRn}MX7c1aT*PV$_{NGGv5IzRC|iCF@5J(|!NyDs z?>WexTuCR{x*YDJZa%zdtvIJkvL?!^BoVB0vB*=3;{&guQ)4Q7Y2N>KU*Ljd6sKVG zE4HkGwg6W`?kPEYnt~H~GgB;#=Y!wEIn&a}CeO>3(&MM%chjr(EqpkE+^bd|E#BNv zKUfEi0sodSG{M*RDZj9@XIh@`y`7VX9FW!jYgngUTd}T-s{N5mjIxg#A4)gdqZL(E z`rPETGFmT#^1*o&es-^2AI{P0NiD+{93&u{1Y^)y{%bGKM^EmaOvjzsqrhPQEw12o zdLya990r2evb3=513Hbri6>R==;kba#lL)lFUy{xj;g4aU>yLGDCA_H5Gk+H%tk1VGUGmR&XYSuW*n~8fHjI{E% ztJ~&fWTb!VlTRqe)L^wH;jP;uwC5%|3$<2s3xCWfTr=`nc7AD^CO%%UIhj(JRL^Hw zXz}(rYstPzR4W{nv>kfsk6fT%RPUt=jtz&gUM_xE@&Yu+-nH@uPofS>lQgTiW7)D* zPNzQ>EPINd@xffrt4S4?q_s@vMiz$630QR2#;4H!;%&Rv_PD*_)GW&(dL35Y06T%)B9zX zrDlg*&y13Jr)^ma1zwl2xzpOq2d%-hf<0p^+0^1**(KSz$hU4Nt?&14;e?wQYJu&Y zogYp*q0N1>1DX4Z|qC`!LM6trPFVrOleMt0u0?k{-Hq-Fg&=Tok&8cFuE>P4?OFR%@`vxPxr zVfw6W`dL&F2lr2K#5vun4}|xc`!_{oLRqT&e7RCyunz*Q0_V&u zJOP8FQH;VTlmFzwMp_S-&;po8o9zY>$p5pk#uJNE@v|i)A0Y{aL|i{k2iJ=VtSWzC zO~A7%DSEfGrGk>h&@4%7D?-ZL?JcQWJp=S=`~2aKGq>ip$6smwYwaj0(8_V- z)W(OFZZh`LQJ>#Rot?kzbe@a;2P{yFPI!bpa9)19&PcB=>61yKk<#7GDO=qb@tWa- z{vYz0u5nFu&eL2B0gNsYSF5GDL9gg;jlVD_D#Nav^BjI+z;2`N=&0asC}qJ}Rp>3~ zi&K(QG|{)2HPew9#T(T93|)ATEeg1tQ-Qn{lK%vib`f{*lFa}EE8XGWkUxzsU%zCv zxJdO5v)O=+HC%4RjhrXB5!zUH`+m{R_&@Ok8JZ#bVn#$~!`8&2s z$)?0n7(=lk@1FoRsLjS`xrPa_KyUbh{5qQxMa`0noOJsi3(z66*Yz>Aj*>lP#Os+oMWXd39`Wn{$-AfoXsK2D4; zL|zCye^GqV4mu)$vtyNtB+19-BSq(-lyR$IGnLX4NaB4q;<)}EA!s`U5IiUOM6qNq zgA!q*$+kbSWa1>BnZuU|JN5KiXky6F155qK|6uMHU?#2rk{vef^=(*?xJx7zMwoy{ zDwZZoi1Iw)1>Jm^r~+(AvK1&zE|iPrPI@o4Q}c7D=FUqPHp~}aG;e?Qo)?fjm4v)3 zQ+mIm0v+b=j%QK&T+?pWcmB_?-gUkYuB81YK}34$kVCs&E4ca+Jt@pKfw>=xt==bJ zHjq(1kT6FiK#S(UL3seEk8f6QOGV9Y$?02Tj#6XtGks(Ni^N22AV=(3<6`#}GOo^Z zW0rcd+hUoVD1zzu4M}fU#Ub_){UHkb?437F=%*zQXUAb$Q z?Qjrw)X)+5tbqPy8KHQ|XT=I(>csf*K2or@&}X|3(BSr=19&L9<`hJmc@i{ZYu>G} z$%=I>T)1k2*v1-vMHk^#M|@@JYY%jr&S$3GD%cwLSW*uRdYXC{NTlZPYCcPMa&cYd z*n>2n8c2P)mDi)0_s2IP2m`{6k*J>!|38Y(#4o9|{lf|!@)JBbVCriKx`Z}91TY-$M-S<0KZa)HN{;Cm& zLz1f-`6-&3YZ_hAip*Grgpre~vvDC3?|MmOrCepU}6UZ>Vw*8%$JBHtN0&A-GmAz;X zaz>#U?bMm6`y&2nNgtZd-<`uvW_!zG#Gj`MI7lMW<|7~v5e=TQSu`nc?QF{^yoMsT z$kV(Hi^pnF_~+$9=g{SIE-2i_aGDV}YU5$<3g>jovw;V(c=+YLxiPNfMlChg2IHO; z&SYBW*xH;3;yqk(d6NlOWs2FFi{IzxxlA&5!X@P~Ghb0WfjY7_%CyumJ4d!?S$0gG zgWc@DiTKLm_8-rrdz7D~N2F|fn_lIIQY0kY-Ri8^;|^`IFOf}HTYc)=oiZI3-5cTl z{_`|0W?WfZ^)*66;LI6#>A7m;pBl%mU#n$(uumPo1l`wAEA+1zFTPY$m+ii2cSLNn z>&G~K{4Lpr1}7W(*?s$I9{r56TuU;g`BJdWv2|1+p z`h(W4nIB)V>!|+tg|N@k1!f-i;*{9$bMw!GZ26L}2{!bJu!VsSyBvCK6Q&crPv-mC zS{1Zkn(x8habBm;2`hT>N=&dgyxh^rG~EQl)JUa@TQ&f zO{PJW!?)sqZTXp5t&gEjXW1L#c3!OB*eRRt%pfd(d3RWB7G5a6$*?eUqYHFjzRCc7 zIm%yT^Eh@d|90@eFRBG+=6vgU!&LoEm`|m~I3q1cniLXl>@S_vu*A&k{<`Rd_1rqk zu=&N0y%F~5DW&(gCU;10f^Ako&ouoV-nb89d)J5|11VkbjY|=tQq@V9dqY7SF$W>L zz^Mz1!ttF@lugs}7hQpd06UiRBBD@C^q2C5H}{*}+^M^n z>-PK?LO2-u@`0GB7o^B|t+pCNQ7Arf@TMA7XTKD9)A<^UskBmv3Jga~lK{<%Rv3qY zzXaD4d+v{Kh>27Px(luNzD{cm0Qny?gmGr63JkI(R38At*ij2^NsRGmk=#aIJcxm~WR zfCwi7)rI)Ko&ZaLN>BycQKRq8#it1ZyX)-PJQ_4eRhMPBwW5kolzfLz(r`Ry00Jt1 z9y}ay+$Ls800FAOUDd93R+sz6>UGEGB(9IDjospSdG{WNzXFi)9tYoSj*%aey+bi3 z;FwAm)yuZq%(9G2LWN2%ssuqTL=i^&@@Hz$y=?Yu@|nDwuU0>8S+VCk z_iB~me@0B7<=w+6G)1{m6P6y7DJm4ofEA*o#-yW;xC<4DE3x5$Feok|y7NmCU#ps12XPeZM8pHeMqMvUgu`Pxo&N?|3B-s2Z*y)-vuc_>PN1 zA>I40ft;8>jnc8_o}9=PY`$qTc4)CD$?jWI?1b3mYW*-m`O&&=#%~=uxFyCxD5Q(4 z{xepSP8`y$(b+KSBVQN~XmWMkMQQXUgm;_0du?oHB~Qt1?`2+yefP=XFj1M_clyoI zW`KBzCT^PT{5Vb+E`$y4bx<{Jb)`6L@fp~hwFmr8!Wm7Zy0B;(wUbWu(ny;@PNU}I zUnQxsh>DVrL5Hk{?TjKIvR08K17u$XNeQ@6(-ec}k~v2lb~?ezBMdL9U}U zhD_cAY?7nc&7IG9=kcQ@n%_Tl?N8t+JOjnku$x)yUmT*VEyKAU!9d z_?T8JF;ytYReIz?YFmTTrE+PoPy|1npO_Gqb+8~ zb6gNkthV@zk5nr+Qq(>q8nlkmh3}2ctVyEu*SJnIH9D7ZBpqHn&(v;&^CGm{^+9AC zo-E#lVl+~c&x}x6kHa&w5v{k2>ky+}HDa_~`hK{9g>dGT`neRRpdsbhD&v_KzlosT z8Is#wzrXOVDS;$W6g08n@!tHNt1Z2dT-$(XuHM&N?S`U)_9Ir~UC?N&D`73yT@GT~ z<16t)M9zKJ5~!k9r2C`~IOEgDI|?BNRthCknUwc)tJ513q<@dAUV0@)Kwp8z zH~H)1OM)XS9t6dD>av~6THKPNme{kQZQX6u2|NvkC6qMvVKBbHfR2LQ5R{A`C^_Lz z{c4fJWpx$$Pg4Tx(RjTq|3Vjei^@s?U?wRtiOUN`mgPQ3Ln=%d`gCIsoZTWJVZ#l< zP#-Fvq*q>9_L4l!QVjg=IfvK=UDY_|xy2v!IonPwkDyH`WDDXnVavzwT^#BoY>JC# z)kfG$TvulE6EiV)v^H~prc%wnPs}OmAM|6^_OY#*OTzPUe~?~v5*3m8T_YOzsjn+G zpEP)X!A8YN-w#P#Z&dXhkQf7c!q01C_vDCu6T@lRFQ43Z8v?8{Yu5OT{974-N=WYV zr*R{X%{$2EDUjHm&ifL0(`9I7HME4=FQD3ed~VkQaBDEss+BAo^g6(Xg=;4ib|vCG zC9JVX!E!jOTR+i?+<%>%^*fm!Y#?W1=IBd9>H{qeQSXO z{Mk*`ot-ijjzAN+Uw@$XeJ7hIqWg1+1}g(U7N>KkdsB6w{ZvXT%bq1aRQ0NQnIRC= zD8D_ze+38YslbW-^vKRpkv`9TDM(Q64s6M?h z%BXK`yy@zv)9+)O%RcR?5wY>0FDa~Jymv+^Cy^&B*v~EO`6%^yATH83#-aWYfU#4i z38mpvk4l6g*eSLZ+f;!`x3~3cKMysDV6Z+U#N9ya*B63!)`B%=U5a^Hg(Aw6fNqAM zXmi*b*pA?i67CSQyeCFsw4L+@2|Gol71AX#cDFS}Y2rfYeO=%`fr=HL@`Q^RHEou2 zbCu1C=~uO4(F0>ks4vS=B3*VNsg!iar z8*&un(h_P})sdpal^0i6tk5go%?iTnI94mHD=ICpWzgC_%gE*IOX{z7ZftogTq4m0 zN4F<07x?!Tj9B9_GHs@Hj8a=z|0U&5|I?Z%u)CpyzT;t<8n8gmr6xC${@A^e*dkVu z6wBfcykO_9V4I4QBDWa{zIh_`S?XHk!J(@n&n~b(92;MLcj;r@F?ar~&E>F7l|8JF zyMV&)+onn+7Wr|GgFbZZZ9=#@Fkubh=4qD4Zdbd7=d(*&q@y2`*okL(7HE-1*n<23rpBG-cuG9IyQ{?!2T&Dbg zaKlP1tN8+jQ(&yu8p+RMv*<5y8m`MM;xaRdE8a5+e(*qjz!AmkOb}jf^ALJfL5g4v zg^K@1qPd3zEtIJJ@Ux+sDGJE9!Fyu)5{Xd#Q7t)c~Y4{^o#;t8KbX8U=zP zHTV{uzwBH5x8(lavc?-djFS=b!xVmQMS++o2#A_E^{$%_=mW43N4iXKa)B4WL@-_% zVDX#%vGa<(R^(NdV|YA+pR4ugq)1P}w^o=+iG(Ik!-Y7TO~;yO8wgBP>+L=H$=hS- z%t_qhft(V3x=v$13od37@KKwR#&6lZ4H_?B&p5mb^TK1TxM?K3rk9byYC1U~hCa00 z3?nPtaFe#gwruc4BzQHVt1Ru|CpUbKyOwfnV3)#o2yC7eql_Oe;T1ox7!gc`p?7kkpncmw+uISyXi zyd{EMvq&o&OVCpdJL2Q3(-xnCt%W;uzdwHRqM!?%Pl9IMOMMm=*YWR`%W6Fdy%2od z8v5V!Hu2ud+p0Br&z#&2UoAj81?G7^J$vwcfmfk5uKVibS2^>86?(uWIo8hd{C@x|JhNOg4uB&XI7B@6`g2 z1Ws+qBS6tJ(m7ktD*VF{++!5@E^XFflE3dn5kTQw_mBbt{N4X$t@n=y^SoGStewal z7qpH@`5W|n0I|mca5%xgKuXwH)wOluKt9^-3E)mb=ZvCpb>`OtDI}Xjr-l+hYXOxG zl31GO>`Dy~f?}V1X|`yWAbw5X+X6|73JE2o$ifZv`r(iYUTLxirgIjf(Eu8aCf5Bx zW0ypqQNJ@OF0z3;ul{RIpm{3Nb(n7ePn^|jD`8}%M0lvWGdCZXZv|ZFR159~XZiye zN1jNK{F&+xCSAgz>91V7g(_NDO&Hv$w%FjXHfZqLKdTF>aNy1Ax)+xZkXTIfBg{hL zA@^p5$_ai|LS5Gk6q@`YT9NK|D|rXXHt`2K2sBBWOMU#nB=%_in__f|+E5gR#F*fB zB0Kfj$pewVli#V#C_KrEaD#@1uWK~#XZdRC6$F`?!0+80Ldj{MHJWDf)&ZL0DZY8j ztyzgoH;coW;0E<^Qg$1h@dps)tH|rDNPVpl(L<_R%gS1m zQi)~cTyKmGQOL>4+Pv&I)s?O$!V(DPgpUX|VazhP?zjB*FyX!lixVM$K<6bW=}aM` z=nQ|dZ;2sBHOVh-0}sJ7M5DiKiQ1BKsEq%EK=@2Tmpw*KIK+Q5Xj~@XL@@{E0wpV$ zNM|j(s^vzX?WTiIg3rEvsy+uI_fFtYxBk4GHRXNcqh?~s)#y~fLbm(F#>AWb2P{n6 z=VqOR7k0-!4nHxrJ6sx>PaZxaAn1NyXM=EeB6oS9jl=neoV*O&0b6MDYUh{?-mqvJ zvfC@rCgcx-i|94aC#v5uyo*S?`B6TyGtC7%Np_CX zlm1{=#?QlN1_x8X?bf zRjwoSmo3+BIkok*rYzp3l^pQXd5wYGt}VNefTJNJ)z=;yMUOR;+mEiF&X3Fr?oJF$ zHTi2DKS{f-C|2bB%;)l5r>y&@8$2?aUO&ZGGIr5}2Rx2qmhKhSGb+ojUV1?VQQ1pL zo#U5UwMXWoa+K~Xo6GLeHlmjqAcpAD^r!P7K1;@J@2c%x)7xy`8ZzH4m9>qrh~l`g zmTvz+-V<%?6GE4Vb8FkeMOu5X+LOskB(g_9R9y1W$l7U;4CK0!98pfbvrb<5?4<)j`#*;)AKuJ>^K z(a439>V(#z?1OaBS8=Xpdm&~eBk^B4E!nMjxaYB`0et`+3F1|mMkpuT<6nctL>65! z9aK@27|9kf(7$Hl(D?Efn`DuXuN+XiDu+!D<9dZRij_yFF3%AQgc@9(&?x4>dSuAC zZk2eq*p-K6Wa<>Q#khbBjW^luSk#onYPD_UMeZ@Ei_<=hHT_$=_9eK9A7Zfr-?5hZ zY=$h(b+EG^w~MXWI;neHpD;fJ@f)6q(C|mUE9$~$gL@I$t@QQxrVbC!0VRvK@rV(7 zUVc>3USo`lGrh#w-W}@k75p7d&pYS3_?5xBkA+7if205{)IKkh z*S|gkjmK7A7;dfFy5r@r4thos2*Ti9Z@aqca{hS&@w<<|CXOS^!F{2j$tU~mtChlA zo<6B46Bpl=(Ye5vZ{v#vz4i^Lv>Zjk1LMym`)0N%$EyZysjecQZ2Xr@0#yY{?8=QhEPZfNCG?RZhzP!4l#$X%HcJsO5+ zKNA+U$L;vbf^wVg>q7$59eQ5ToAJ##i-g=GeFOYe&c7NopW0u`Eq&%6OTGQie)hb} zv}_!8Drwk1TEU*_ylVz$3za4_-Zr$!K@?*J#IC+ntv$GYDdsYS^1#_SHzOXp&Mq}ph5fP5>N7))H^h{T8$-WvMD_$upIx`FV8Hj3eThBLPSMWXK!;a4{kn;`+*lMGX*GR^JBF+D zV(vIwLn@9WtCARlR(Ft=mFrtF5A$^Yi(dzSu7yEsWfoh#bww#Z&OsL1wu zhhB8%;^qcbyQddNxAjpG{@6aptfjMTqV^*W`;$i>v*v$1zEtORx@cL*xRqSHsP9L* z>?3xdAn+OZ>uF!?1ww$qDL+Tyf2%E5AU3jQ;eB96#Y;`-8<=0})BBKhf%Z%vg*hDG zcUBdFo-Z_>@|;4^w*mVWB~O&uC3y9Hp__f*4&@imW)++mL~gU;o+E*$peQfd+wv#u-TiJ z$A=gE*apgOYphw5(hZuuf~D6OFJJC+!wS=C5L0OvLI>%nt|k22G?nyPVa(}N{WNjm zQrO*W!Hb?}O?CIzBJ2NRiQyQ~0NB%J;0(=k&{wU61_IhgFqBNKzK{|A970Fa&<`*P zEP1q=H5_UI(J^XQQwD*c!3)hOjQJ-j4Shwpp;p5abF4`bbKJ8~SuB|+$fl1&;Em(8 z==2DZSQWwkkBvWIHVQ*92mtU~((mXPUvVLYU1NZ%InD+Y{5n?cO(RhkqdS|Sw8cee z0QhDr0FPDzeuWa6VxOSL3gSlB2*}`CV32s9iH_kISWFn=Ltt_rn03HbZ3WPr3ARMo z*?4yoXd|OSbRyg=I;v{5c^rN{clqB1)vABy_8cE+-+Ew{f9o%=fq)MU@8Zl5@f4U7 zh`ZD#=vI3|fonipaHuAqx+hfSp%kCjjuj(JB+k8xzz2)FwLxgu^&ikc!fb=@HHxt~ zx4DR3g&NT?Ul-&xE!x{*XOcincnFa-0_&I&`-jh`hWbBBIrEI*&3TIlfJtKdp@Cq} znB{N`laQhXhB}pLYSoff=i(Qsv~7e%DU-4m$c`PM_>zrcM(6~#ws;b4D6A~lpa-b_ zVn{4|Z=CiUShNzfLy{VyV?I5)Hho2_TGJ%n)!}0GbU{qlqg3x1`ZlKx2|8D@pFz|O zpa472fD~^d)+}DCv&e{R`8skm;f#I3REK3>^}`qkEH}%9{#n*(zE*;Eb+`&dbZrXO z=z=C+tDEod>`we=TKp>_{m~TQx}b75^m9unh;YRaIfTShYBYQFW20xeEA{Q7zXW(>|Q_au%bneeJaV<5kuAMigTFYpy3AGP3{a=}ZDBfW2Glp4cAOhrs_WAt zLRVz8G?=sBwFTOi6AyA!1fWwz<kYy zuoXKGCcilze?HNB$_fzx)nw1*wfU7ylC5s-m}O$w@0t~Ah9%}uuOT_f^@E212eD?+ zr4t@Yd<;f6S?PP>E^Ig0BrhTnZ+Dk<&kr%;9{Zq_p(+82sAin931qFr%de8|)9M`> zY}TE!m%O13$Y)eZu3KQ@)gb1D4BuQP!RB=KpimY2FU?Osg<5hUc1q$4Q8M7+&i4kx zdjPVt&1ei>MW0z7M&ye}RBYyIf(HgN+(Nm>0b#f5SAF`v)Ki7l5p%zLU*j_2bMcbf_)rn1`qQWz(FWj+?~N7P4v&o=+o>pi<>8@gN*X0 z3sca+#Uq7_J0vE1vdmm-DHQ{#g1(3Y_G3hmf~Aot=H|~_DKGTr{*VfPS{H%!sKb%E z;%fapht#fdFOv^!+z1VywDP-wvt5-DE%ub}pi2X+!eE#;=V!tb_pL%IPN(9co!vJL zF|Un<&}u^5-*n1fVelgDndWf7xPEq4ASQIGXeD?dnq84$Vv95AbQ;2+Y!c*z5#VSB zLb)dqn@mVkARJlIY!OfPdMrIAFWvD#-3HIMX;qPEb0?{g#YKdyy;Zo^1F74f3K@@T zwj8^j)`Fa%5_6C(mj5okQCYsQPOVjjlabwo5Oyje2%L4%N@mPkY_cE2AE0O}pI%#X za;pE8*GStu!U1}wKX`0(S8Q|yjpmn9&`DYP{$B0-wwsz?-y(mA_Gcol{n6NyV@IWs z&V#GP(0U-78p1pys}m$o^>-LAKx5o-D(fib)Cbp#)NL&vFkGP_OZJA~9(Pq3|n-C|dI6t{jD z3SMhTLfPU#TYb<712~t|iuPGkjwMNVT&ma$4uwqwAAL3Q$Zq&p-mZlcP8$G9s&)$x zn`nu<@qE(h=hm3`%JTl9b<(tF;6(17rGYV;EeTlMc7H^0aQ^)kulzJ zPku%138G}4l)Y*_lfm*iYWN-_+HI8o<{M=D1TJUc(AN>mMZk^@_CsFmGtm9~(auc! zscg?nnftPeIojbvb9>U=L({L1P>>sPH=sMO5)XtPRrXSPNn_!aUTd0AVHU- z49vBI)aU-a$OW-xJVk)zrjV%f_l^&Kvx1E3v4#qf`^Dxhx8QAeK|Lq&G4YI`D2Bs0 zez8{&^)#KH=_uRgrI=1}PlS5K(%WjijDS8d{6OB@hP!y8%bB;{wytj|rgwxlx#*~9 zt7f+4@UWmxY|F=T)4S6|aFKo#6JSTZ4es1erhg+bjOAQ3{&SUtz7lUILTVtsA=FEZ zA@7uxVt4Zw{3YOx&Mz`k9S!yqtmsgYB&z>BRN;+ukw5a;{oi9MZa`a*E|>Eg1)(qN zM4pg8X>}PfLqoLIio!9`aU+#8qpl)aOLhgDoz@7lNJcEsceLA0SrxAz$%7$$3mx6X zmVU3Ncb{xLhKcitWkWSD>_sd(%2T`1 z<4Z(gMJf4CW)tHWw)Z?DpIa3;e4^I~eHn4SIDggG^%^n%B(%|5+j4i|s?))6O*W4i z7faxXYh;ob;H<9VBjzQ44F5R@oAg0H=ASs0_TRIyj=g>tqLxjwF77)|y1p^Jjs3ufqWsNUPHJ??-B}6ZHAON{E3QH)HR8{5v=T;vsL3{4`Uqh zRiL1Ow9EA$%WA=QKRaaqtP?)HIkd@$;W`A^ST;u|IjlA5!aNz^amsNriP)t zh}aT033{T91#>1o%gMM!1b1O*NyZoriyr7&#KEPpb z!IKPt?ckQv+R8N^;LB$EIEKN6O{$Z|pev*BmTp21uFu=q(T8%hQ1Zfrv!as8CKc6O z?#Lu8mF`(R9lxZuh!~2pM}Fgv54XCB7Bzyv76WHU6f_D;#HMkDBNf{PwX1j^j2L{rJfGXkLwd-v|umL9|e$}H;u=kU-ZTHMrJQ}BVE8WyXy|!Et7o}hXg&S!qg_93-hbn( zwj_Xmzw6J;*yTCG&`^({Hx*xzNF4Sns-*vc<0b*K3MGyIVLeLYm7baKsz^eK40F-k zV{=sArkmy>nc=Rt!7s;KFXbky9m4tfsr$b@)t@r4FB0R9 z3LGD>>?@i4W%!cteMR3U&WMjW6GPPdZ5obVv8W<%I?ASCYU(=?zy;KHT(5>e z-{%};>z+az+<)hOfBHaCr(IxQ%-DR%e1c$LC+Yyy8N9Xpi)k5A-i!mSSGL>koyjU>iRvMqi*Y_k;IASLDLAfEkE&GPjvy$ktCuL1Q77$zp; zBvNyOH%ilm*8ecfS;g!SK8Q~R{zi_Uade#3$k?;Ju|qQ9$)WYFgYCrE(C#2)kVo7o z96D&p+xwRm+3R~Q25}Ol*6=fdRtJouKs*W=3a66qbSSH%H%C84_YuF=HnsNs3%`Hx zVAxzj`eeMW9e}4Ws8~2zpc?a)il8_uQ-n~6EyQuzP)D&z#dL$*5vO@^Sih($ges^D z^;Dz91@(StsBR`3sJzt{zqau1rbVCiL{%l07rvnCidVw6h6fllPNcGHWb{HwmJvJ- z;-qmBen!F#Ns%F6C1n&Pyhv&GErk3_}?l zVy@}+AYE-}jZFs)v5^3$N43&B967Ytpx1}p{VKq-9e|nEE)AO4gN+jbzPQ3pL`S0T68w)kO(p%nfIzG(34T19P{#vw%QA1zTuZrqA-Q##6|Jq-l|Zh|HFp)F^BG5kTA3l^Lql46|JES5Oi70LW3I!z#b~~elgivlI-U~PwE5xr zH-NF#iMaxqNsv*Bg$2Z`lWvB$W7_40OH%3~XTV;Qa|l4hl{B^1fWzTnn4VE;(86KM z?U2p0gu1hnR_{yPO|K-?sw+8lq)KYn-%*TturMQ98&P#gl^{4IW{nwzn}`?P?&pZw za445x5NzyxE0wQV8M_`ueVX6BHfWSR;Lmuy*h;$s?VU+Aewj9Sx69t~l7@FQtNZmq zpC2Ey3TO~9z8juYz(PqwEFv@pXj%6_s|Y|;6(a+9n-?$c$k{!6I9oXshUy!WCHiic ze0!IX;4l>aIJ0TMI?KK{>kb8RR3?%c$Na-`HVtn|)*pvyrfpxk`h4OsU$*9Ehm)Vq zeH7{E8{mYo)BabmCq04C#Fd^&wnMCxK$y=yW@Pmz=(SN|;+)-m$x05_a}t#~x+B2d z3QtHy0}HmLDSnTsKQUbV6CYP#T!Au|=TXOe%a%Q57feZt1#jJ0I zKo%YO<|aube#By$E$CFJ9g%%{fqxS78C|7iQ4w7pF`EC*Y+13}YK)+jdJu{Pw!ab0 zJ4(enx48IE{y|3n=sx;K^9v`A1aHrM;H_#qlSajPoZZ31G0I=+?in7qOmQ&garlWke()&0hhCET-s*ksi) zm#lsxvI@9n9sL`Wh&i}MHdcc!2gj)277O|mP<1UCh?DV${sfB`^Kt}ZBAAPFfp zWh_7g^SXLvpbI3w4r0zEV1@or`ml)+3IRtcW$HfB-8a>wHdQl$DpkNglz z2<2V@0;t@WRB#5q&{&heimwBLCfZK~4LbNKYgra7e8OVl&mD3SRbt~^Ek`uA=%3jA zHpdj7o4uHBqA%@TDfheR@#guw5PjYa4f^~{Lj3=}MRFTd4x z-Dv6t!F6~gb@O@R6<;J0kVM8E!P`>WBkIK&4{~sJb;QB_ zLYWG9hb{-fN&VWKA;E(MJza3#l%DvWMN6}o5+^R6SBb~ca-Mj+v_iiC{B+4u4`E4# zl}BN?ZTi3hR-6l181Sr4!UZ#_YU`Q`i7J4Fd^-ybeYv3rGLXOx;9(5DlduToU%Hs8%kGR*~YLwH=+gZw&7I)iVaAueQaLu*lQ$alhiiC1yXO>(@lCMYPW_=mR zabGz%Y@|ww901W>tkbN7YJpdCMQ?tvKPKqjK)hh@fC4Cz&%R(bL8U5}o(nz()DCna zW=_^UnsLaKx;kLi-vSR6G167g$e&aiZ?^xIpf&c1grU2s&RLF-E_QKfXbWrPY*p*y zL|aN$PSe|2qI3yPxscimdSgrIweBSb^=B#e$&9Nd8lBf$2_vwrU2*;OM!LKO(N+QM z8T1w^SU5r=NU;@(75_74O0EX!W8BLB^BvXzN0EajeAscaSx zMte62oK`ok`87nVyN3c_&Y_4&A{ z1HirZBj;-<^R{}~8p)YZ8<Ys_B%CDqv+rf;v)2&B?%}z;^pT=Gf5LpU;=fr~Q$nS$B6R(+@FKFt2KRx}5Ft+TP=?6eFP` z*X|XnqxfP#z9mjk5`5jZicq`5jY|S0i=B7d`&rP-<=$Urh_qu?Wnl2l?V#B_P#kXm zLd9wq1<5N;$!>WpfV$+C;F(C`2L^s1_9ACpt@xQw8W8*e+PcucWc_jw(ICu*ITv#ag6yLynlWDvgdtBFbSvASE43WhTOP zIDwn|oH4%w2OJ+75BRSFC5U>I61=Jw6?7yn5q(-Yf?ARlX{yZj*Zv&1D$2iNvT8Kk z)6eGwqQ@-0lGGooacaZ-y*o%3etV`k)#WiVntxUr<-DNsF_jPXiklk>Fb(|lMQ@arNZL-}QV?;=V(-GI-iCe-yU%ao43l^J2+yM^YKoIeK z#;q8qzGWJnYoqq$l;6Ju+x#vf41DXmDk6tYjTq-eEbSo#3rh%^`)Sje4og2nS;g0~ zT?Hx$>ta}%%jq@L^Mv1B*aB4Khn!REo>b2$=Z~GHc~KW%`}LvzkR#c5emZ(gyL$nO z_3RVV7bQN~d$9%Gh4HOGN+&EoK;FNX&{C>O-#%|={dNM&X1zf&j}cdvZMKoAW>Ex# zH&4@S)G8x=z&F%qXJf7r$9fArnNJxJE&f$0von>c=nzAmd29LM4GYB2s~kVO1fC9eZC(4!`ex03=9WEY z=c+j~SyP$MHW^=eXFvMdOLKkOeeg|js~H`sT?oIaJy090f1EEIim$3@tyE{ao+}DE zdq7)>)c1~uTP^(WxM_oKtDYd$4%sfch=LRE*Vz%aF*~+BSO7`COH- ztQR6*;04;N4N_^4ebdN2a~SfMDQH3S-$*+50A^_CL^;+a^pyV$&qE!#@XbfvWv;A; zN1iS~Cfmp5-KX&Hr;Jkmxy|m`xb4Epu*I+F@td2AwZ9Gytji87vwwB@!f)$m*4*KK zBG(yZ(wr5i#TDwy2v?UGZ-G}|M@_?j>i-U&ESk;X$38>qk^ohrvRX%VRz=S+S$7!7 zh8i4+#;T+XM3t&wzzcef%OEk0PIN2ShChqtxaL4QcuC*lo=M<1XrR(RM9XH z&NdnTz|0Jl0ASNmNmHOZaA?aquhKxYMMKVBX@&sg02hV)s2?o18#Le6J`w@%OUjb#;+jYgI?}@15udkePMirMj+DS^3ZD zA{a)qR>Pf^r*Ahl_|ne|A!?l2K?e+HcJV%{jLsRV1)Z%PMBRaZCBQFb_I?T#l@p4F z;_3{okk01ORFjo`L6QuB?pokceP!TaluYd`YHKP!Y)t;yBu%&`cR!<&U<# zKIx!gn7LJdz$GSCERdODq8T;3MaF41MOM^v37N-Q;B{%$QNtaHhJIqLSXbC|GLIohh@)cKiocbyprjDYRs&P;m5i@)17#?*R=@1kvXr>P$EexfAyN3?zN z$gk^)JTd43e_Q`JG>uN`l=BnqE(x_>&1h4ylDYmHm%Wsn@k@lT?VUlB=jGC^ou_5o z?RGOJ%Nh9{zsw6Z-n7W4!Qz{L-_c0LNCXC+K3#11-&Sq_F*I~4QLx&CGO21dOEYhs z)M4=q*AdYrwGQ6{t?JvLeC?`TxQQ+*6GtCSa zNF4?o7S|%q^2hvo$M>=)DuP&x97m>B;>fnLiSbUG*x&F^Kk8LBO)7yc(+0kWB5&t| zDyL*y9mzK2BTG1z@6~&7&Nou-6Bo5)FUj&0!zGw&W7^{)Y@F?YbkJ- zutGJJObf#J;Amor$Y9$k?pEO2oPovycaJYBB>Pu%klH!cX;l{X%F(F106ks+8U-CRahO=#c=iC%NG0|(KKtl#Kc721a>1E6R(0T7U>sMK8OTLmb%#hIg;wC<7zsn zZVS^3s|dlX-tKf!&dOvlgGlowS#NYs)wlQsI+CBM!RnW|Z5Hq1wkL#8{7Fa=KIg#H zQ3ih9Ehyl++LHNs!uF~?W9fLWVNQ_oaYnG>K`h&WRq-`U85$s!>3p`qVcgpul~4C; zCgB%cxR3j=*adh=%(HK_+$TzISl0R<5?Iry52j4&w_x>jq$^r1g{m9ATrCYdi6n@- z(-2ia=#mSD^PHvuL}Z{{+Y=&7ZVbpQHg^t|w2ndL#^$SD9remS&=5mV-@IyExN&O8 zSo|6q-nS>6#-3kk+L1ZZ9xzn@u^769kNFhF5T0aoR=#R2Ew9+A?R+pPZWWJT5l@vW zt06@2N&T3Fum#6I2u?mL%si`^pBz>!=euUwL)(|URflo5n%*wiwplGue=Gbd3_>P? z)Nh_cwBVrqCY{4zylW;-Vh@$77t&~UbH;o(H??p=*2mmwXZSctKREf|75>fDF?M^5 zR_&TSFM9N;t|IL67U(~b`??9qC`W0U!^cejgW?p$>zRN7m6zf*~>&xA{o)RhmOE>pi62c8t5pKm)E=wNF2d#!kq9?V?%=amfekv9GlhF$dkxT;;M zE%@N+rk7iXla(p68KkOz){KA0qR(mauyy@gr%SHvlRe}$VSLH5h>jFx)$p0tZ7=$o zfA^0l)F4axc3GgMX9iKX;?852S2WY}5EN#WX!>PBk!t$CbEAKT9gkgqC^tf!`#6v_ zJQvQ92migPY}RpiB3PZ8Kv2Hq@K> zo5mi9Pw(_XjC7pGxQLjHm=JRo<2_aqKx>`beRaH@#8t|Ttv}8#aFMa*l$2u&8l>%f z>lIT>M~BE(Bc53W_4OzGEW+PIb{?gB@0N8FXfoOXaUa(B+x@4>Xtda*Ro2)+HB>5S$V`s13PXONI?mYcZOCz#L#8%^>PuL# z!EU+waPp_PRJ@${s6juy+y-WS$*uJIt?5HqC+e)DYfVPli8}vA6cbb`XS`HymI!tL zy^{2Mckw5O!`lxYCP(3a2&|Y#au@A)s2jg{zZ(}^ZsU5Byc2z%dlR>Y&+;tFbv1e@ zqxT2(o?AM2^MDQZ7Pr>twbhQ2M+3fv2`%S-`T5Mr_bsZ3%$>WfRFhSoH#vQtZ}^qf z_kR?fiCgJ>!S2y0J z**@z#GaK3X)vzVT&gxgv@b`{~s>XUltvt`5nEVm^Ra5gZOCfssSzeY11(P6n5)#v zM@M6O7z;O6sf-H+J^7~fYv)D4SA)y<|DAGvqKP`9`742+0 z;K3GW;IF`RllVX-PGzdc6q?(P$57!79NHbYnPh#`(UMioQ$F%KbUATe%Dm18Oe&nr z&e4~sw@uyQucD=jUfO$(qg6Tq8^M4h^q;<)VCqrQ=~Ag`JcqF6zSa$07Ms zo3$j^Gu@iY;d?Fxbs&A2%pV7FPKAFU9^&gHR#Ve511|o>W84&G2rAfWfo=w@ENr4$ zV@CBpu9(Vw`r3-H3X2H8s(nMlH5wA`c;^oPS5ZvGe)TAIbtuz_8eaMFT~ai3{Q;OE zK8j-{St}7onbV>#vfS-3YtA5oN~r;btxeW5*T;TEdA>VdxWRd$=8X55x_ho$Dyp(! z;XgcaCR9A{nf~?epnyO4g)FAlEt|I@KWrJFYtJ&BIUxFaIf}IVJ(@uvoUWPy4N36o zMd&8lPK-`}uB^#dAXine;aR!<6I;<}(<#{}4QoGOZ2_C#-p6m=q5@Jp zQ?Wxmo?HU2w$6&Dsko;n{h66JWiHzby!ok|w5r1OaaFxyq+LC^)JUVdC4WC9?2a3tHjTxla~__AnejSvv>l@(i0UJOcr+`n~b%k>P&&)nPFKvt}jp0 z-)F}XEolmm&}*q!1jI|!f~o{79q($O0;AbYdy{~%!OLZ?k`HJ?lM=`YeUeswj|@XG z&6*C2cq=*(2J`^1CY8=0RJHN95RBpBL5B1JHAY9siziPWD8d^|sr9Jk!HLV3LgeQgYUl@D$~wiii0w;N^R&)A50VP`stMKVX1 zRgAFT`yFxu+s&r;V9IUP;=Q2tD4*m~Rp71hA9ck*sh!#{%0QU^;Z@}pkzL1T+r#UnM2E)19fz%?o_&F9j6wGknhbEpKrx2xmUCwZ~4N%|2d z%Q}c9ST!%%4(UWG5O|&jKl97tZg|iW4R&~MRf|_^(|zP*Kk756X-ku|<`Fk(uL3v) zI^7URtR(jFe`>ZM^4k9bbDuyrv|@`?*lc#b7yFl%JR?Lhm%a!VqDyy~A8C$?ERPoE zt>lg7)*Z^ilz_UoXkHdoJpkWmEJL(o>ZVy^X01-Kg%ekMSc>4@0ybj}=)|i4$MGt? zz7Gl*41;nun-7hb4Gd4a8j&GvTs50k_|GqyK>x;ru`O50JjY5+47$dh(|xl#`95GB0W_(7le9n(*`$-R%EL=vpIRzgIk zoRwDnw_ZuGrn&)QmYI@DnJ^O4crly4hNOn}>KVL>NmC)Pt?>oGiFQX+Nak|?o^s+uDj_R{aW^5bs3oi!+H1aqwO8zi`s_%=?`}8v7;7<5$gCBgo z)&3yJPEJlf^S{%qm|zoWuPHG`ogRB&J8I|v*pTuiaN^8rTsyntE$hn3xAR9JNyGIs zAA^lv&f4qVjw_~{Zx$CsO+0F{bv*%n$#}Cr+)UcA6uz6+k{!h)svBWUnYnO52+mxj zWmWI3n?d$YN&)f)EsTG2WApR-XoE);$glcZAow|NVarT``#UJ^qao+H{DM(-9y@cs z<=)Hug`7Ok3uuh%u^FbH#|mOzrZ&p9@aBlkbddcO6iGn3bkO6g9p7*fH1I$${l&mj zy>})3rco<50P>7-S5YGA#L(;X=`9aw{TVn`vNdbh#Qi09$Vi)ley8AwXCDZ%*xKuu zSmT2L^`M$0ZAfmC*7S&T*9TTPh1KH?S&XkM+w?n+Ll}p;@^zFZaFoyyKBmzu^8foG zRZRE@Li-IE8)&#qYvciqa$|Jt;G%Exn0tjaGwC}V`$ahOxq&ZN58A}`g~M5|L7Z{V zt?f@R?))8%0M)+Bw*Oej;(tbRzojOYncj*l?JO&%zY8>K0Y4Fv3LpP+W+U)=ZQN?) zx5ZcJyK|0R$?;v}Qf~~R1;M9+IS68&dBkP5SK$^`i>vjU60AOz2)!m_t{R;O3ho3= z>uTrP%|+X+OdkRsB?_-6n~w%Fw&$NcyqALr`AhZ|%Tgd}7?Qt!R#+dfW(7+tRD&kp zqY^u2b(cO(JZz-sNtVsmwu|&}ye}h>60?wH>yjnnxd4Zc&*LK+`yeThbKvCYF#BoD zyXIQ&lixe!?{9l-`%kX&^}}~ZZ$}@CdoxxhlKC|*UKqPjYvY=af&?)xA-*V5+ zXRE|ucXV{s(%rKa2V#dx_D>&JH645%52$;2TjL)PNKyrgqcgakByED?i3qB`) z3&%>5EZ$bMsVwxt;tcT?Gc94{kRKL0x5}ZxYjo{o$`ygUFmwtyyu*&&B1%s+ zpmmALTv3Mt)2H$WfyCY83bE#BXV?XlJfY_^oyx?Cb=nREUE1$s;?3=yya~5czqEI1 z2AnGFnx@pc0FxFS1^`3ub5>BZA{B0`-}>%rfPa|QDSFZQ+~oS0Mh&{i@HraP{H}vi z#e~HM#dK4iHw#T)M+fVlKV<+VhGgwGS`cd4hqgaGVxZ?b;lZb-bECDOMu&W z5C2O6S=NXtAP~qD6nSLk*XI;N38c!^tIS5LC|w41aPs5YrqC-@DAf3}enfrTS$U0s z`6j~aN*9tWZ);V0B#O2pc6RYz`9nQS?H0bj8{^LG+c)?oZv$!_}yuRzCHC#<@LG_n83NTQ}`# zlt(?baO1W~?FYtOhj?@UA1jArll5i%HCYHb{Jd%$GT0ohyl^S9 z{{W3@rjRK!!2%XPP6xQ6umNT`>DS$a5fpLaDaZ`yDwI3+T*`7#6m?q#lezq*fZY4U zbvmH0Is|V-fv{Z45Sdn~U2t=VXfkKUVg^k2=dbFfM~F5j*B)0l=@iRwk>h7lo9%`R z1f1z6Dy7PZSmbr*>Vit8bgUz=6)JGo%_L-h-KXPtDK$^KSEWuCpd6TOeLqS1${Tc{ z-I96E>1Pl(vyo3xMJ*|Xw+kip3%2ML0bucpSJg<}Q)n?6V7Uc2qG(H09Hc7}z29RC z1yZ{s{EROf1Ql8#8u_%^g4r)G^&YEk1Ewsoh*}^BYObL%MpD^^$1P?5f%77^hu=F< z&2sqcZ*CQtGMSg^0;_nxJ$D@y19H~q(|%DdioR1W($1ew+3&}%(9FqS%a@14*G7EU zv^F~My7D5J-B=fd2yy35WWW6L&#c=8RR~=zv@JmsfS;bs3Q93+)Z3-k5CC1zAp*K8#4LxO+3Qve`=!y{fHqZbUj4!k*@1E?ufo z>EKeSPESV(7z#awE@4Z@=Vh@Fuzm2pmab?gi7Oy|i}+domVdLiY zNj&aMy{K{Xr0!Tb*KM8!Pt|s@VEi3S4*!?Zn?54%Bar4`9Y&3AuFn}5zZT8>jcZzuV4vPqS7*C)j zij1F<`QFo@Y7q<JE>-aFuDBtt_!Y@^m zs>2W6k@mVSVY^E+MKEH7y!O#8+X6AmCRBM-nb3NkSh8)=#QenH{I_Dv*sWBTzVdNP zGJxv)yZm&kx4eS2>hzcrcL0=&VvSb}rs*7HKY&W@m~$x5(D`3A97pGR23=Ndt!8;L zGJadyFf?jh)txz%SHPE%TYpYpJKu@)L9hKR-J{w>k)@Uq&OA)WWLtlE1J2q%9Z6d= zcJN%-*Js86jYfeibZ2-O%7sgwj{VnQGsiymn;jM)Kj{szHR8K0XY;OluudaX_kLxo z(?RLtvXXzP0;Awvn>K}k3&fg?QzsBx+YaLXLO4YpOq4g*Z?HIc<&QBL;9NP4 zpZA}Ngg_qe-y!w{i8iz}M9VR2UD`=qhK)6r|BwS)>Jwx2tH)9=@4hjT@1J-wT@Nv9E`f;G+OM@nQvSW0}OFXBE!ba9P zSr#SiowUTvlB56rpgJ;!W@ZQm`l8+?!Zd8P7>jpemYiTTkg6?X1rEXCjD6qZd*3YfIh_t*fX`ETWkHop_B5b!0R)DnyE+PtBx-?v~QNZ?Bjw46Np67TXi zRKkA)Mt=7D)KS$5zq~O}HEpC+n8JI97K&XSV&U8_lGP0HedGFS%wO|vCH>e z!w&}5ZHu0`mPPqheX=aqsT!*0SS*i$+rT}ld6BMP|6w6;?jz9P1X3zdm<5Z+pk`}5 z;y%HnZ8}|h>31(E^5`BT%}`$tE*yIl(W)2WV$Yb~S5ZZh5S#tN_yF6&alc z-rlXhhj1>E&&o7-H`C=mveko{Sm_zM1ncaI0g6yb8_R7jNl9Hr_ncPTm(r_7?}67Y zGX~7*Up@ZJ3UGc0n8;jpcQvk#T~(a#*_Wc=-j`h~g7Dm}QxY!z{-vfV%g0x8G6zDN z)3C!f7BS^#jlA{%R670|J1V|-G@uY4O<#(!acx#X>^nN&aR=RHt6TEqvvF}4r;KL(q*`4#f{m&iAT0=zuiB$!<$susdC6|#)|d3prn5si;_bm>7YBnSe@#}SKsWn*9wexMzyz=IwBjq7mm!I=!=cgY&J<9qp8?-zXuwA-G z_-k`2P;o_iA$MX-l}u9=#9aPz@a>M4L?)^PcC}7-?Z4iPQ}p1N*p+krIpzJ?L{5%Y z$JsIo>jGL@I2h{G%R}MWt#TM|c^Q-|2qL8cHp;6-ixQxd0t`Ta{4Y-U^y4}V0JK@A z5Wc2ng~{+3s0owMp9p0#V5nNoUKHe8O>}dVg0hY%ECi;AZFWtHHG~BzQv?+BOlm1o z@v?9fC91?QbCtz1KBAR&V{)nxX}ON*^7wb)a0Ky}?H@5J%D zVQ$j6jOws62tYO@e4_I&(_EUe4X8iCj$MI~oH3s95tpPK`#0nji!PevP4(%367L-K zNH9UW-LIHCTQ`P(_r85;XLf;Ez@wv@b5BwNkd2Rb>Eim(gNDy0s2OJ@{Md28v8(-u zs>~H2?Oy0vn}?-}5Sn7Isxn^_Me~}%{XPi0-Bw|X?Nbe8X~Y&j;ziV;dMr%7=El8W zen>w+3J6*1LvUWePe!b*Xn_^IPzhYFTU+R<-`oVkyk+Sbh1XOLdY)A5p#I=LUz|}G zs2&cheRVbm%4!#l>9%r4%U|KZ?H*z2qwl37Vn&`;?n~_O4$iXmNxu{O4SUe^8WQk@ zMKnp=^G*w$i_>ijsfGm}2m8p?sa!yYrDKl4l`D;_QMzY_b+%sGuN`ZOc93Exx1LIN zkBjpYl-s+snxHI+(`*i!@2oR*E` zT}Eza-+v<+;lUdp2LpR7Ne-{839O@QB@}#lb>iBie@?D>{(9L$bddd5Ok?xShO^sj zvMdHSTnn1{u<#Q)H6))aKN*`rLlhxKpbW39onORAs7eOsD3r7l_84=^UIjQAx~OIg zRz$N@`nX|QssmdVl;%s|Ay9Ea4C|U#0AvWW*C+UCJBkw~BdoHUg?3BHStT3p(29W zk^paJZ;S$Q@be>d_g#h$ZVt7f0zzP$P+5ReCYic$cwC}%e~oCODOSfWZ-zWVfsC=U zmDl=oM2|Ea4*D z5kV!glaKMenLB6`A%FK9@32#+13?f&KHF7ycq$JRiE6QM^B)qe1;YqqbPG@*0d6NA zCQ&{wU$%kz2#i045ZDqwTtS?(mKTZ=zbu5uDghO#D^L!3gl5dq2x%gN$G1U7W~!*q z!Hb8n0*x2|7{DOx>aQ@iM|32eeN=q+iXG#+097Pn4wce-l_;@*fPfjf9(}pSvi|Svwpic1mzIR=UwgjEepw?GIr6+rY??w ztt~;b+b@ZbKD%g_F~Hj1z7*HhxD0AWKIc~!&sKgi!6uIAKi2w-t;NfE1O?KvxxH2J z(7p{qrPt^>IvXi2x)w&GOv?|VcBT*eB$U6u54N<3>^S|3XprqR4|@n#XitI-C-%!D z*(HE(1ov{57a%(c{xPZ*W=Vm~S{J5bYLi#~>dmr~eJ@v*e#8i~97Ff3h=z=SFR$h$ z)f26h`pt$81uEg3FRB@nd=S%qHPx}i8S{s;(@m&bkm}}AJBCTY3c>D9HTm$#vuFKziR8HnDQq9Cl7O0XvzOGr!_)Z_i9&FwfiJMQK73k`_Y5o7e{>$8~d*wbladcab0V{j&xRlQRV@AM^R#{|`+Zr=kp`_=p>P?yAe7kaer8Qs{DjD} zWQu=9nQ7v1i;F5YMG}FRM3E#%YsSq~0~mj+jWfpb==#<>pc1M07bEL-F8v;t4r+MZ zR*>m$V#$iF33l{C_dB7k1tSM)BE-une~6ESbgvX=2-sQR$qZj<_hIq1w*#q1x8##= z@7r& z-*Sq5s4&Rmu9V|kO7H`vH6!P&Ty8tx^O+f?%YMqTnodL(cMxACNPWc9`Zl~h|2|Im ztD(y=uVrPR)@?+Hf1Kmo7FJG=V7Q8e@u6Rcmr;-Hos?fFwmiBvf!1l*w?5o#mhERT zvE#Tg*dnd{bVBG3q3;RhV78e!xu0PE)-cIBvil6I5t6$x-+iyW$HKh1$K>&zEIAa4?-T_fzvmV``JB34);_KUkcgW8Q z--KEgG5w*xz}V%i7o)9f{b5}7U+q{l(&uJR7a2mXGi{UEo7-VGGxOds$tYJ??-iS6 z8^QWHmUFRyx^M(Dqa71dDSG|>!#uX-Bf8Isb#{spN&tFVg?VPZ0B&L}>I-DHF={WN z)&%c?Xd0R3CWsra8tr}(%sAzLbxEMgHe#n)n$bmYH-S9QXw9`l#8an7iL#3JwBw4#CQe#_absT_nL`z8#QzN1-$wE1L~P&#z^h zkJHSp@3NzeA2Awwo-=Df17%Q!C*aIk0qxfVj60lP>Y6T*DO13%*McdlWoSbLgvooZ z`*fLS6Ua}$WL;sg3TSBTzcP!d2+?Jz2A6&@9E5pB5y-*028thk&-p`!dpUq>Ux4Ue zUgKiOi;v1$yM=;=0!#&Ra?Y~2K&)2CynPK+|~h`{7bfOCOxw%%872XoB90~g#b zr1q!_0(?|WOBM7{QT?RAuF^M=PU%EIDyX(g`~sB0vOWCph#rI>72Y6755*`^`t)5V z*pnZmCIKYTO=-VZU0Dr8cpaLDh5oCqvmMKaNU{QBiuH{!vndb+R!&6pzF@92y@xKB zaxr;9df5C_s-+Ms{lbX_QwI#0M6VQdB}E0YgaDh{7lNtq;bJUda<BIcsg*&H)y zyxNx5tA+o&eonAwVNeoo(>$r6%QI$KG?gI0E@uuAP9?T;uyqMHG+1SrP?u>OH}sBz z{>8+^N9_A%{a%l_ofoa|*2kp2GbC{5509=}RIhdMMyO;4e9 zeZKMGa%V8@ECMrg?`E3ot78XU4fcWa+03i@79Bb(GA1EAS^zdED$pBO@fn{U^Egl% zi_3K4$F*mMWWkttiH>#JH`335 z&jYPdx&(2ey6I^@UX~85CLHYC`*|OcAN0qW_j}Z~<5Ns)5j3df5`8}hkU^31%2Ue# z3Xi}i<`@m6*-@j?x#RFYV!&k;*&Vj%U)M_SN!TABd`}&v#G|*5GXJM%jXthWfl?Lj zh!$3o5#PuqxEl)SYF$6}(}qO@`XH1~TM+~p#fHs$I(n4ebbqGOYefUd+KdQbSs3g~ z6WZQI(b%KVY_9xUJV38|N=WMkb)Zf!()nbKQdRqc2<(2~iHj=ZoK&SCZ)stwJ=ZzhLF)BQek z2lviyQGa*{1n9S0{5;=4{)_wI4=)o~s3#b)Wv^f-eOKCEI?47=4O^5=D69|Y^dr;5 zp;1eB`!r1UkTZ8%?5C@-=L?49ptHea;WR}!MuM*%Ef$xc(?2il%plxB?@o5MPUgft z1a?;}>6s1$iF5B(e=Ti}8wI(X4@)p>Eo6V?S3s9QhST#VOe=&Qot<|=Eg8Y`$1UBW zkwx7OKDoVIvVD1kvnP3q_ttg}?e-rgNcV{>u7*uB7|(Bo9n3pNnDvuM<-ZB;qBV?P z`6zw}Zy+*Hs|gr|O=p|oMZ4Cx$Rjq~EJS?FW)-IjY_O^i4%=p^jUzmF zqH*=^=Rf+9wHGf7oCePli&p&W>D;QQM<=@q*y-6fx>m%^|GaOV$?R(rbYGUTROlodNgfW{erIoD!I8&FxxxB9!Lp>9h^-?l6-Q zl-?PA`)>}$Se5^NA@6t~Z=rVUfdd#*G&o2RMLAS(PM19b1YeFIRjI2|^a&K$LG`_yQcq1Dc2rzNm06X2vV_2mILzv1)La?oT_#y`Y zO}|qLKz&+w2f#mHqxb@$gAuu%4ncYF$1DtEEndIE(4n3yrlW~+P4icrWuUA*4!Ap2 zE@o3t80qAP5mE|f>2Ho9+uZBsAYnoUqBZ?yE z%5|aux`32*PIF(E^HrN=JmuE^HHmDxCPa3xveQkqGmfhtn+X}7a={T}!4<}4I%0rc zC{oSopH$G9bkM!PY;!x+)}e{JP6$Rl&tnr$bIqzFB9GHAC6RmVb-dvLw#0*SMWq*d zCw789P$=w+u2;(YyW>kI%SJc%X&+tG2ScL?bIetJDZP#T^SyF_I81Lx3#w)~E;7Cy z#}&o_7c7BAg;}jXK+y%Lh^KT%!}SVbF7oha_hMmq_HYv5gKE);lx<#V5G@HHAdnbB zvsfc~CT{Vd9KNV9*2~tQ1iEdB->~?5eYQW3nFWQW%PzhJqPN})_+$xl3?q#kiiw55 zob82!u~7|6#ZZCxkI{E|X8(>I4^6IFWFDx2h;I@S#c6*8Y=koX>Q+c@nnDYwE>JXc zssIChi@Y+dYWr4h$Y+$9nlA-f?2g(pBng%>+aty&RC065lbIJQGUC*u506Mz-(Wpw zzLvdgw#-3?Zbk*A?Xe|SZ?*jI8Id@?1#)3)4qv;;6GZ&^{=M=+7Q=lbqg_{d+4U=( zv`&wFhXN`a(~U3d;28d3b8T*VF0{%*YkJSE!|$|URx*Vx?}EBbnzUwIt?y$Me@)rX zIPUzT&7Mil`HXB=$jtbrR(><7>dcHEc>Q4sFvF-+;xt z-T{+d@GUh&ia9tmZnh)~PT6yMcZJ#A>!@^tiz5$||D?+m8-MsEcL3P!iUu+!j-Xc~MWu)OP%pTW_p;*hovRjeeGq#Rk5`eM?qxYb_i2_ogceQAN?jzw*QPgIXU<-kf zi@JSIhh5F zcB^WyjehK1f)IErTUkJ*%a*bk=J@qFdl8oA;PF!`lS*!z6jH-PvxGrK=GLafy*pgZ zqnx)0g;9lZQ5zTu*1Y9XAi?(nG)816Nu~s>$yu|&W9<&l~Mx>Ly$Iy}`vHJFSkFL&ggVMhyJyZ zZsNSVj!K`0t#;`h@pQd|S>|wx)hZCBQ~bZivl-MZ#(-eMyi}+*CJ)aD!xiOe^2C8H z#-kf(-D6!F$liP${#2-Cb5BgP%70#X!2a8!zojVYJO_^(L>A(vw!3QzHxEwHUR83w z8w}d_HgOj=L4Lnwi6zMzfjE7secxI2@G5C$yLz7KKXgW|k5~-t!(2XZi{9(b-NhgJ z94C2e-BLIi=p{*yR$;!MF5TYcIhCA8dcx56X1(kxI5S;#Zac4ShO%;vG12z+*Pek_ z65XQ`=V=?C%Vv_9Nv{0vLCvIMZPiM-Q$FZg0Cy`5d~?0)ZUNkd6M>}q?;E%7&k9hD zJ(()n<$l>>phaU|a&9Qt6-x580#Y}eFrA`kUN@!ChKz0_0K2lYT^hapReYev+kbF` zkKP@RnIAT-rK8fr!Svvi)q+~v@@4Z$75p}}4T=ZeZ`xV$-=+`dHXH1{lk9;g&N*4b z%)Ttx)YX*o66?;a@A^vFHX)GsW)pm+`Ou}6rKr#JgYzF&EH@QUafWq6-wMkvY&pFA z+1v;vkRJ2Dyl=>B8@vReK2_NE*;i?AA%pg%Gm?A$EMPjix-^^V4dfVp_XP`b@3^?A zV41bk)^gqaG~^ljl%ABB^PmO=s$fwI{sh8vE^Za43+%TN(p1ZO&|j$oXGlM4$!zvw z?h9gPOF_SoGLWu3WFjhZqQNn9%lviiLh^d{k9Ti2B6s**Ja4Y4hWyq zBGbSu=M8rO@h~>S95za<8wCC5&WwkKzG$2|lOcr-dQ} z{#`CXfZQk7nF&0WHRI8LMbUbh${!})f6aLatI;~>Jn0uRv)amM-I|CtE@N#`^NVw$ z1_KJ7>*s70ZK}^7&7H^nm~$r*XfTJv%wMY2LaVXC=gSVu-u7^BkfUo!#kUJx)8AEa zufr{S)?9lK$CXON(ogfC&ih!>R$qGmc52bJkG;&vb9yD?s<=$xwHR`|dhKbJv{)QK zdZQ~2QI|K?O{B0#AeuiGRB#W=$Gm@rnhW?nXta1r%1CE-<%r52sAEOt^O_z}q$NX& z8SMz>iNHi_2x0Bs-ts8f5A-&Z;Xbyex>s2~;!#-MpNs6GDO`I5r8m-H#t0KfLoS5b z5!xbK8D290w69Yn4+M>i+cyGck~6H^yV{Qg5LftSG!;Y*2 z9YoutVVI!y?M8Spj&0rD4^zxo=3xC`{bBlYP?fpoB^*tq++g&VShI+|h+O&>mpni; zpxreuQP|Pt;O(r;?3(WTV5K=@5sM-~uSB)yz#WU-U0gu=Ej1_>O*?J19d1ES{ zT#G#yGDL@UXu*F!c-G$uZZ$TJ(*zQYygO`Rredn}&7Cy|3Rxa6E^f9~?c2{n+@ zKdj;SLz*5*IXMF2*K^`W*r>yBeDOzz(V(R3v4d@r zre_C(SH<3#fkYX^q#qdwSeJog`!D-n2N=~~XYJ?x!OkIg!`ow}>_T`-6vQjHq-d|J zTJ!rrjMs{sKt$A3b=cxxY8#%>ZzT{uG50A6sDDB?{WeD8OcL+w4^tyT@RNQ6CaS-9 zz+|wg6>Y=2JrLp^ZF07RQ6ZaJZMvcLq4-G=lfC64>5pP%lp z`lzv^*ot&*&MKH`f*qR)7i1p?bV*k2iM>$aNE9fN`3e^OXfUpVsuPW>uz2EFHNkT8 zLfXxJp=dVU86$W=_NX0=8UFkVMu!wc2nDvD@%|eoyo{R|V9ICI4O(#y{EVo`_57|iBao_%Dhb%1 z3oo|h#s00~TyiG(+7xc_|9(5I?htQi=jU}b|7ejlxQ>Q};QVJ1cVlzW*x>a~`5B7X zBr8Nn$qmb)TmL-*dC|NxKe$-XLzkABaN#!Mz1E6B!x;^r$*FL?(MApE{YNWGT8Pw? z!dru=_fn39$V}F3fSDN5lWcL(*6&iMJThG7S{6cIBWJN&H`A5!mL!MlD-fH<&poSx z@n$g{FKmWxCiWL& zYCkF|icW8%W#q7RNq+<1e<_hTHw!Jc1BDO~U~n!4FeIWmAr)I3gBehE_pZobgif+q z7R_o-j-z$Vbyld|w%K`0j?i1vDQ3Jv`*4aW5i<8`Bm2hLI*M?cw^EUHmGmP($rM5< zP>(!AU~fCEUM4b&9;y?8t|hSs(Ok77S&E5KQLhPMxd2zp17krboR%Ay5DV zmCFH8dG8_u1t)V3=l{glRlyeWCR};g1U!4TJRRmM6F~n{NVjXO-|E3=)Qwiu=uD5x zV?HcCA9M3_Sr>`Dw-e>mMbBUyWt4uYq?G5=I8N>q7d$y$jgEGXwxsUhruEic1``Px zq58Lh;YL-43r|%kSRO27to{GYO)lbBMQo$dyF}$>p5}JCC^^|{3CF)v zF-2V@XegZKb#@DH!98c)?|dIbhv}8Smw#)<*#m4cM-m zzCjghwY8!cD0Eo_|?a!@Mc%1{N{P)=XYTLqDpkTwIfTb5bb z4tG%~@I7(Rki)#2t)~L-$eRs_oPBCctmX{_dWEMqdrOAH>a++KAD0(yeVFuD_3&A$ zt*|2Y4vD#a8KXz7pL_^@$`H~u*vrSi{@m|l4xc_0_PyZ4R|eo1>HhCcKgUl8%DbEi zi#7l{sx4g@8>?PE%(&-hK$?2ejpJe7yFX)tFyBTYa-Ta=9~#51&!hh-wOAfVy@&mk zTu9$HJh|x(xiaG{+0N3XTpule80eGS;&jkBKje(v(!?!hYy@x$=Y~(Zb;+)6-r}*jD^9H8s zH8cH#+Eo&PfO8S}d5NJ+0{m@j8i}nxGYCupMC|S;!`mP&T1LVq^<1IQxbyFUWCSKQI|IzV?!KfUg(R?u!42@Ych!VRyOjh`67X4?>M9{mdI zq~;ER^+vMy|I`Rtx>T<-j?A}fe068(d(X{9iDHIMFoL_J{aN#!_co*E+pODxuXBmI zV{t3P+Ysnl(?f?&35BBoECSYwsWuo$tp&X@aySx~`xsLE*YzJKE{PM(F?ln0Ao@Ai z97|zrx=(+E^uZP}T0`FzP=s|JJx3kL!mpFPR(MxSkO5Jk^Pa$D*iMk%7g4Z_WM!$x zWahoVX_7v1TC=VLa98AJy%X3ymj-*K&@y0|=E}$IdH4#=4d^{+8K3C96#bNP{DDiK zpliMM3N0h8gig7smk#u@6>%OwrlA&v!lHWT=_9muO;+hLz1Zg#Run^71oi7YyMq55 z=Qw!#(zx%n^p(6jEuMH84NoaxqimjnuxV+zfwbx*eaFEcACWt{4gMGzawchJ7U~FF z0)4#|68A4->%7OT-MldO)GWDx?ou;l0qoM8`2wyqtnj2-uw3789=uN%0I$&WE{FC0 zYZdizq3QEuFhK!$3s~&@*E!?!+96~>B_NE!-0d@$x?t%QGq1d|Tx~DXYn%^jGr3cj z9?v=~yBs*3wH33-X3X+az0!03u$xFkv0ZhLp!?@uFYBEx7a5-s26rmU^eBGepU?Jp z<+m56N>r4p+g^2#oKEfReGK%65#o7Rb*6F;Gw}XETWX}pX-4*XPr#(f@1##kL9}W; zr5nksOXMW!?|5yZ?cg6r=}KLHqbaxL`r>|uSg#;Z59Klo?yale(>dAbN(AO1!ohHJ zv?I*yOG~a(g?D5g4ww^Eku()%d& z?HI-{x4JNRcW!GqT#sA5)VbuZ7>JB3H92*FekS{QNzlb_U034&Ru8prXDseZPQ)B$ zFR)-DZd-z|zfTWP#u?BLXmj)6o%n5x`Q z*7k<$BN%~6rk7=NEfnlZb>li=Tr;t-Z7ej??X+q{$?pH7=*+{CO4~nv;JBb5P+HmKLTYJ~ z1&RwQa8N2O7c85pnKCV#Y38j)OB*W}NUW?(ESstK&D6A+nyGPZcLBxH5(U%Ja)HD~ zO%o6lWII28TwMIYpIi^md7k^ezn@S1|KOvvh}Q>KPH1(fon~D9ZGp`=-+RCsz)!lu zT>LJ7p=}$w{H0O#E5mm8+O5`Q@(h*#vd_$39n3>o;9uVBF9O$ea!t; zFm77@!B%7M`tRP?P-8p@=a^Q#VBU$s)qDiY?4a>&sOL{ZDyxhu&3x@i;BS^7@1M+} z?K8deKEbiSjv7k)X(vO)vNU$Zxu~(iQJCNA-tTH50XSsv+5M}TV-Wf{bHP1kaX62^ z*UeeLyv4k|Up+fNz>4|70WUUY<7h@=v*($)s+V*`%j>e-AAl%YZ-IYL&P>Om=7#CQ zK=Dm&riNTAlld7JUev$D6{OixGmm`-hnxT5Z;m$&yt(v5x}T#>k}BZ}qA^lFR8IH| z!!z_3%MdMf=9($O18eh}$fHm#9{JLG}6wU@U*CZP)Jj$xK+mCT3c z@a+eBZ|kKm{0JaGEMTG@Xfgld!e;i0-9T?v z+}EpWx*T_AzsjwcAQ`|WcxgA^)|b?fWv*va$L(4PGUbwkF-Um`unNO0Zg2FR`b@$s z&2pYdOcVHeks>gR#cy0I2AzDQ2UX}B6LpbxF@J}*&`){ld>yHzdNN$gOAvT$B=;#q z0zdH+P9chD6u?@TKn5*4%q#+y{`a2r$^v5;cq85~Z5z>qD2)lYkw7}E?GzSh`fm<5 zk%3@sudYhBPWZC!)Lf?@ITaLe*i!!^W)-7|t%XoLO`yg6Xgktnz`lU_;kiZnbEdAbOL@o6q$)|u=i+M^(wtEsI_=w0qoo17 zZ%OW-RGwj&J&$$>$E{q7bxtH1uBeMO-IwBa4RiUU-0Hlu3@lBCiO%hcFLiXT6A> zTtaomvEuI!xz2}YCAMepoMJTFUfAu!TLyP7W%()`w0I>$2Wr!H)q|xnyj2}wPqj}^ z{zgGq7w8dJ5IDzdtAMGI?Dd#biA@z$O+p zqb-+!ustAMe42Z+BYwnoh>5>@JSx&B#C*z!x#QBRYxE1{uY7OeqzCT#l|CZ_T~#Hz zKo^0e`crD*P6BuLnlN#kwLzo=Jgaq8*GVO+FBlHtfj+3_CS2+Im&Z$QH9H=gXUC8v zkaH&F$$_gKoXBF5lyRZqKBel~b3wyoSJ}oEoJbqKC|DoJ7~Qzb`TUAGpgiy17~I-d zAFNs|MrN;_42+#!82kdV>yUm7u$b85V{WSTD^HXT?+*t}vLa_;ucwT*eG9uMU+iwY zecfi}*vc7Zh>McCVp$NBe?u#;LdhbyeK2g52QZLY~;BxUm$| zbD~zxp}7AZZ_|*)@O^ztiqm>Alq(jUO-P@IBUjiugy&8HTTm&^eQQ!?++$|V+28{X~4mphMp;RU6D{Z?bT%NAbp}ZMbDF^4e zE7TKMhAwwB|1ZP6{a1?yK4tlF!HYqBDH^BG=bjCpB_H!Z8(W7Zw$W*67$o1wHsFPX zGRAhZ5l?NXz#zvbF=S+@SYt4ce?xyk2cIa^B13xtmo{w?rM#^%?>#8$c@+@9b4$l- z@@^aEmmJ*0OEwQj&5$}Em5^FvKsYLU47v$p+D}HA9MVD6%Y#5k)Q7mHp|Zbruqx9E ztS5x06AnVrwOl*FHH&JP(~7I|5w0hywoio0L{|iBmLF&DI=AvChf3{+I$} zw;vi&G9L`s(bahXVb>*9KEWWP`SKYZ%u)y;D)|DNA5B?^%KRR)W;@#)=eS#ND$J@7 zi1$5~$VPF@ROQbiafa8F=4Eb4%A%xUTlS)$wUUPsQ<}vw!4x#e@rJa!hDU+VEQVFr`t4X zP7N|~I#Q_Mh}ikO((BWMVWxte?yU^PQlYqrKOG!6qg6|jyB2hVa~ko`tw!chq9V$8kvBf!mdS6Oh<%uPWSA>l zJWVWmYE^*_YoHdO4Zw@O=23yx7f?Q&V@RL)#BE70GRpWaAIH?hrZwqy9^Y(xmyt^(w??S5&VRGMg?_#-skGGmg^JJO8%GL^+)E(LYRsmbB&UY?_Mk`8veo%#?pP#`;VS?}Q}m6vz@jvnnI`V(H2H zZ5N@Q&a@6=!YoD}qGaxPO1y3yEH=VQ@EN)M%$t}#(>`|@>6&4P%j)cy=yg=aqk zxVOhN8u5%GQx<^4@0$rSQT6a)#^3RG$tC|lu^Zv7@Kv(Y=*&JSi#vM(#qGJ}q6+eZ zQU}I7wie3ZsWZgS1VZfN3LkPq@$^rCV_FL6JiU1rLc;tr2>D= z!AnCq!>%O-7$=R|_oH0*h2vbI#Mlv#3>3-U?wHp%Rd2(-^gDIAIRBAxF54~o^6h(W zji&4CL-(wPS`;9rK|QLL)Hk_2t=Dt{tvb#}2VD;~K!<@iE&zaQ_LTdCyi_u9=OEWx zs{tJ>8rMb)KXtXbnf~_Ak+CslD7^L+jt;Yop&iy}a>bkf4c zbViLD?3+v2uNVItV^zf$=FN(;(*q6@1Z02=fM^f_SV41Cwz{X{)}rFroK#_j0X{J? zR8O@I)PW;JjhYPLt{IQ(Kr2CUu=Q_63%}CFLbymiiEV7=i>8&n*;H$ zU?ava45xy#p-{fVOUqpA;>_qK)>FnGe*On#z@av>%r1T$8xic(#$JTF=p4sO-U>LB z0`m?+uo^eT%1C*I##3m){zV{~1DmPTVl;3SsnB5edo#DSrwLaCba>H%(}i2^1lYQ> z)ITp}dUZ$~DGJkVn5`W)#xRFyf5L!nd}wBm2=G&UgIc%595YjBed#X&;Xz(Wgg9oC z#b?rP+K~b;XD`vd7=-o$BcxyhkTURYyjR#a7iG@(E7dyACE)G+z$v?(+s1)+f2W;) zn(UB5)I5KU0!<``U4237HbM~N)PVqIk+LPRkE0i?)B{xWnMZuPu%6HmCA0ys%D)$J z`&GAjDWR;Sj-5t)<&u zEBt~1!a}#$2T*jBfc9LCz|P9_K01gcsBl-rSYZejcROIQosz|JY9$sx8c|gDpi_*Q z;gfZdyG5+zQp|}X?Sk(*VFBlU3;^8y8L`@bkFGIADg1=#Rim4iwwAt~#n1^vOqmXT*F_Hiprok2cW?^x zq=tkYg3am9+Fy;a888F~!@s|5FMY@oUt(vEPv_V-DdtdR>WR5XDO)q&usD%GJ5YqW zJ_&&gJfeJuLhq}s#@@M1F_|KE6}sJ^@WpOI^W~O?qNn}+Bsm?hP0*1GO%)IML)ibx zgY>s9b<=slvYOZJ5e;hk>5c>gGi2YrvHFQrHsj1rgp{~eKP;L&Jf79_|Y3`W^8k`Mk;vpHa^o;MBOvkX$ z)Y5>I#y6pr=`w8HM5;XL0h70iU1r)Q{!ZJ_b0ayTp`mfIb(A6OHvV+fF3$G5ZPy=& zx0I={%@dB<{mUmudr#p#THf&Xal0pb&E$#Ej3KP?wUy>oV4h?5oO!K%Xo{}SKVH9- zq7cu2+^|M{^P8TknJ)g=x}7ot&4oZLsMK*0p`KZe%*a#U zR_~#knxfqxNiY2p@1BP!^k-!nG2#Go^83i-e4o!>_r+*tqUjfSuct;CeIZt8-d8zb z&~DRwN!Wl#wY!k}m5O(IhT{({0_gKbecow^`qZZT)CA2|*!VZrVfRmgCmF6cEjZQn zw#O8@db`V8wYho(MumG3_%<3*8;8&&sag&z(p>SIAwRuVE_ z?D<<3oSc8w3+2?kbtu$XT6HQ`OS?1a^o)M8hV~fTs}sL)6rOjQDw!HktdM@|*q!t& zySJZNhI{kR=x?gJ>v@EVi?b7ayr|bkF_TPg#vR7O%&hTGzkeYIHuOe)-CTKiJwLv! zr}oCcUqjvLrq55>0DZ(U#=zz6Rm+`u^^}OKQ{ts$`95+5s<`G1{>EGe;qz(ZMZp-F zBGpU3{L}Jegs`3t@yf_+l2XgLF%fmP-Lv{#)IsUX+UBy8oZK*D6wt7Di$c3|1=uUe zIdKe{`?<`0LO0*#LAh?`Zz$72w`=c}zwWNwL9FJlXMCETexR*)K$o8AGYIfzEAKB} zYt^yZ@VY&>&JW#cUW2e&H!*`NEdq2`VuXUyRQ38#>Ye&(! zdn2L?8GDP;ENMUQ0(lP|v2*V!S*hRjHSelaR&Z|p;4f#VV!~xbA?PBWr;CQbDLGqK zpmjez{f?~h47z)PXTePMj>Hl~eEH~8HCOj`YqMJHELZE~`P*4XLRLuMtzdjcn?uIp zvi>S%cWrZ)epoi)nI#{kDMmI^ze!b;-QvcFyvLBjliXDg+)LaXy0V{qdZT_=fkOV` zuGJkN=B=cBJ&)Q2gaDU5!xP#C@A6lxeej%8KsrZaw7s4_k;ne%Qc>=^MCNf>89Ms=_u`| z;#1^s72WuKhZkA0%K36f*5XZR_n$dXLp48aaVRH8{Stm0m|G5q)RZgC^>+tu>NY(- zG5Jdm&w16S>s5Z&78gqY7aT0r>Y(X7`-x|WAxq2q$GGfA_Qb8|&^M>d)Aakl1v3Gj zZP`nf86L1|~gZ|BFIQ*G!vP@1$mi z`|0#pDfZ73)7iP7$&(n(n<>!57S5CpcRw=!q3W1?G^Hp1Y8$za7km@0{y?uj(K$Vi zhyUu3kf#hQmVe%+e)mY7`?x**Zm9l#Q&GBPqu$|xoPG*Hb$#4hAMrB#<78CV^zV!9 zln<+_W0zS!y|*uI#;9YvV7YNmr=-m6;{UFItAtduBsYDrzR7%Dy5|=lX~UyA__%a~ z3YiQEWzEhGm2vG&Sw%1c=sschLE7T==7|xD$wBv+sN(d%72?+UzCc3HK?JM_zttwg&S32^Hc<&3=aIw+>^cAWb(s#!ZUtdR%n{P=YMXTdlvFQS%_mTwLoyc!<+a z`r*8=z4x$}#e9@A*2Pp31^QAZXe8@~t6^LcP(M7S0HvsZk+njp7UxRKOq*$s54S?% z_@c5-=8a^gLD0i-y6xQ;gR-d5c%1RRA!!FE_|1e7)8RS7%rWt=t$ai@ZXUeK$eKq%vmu&|r;Igo z2Dps<*;lsYwN>@Sri&M`m7eSe_hpV{YaPv(EB%^&SFQQoHivwgaB<7(5?sY?!)pJK z_QFND{?_o)MwcU94|s3^#D@k0hAWFXYbVYzOS#_{teD@mJ(rC;t z_9P4@cpoC+KM5V+{JPo=g)^twd1B7Ka3}a4BwGckS=uEggD+82dl!dG67-p(ZENR; z%=ey*S}G+r9ucQAXXb}#IsGrGY!OfB3B!zN0E%zKmUmx69G=an2JGxcMPbJukB&xDM58q=-K4C}8G4|lZ(C|OrgyJb`Wt|AJfg+D| z8$t6WkfUu!5LK_8+JXW}t8)r+b`)O=I^C6ehxC?a-l|^RADCc=p>qL|*UndeG42oC zzkgjBT5TUSP#-2Pe=})}2q#@SO6uT1^)gjdTu&P2W}gqlxBnY6?!9wDJJ;r!WWeQQ zroIA0(PMchp?z2^JZWv?o+S$${PXo0Llj+-!q%6wOIJ?o;)4Pm6w*}exRi4b@Bo#> z8)=Z|(P- zNR4OfBK*u`<_~9OOnp!0hT$!U3}F++WDs^E;!{|3>efjre_Cst6jkL0%aGdh?BMoL zq0RJu;Am^nIZ1%<2P2g)l%Sb)zZ}i>ar2{Jqf0R;$kB*nrY@h~#8K zC$iYUPZVv^mBHXm0+GfUBUtUO5Nj~y{8H{j>3*SP-5N7Thi8G#nZ$mBMm50}?dc_I zQQt^NcDNteGcN9|(|c)toJcIT%6_^2Dtxlmm(=Pz(87{4)POt<$ne@Jrz{sB*hwaj z75A4SbiFlVf6`x(wFr_1zz8IYV8G79(rN1zhWpygR;-sPYR|9j4Lkvg90&}^@8d0J z3_~U3#aNvqn{pw8hFCM7U`B|i{g~rBY&i|S`9}6o0kyy~DIqp#Q*>FZUhH1OnHr_< z?ewX+>peBC`qlBpt_gyOq%oyTb^S|xO>+8V$Ru}oDj;ycE#Ame+~q+sbRdA;EoguP zn!ff~3JI3He;ZdYz>PkSY6P&69jPxTQ9$WsY5eTB#LIYMyw281=A~N)*Sq>~Okt0o zyt!b2~AFntMiSDwE4aP>r9 zu;9F!Q8J&Ss_4ll3ggi*2k73T6L1<8@W0=vJt>=Y9BP(TM=wEr1H-qIwpXV!(KuV z#<@@DGvUs#@QG6-U&zt{u1_iyXqE{YdP0W}i$4rMb{=O?iX?46hG+udT!h*f;Lq)D zFRWQPs22W9;;Jk(q-*OYc`P%IiDz<_*@#0YB*??{ooGnhI^iolc0NBy)u(-}&;*VT zSDXvzle(%E@8Wyda)=lV`ra*Xh$h9oa#|nKlosvt+4#I`HZ9#6(YqNyGGVLeQcYc< zrz}fdA+SuOAbWVn?%v%!(SM@dVaWsURy`A1$KaH3D z3J`#bM26?JxN?)#1TuWQ94{q4nq$RWUL)hKz>z~jW-HC~*JqHZi`%@#kN@3b7jOnGGp9C3dnJiKG~UwIgHC68Z(qu-g{Hnd(~J6HP<@tpmqy{~x; z<-DjM$;6-?u)8;QlNt$F(;bo+!X?`VnWWw>&a@h`2ggVQ+SEb1hgYOVG+s_p0nKFMd}G+6B36YAe4^Z z`jF-b_yT`I91`$bondVH-_|vQpV!G=`a-vyR-SQyAL$#CV(zuv`F`{2`6U@E5}dv} zV{>B*={YjO@R!rv>_frk$nwG`kzYe@42`Y%K+|P9WPt77q9vi-&QsTtfB|T?B zZy62;HQGEM+Y;Jausxhxxr=e<>gMHFv3M*x~zU7a4m4 zWIUNR*k5{p+Uy^i5?65+Nh-n1uF=3J+oR2KkL(T7su2BOxm7#OssFJ#eLKIRYvp1I z;pU5s=bukLe^psvN4#q9^-%nj00=Grq>7CMj)();664)#*d+XFJ+S`RIwuAmAXwC^ z_9z;PXjf!`D@SyZ?!zy|zcPTm2-!?t1t7Z^ZCT2;aEi+nXU4kDi<2paaIn3_g2KOBIGN{-`gq$89eVFmY_{me+A(MB zsxe7+&DX|Xd@6^hIQCyf=<^s(_ibKPr@i@cw~*lBBM3pO_WsTJ^PPRh-}k;YUj+WO zyF-C)S550a7yXH}`5%~auWk2xG+4#NcmRIU|3 z!4X;kEJz3iWfVyqCY{4bn!q#=XyMe!#UdsTD}oq7+c_Frr{rMZiOUfim)qz9)SZoQ1jvY(qBUQSv1SS`39vj3 zS>CR)3J415wj%GhVk+0zMT4&S0bU(|l0~(!*j>O@t3Voq8D40L(U@SVRx=N=H88tZ zZ_X<9^Dl67ICqH z`Dw|n57VF5E&fumZ)rX;_Z4%~c~;?9|0yv~GQ3i@R^2Xe-92y`q@(XL-%Bp%-Gc3T6!$aAmVbwyGIUe;hk*W{oef4`xIj{B`q^ z_fWfbS*z%G4AYM_T+-Pw0`;TO8d(e=d!FZSuR5(*%IRRJs;kZu3dME+jP$Y zLpqyFTxbty930!}6BpyU3Q1}Ghdo-x>6p!^_8b}ER21e)lWErmbhns?F=L9`q1qzA zW^rcw;DTfo2O4D*2ZkgY+b=Sv(2kevLcfIm6W3BTGxRog)0E{2&7#(x=k?9zk*Imd zjd@0AU*xmTVKVN&A%4HSGzetaVqZ22lUmH1!`6O!AH?=fbua04{cTuryP0^seMNim zCY<}rR~LvcdF5TNe64qjZt5w62`Q;dmL`+%K!711ENYBKg2kWu#uUx$dAN`JyIKdh zLub!VOdA9nT7ct|G~&`0Xb#G>L<)0*y{Krip#)6Rx#OD#=5^p1FKX(pkLVAbvv~w8 z_b0GYXRM%z&rbq1FNQ(kY?zTSHAf=b$CE6cF|>fCE+XY{+{^_b;wlvUF$+a6Hl+1Jr)Jt#pd z`h@O_Jumrh`{5ds{0t-Ry?UmHjbkv3VJbk#^%4TCr&(Ju$6OAP+K;sy=@or(Y!-?{ zb#ZZig*x74rQAV`8Wsn0T?Cz_r(}uE8O=mWsd%G*EsM05>WA6e5k28bww@K%_V@=x za9o#1yBrx1yzyf!)}OSbhK||5f``w@hGv^&=pdeS^kDUQf+|ji2addmOO> z;-BHE#RdVIjZB%OpI^Ebqm?aWEtucq{F%b{B@IR;i6GBb_n=5B_aqK6%OZxA=~ny1 zfpR_Iv;8e0hE`ea(SGa%`AzN3aVrwQalj!|!4oZPpf%L+58W6&6&N4s8H)(HLKk<$ zsn7H_5d*+UGFg+MRg&9(Sl24TMzIEMCmakbF4E9T&$e?;fjh&J3HbyK${foOiFb{z z?!a8tdNnnEfmP$5TV||NE7AM;cR(+#!ALK+QV93zR6S5_X|k+Z{W4RNmhnb<92m8> zkDIjf^@4JN=bVI_r{RNnQlrt)z3j46ip=QgsQuG}QY8tIP6=()>@wknM|+HmvZc+1 zx->_jnrbPISWhZHV7$~EPoYm?sIZ7rkZzs?QzrsOq6|elmTpPjn*W_R;a?dgP`1%7 zO-(<}cF|E8mVEV?dnUeW5nGWLYZlHz%Mf5(82@XLBn(oH%QdEx$@+leXXb2x_HWo^ zYna=eK}cy<-@aj#@qh-NTKxftCPw0H9|~KA96cxV_|V=GSE@)8V9;nB%)_pHElVqe zg@p@5A*>!TvYRZL4?N#nWE9P+1IpBa;+U6LfPwS<{ zPiVzg#*IJG`gEc64OKFSwcC#_Va3R{TaYh>$ZCyA!_E;)QwN4dG6!!=wtn_`khoA{ zPiozKNB3V=U(VZ_MBEosFun!Ya&42((lY@O+#TPAFBP+PE=l!((f|+9NO+qV zriR<}y$h?+q%SKw=H`pKSLJs2ReV?lc0jgk#j?Bz@OwqY+LJyvSey7ftqC@XbMr0N zH@0;2|sH0M#8o4+2M(JXOKSYSEl6MGQcRmMV~i;klbaYml+(`>AcL>5#EQOb2|xfRYB zn8bK$^{1fX^(V$!GG%>}^2I2*64iq3*5J7SnTsSBI^P|VzR$Q(_m(bkJnu1F9=fVm@lR{J@hRD*S>W?_fu!I#7 z6mSie6u*h3b4j3M#Thti!_r1Jz z*=L%?CWCf%$+Of=i%@GDB6Pd&RBD=M(TO&C08(&s8+emtVOK=0BS+thBr(>5Xdo6Hu#z5Mc5*N z5I$m$Cifk2P{Qd8xqX9Qcm~tn1ClUihD#A2MYYqjpUjh-dR9D zEJwqP8ZX3yo*48_5mREBh{83)u`N()Jant@Nq^3Yquh*DW4Q-x^8^j&N$ruy^fIH| z>%%dxJIza9ip@F?cM_o|V8NZl@BjpYS|RQM=+xJ-TP*bM3xn0dR%y({&_27hZd_^c zuc0*dUwy#~!+4u$p)Atq;Ea=D+JI0;@KvD`uM^6xotJF0^%B&nUVE@ zbH@Y?grzIaN6>4-R5%ogD4fTX;VhFGBPM=I=+WGKjj>0T$7?-SxpC&}_W;MYjimWL zMR-!t%ASSLxi>`*gq8qYx0tM@r8yOyd~yj!AfhsKPG?%4 z{{I3_WYoEbvqLH6g;rI9%64G7izz?3mU-FQT)PHLQYrF`?*;J0Y9%8Fms7`93CT(g z43IQdY(;B@rN2Vkm@FNDlwi~vJ&W8Q`6Zsabi(Bx-J0v)F;7frGZ+>0qp;S8Eu z0V*gU0cjiyyn+$k-e&zu4ENh6?KK)K8+nYN;K)`7mwrKOA#yAAvp{B+(VX0`0gEc~ zNRwOni<1+NlNn9eA`o(IiG$h+aCU$32@l{qJ(`L5Dx> z0b2&4c-67gUQV7bU|W(5;7)@QJ1SiO;Lt8wb6m$Q9+QteG4eLWw8RsB&6m}D+k}|g|Z;^ z7-)$-K!|s&>0C>|#{<5Le;WWK@{utdWDm-VS$|z{0*tEv@6O(yD9o}{s$0sv2evP34$cDXE&dB$LuQ@*Xuh$;j z)kpRd4hO#zc^z%NDXpiZzB^iS7vXgOb&LEr^o+>q{o{Sx;^veutlSG1ozZi=0Nh^Y zI5oR@Lo80m%iM2`Gdk1)Una@`&bK)cx4t`Uf8upvLf+`fHoNBnD^7(wEl^~PXp|K< zFO$19ShN>$N2F(@L*a$+*pbD^i#ZXwr&LyiM=qxMU%(x1SwlMQ+iKz(yOpWS?O%X< zHlu0U(Tv&~L0jnKLDIQ5C&x^iuJ@brDd8E(c>DY7#S`pFj0jFV!8WckH7918SnrYy zL9D$n?b~+Bek=T@>aC7jQi!mMx@lU<8vb~As8VOIFqk)OsGF3~YYff2{eL?bv9)jY zN@-5gGe}h08(C9HyrhLq=lRX-@8WtmLc>FSWK2}#$dZ23p8gY`WA#Smq){!V8q_UM zjl80#p%}GzlLicAaCgimw}jP9hb{In{%aRCA+KvrbAf5a@ z8*ZyBPv?BHJTeva5rYj6s`E`-U@g3j-3 zzBXu+(ebzSBCP~(tp*OtxtYn#%-*8)4`#NiCE6o?f%pXByJqH!8jU`-o#L1|EcWJ2 z>i&$=d-cyqnE3y^`okaSXjb2})XCn2ODBE9a9k9AU4OqxaA@-xw?=@ERKDrz1em^u1RLXz^3tqoeQKg);@;qo5yd{8cF@Q zlI<5ZUAboM^*QCr%`1fv0i9zw?v8^@z-vG{(1$YM$#9FC+bgo~wns+~VXHpFxHiUn z(#%icK(WKXN3#Ip?eJe$91<&fo{NEYddb5D?FZOZAK9fg3n^@k2r`zK90p2+2oWsh zKNYP7wc8q=`mgDA{f-jf)q8|M-k&k2(>BWNWGyE*{xC+TEo|y$J$ZG1N1UtuL?Lv6 zB&Q>A77g240*L`ddDf367~cBPc#1&1kDjZus2$3z(HwvO!m%iU!ucuWGOE- z@-xfpU%Su5c3foL31U3DJF+2qgD%_l3nGS6T$MR=$`u*~3U>8o&8Q!=TqPU~*;K2? z#UfKuVBs!(e`lXm?XJZ2Q@sU?VFRE{Qg7u84??x%x)No9CXHVl2mspFl#aZZ88Zob z?w}xMVRFWFFr4XvRU7uh)`s8j9#J z-q}H53y7J9)mER9p-l#2FVRQXX08Px@gWizN7aq^a0N*x}&&Ga$;(J#tHzx*xEq}nJ>JHJ4NYe_To=ozi zTRTdH8ro^xg4lRhG?Oqivr2*6J9xzX{(5gPpdAxM&+AJwNa{qducz7N=-gWl(5aE? zWNMC`QPxgXNsq}j(@LnrRyi8=Um}`%IJJ=Ehk^}Hx_E3A zu%c58x$9VF$HpV{Be^N>bCc7bXye&PTs5?-y~BJjQ~ZUj9jyq38^gYBYOw4E5S6j& z_e0VP*X};P76&;?~ehw-$JZ} z{WyE&yi`GA^E2^Dft#8A5^d<1uP#v)Iq9H&g=p$up>{cyV!^%eqyqB#fAJdQJoV6j z!Pw|)x8{r7<-AxoToj^+GHP+)eK?gqcXFM_E~&l_#O_oGRjHKUdc;cM+_1J6Qf|dH znI!2ZHU3F}F=mwjlp1Sk8hctFh=F3Zc7sk$pim~L{BQ2sGo2tqo}_My z*abi3;uz;G%$bFrSW;hFr{ibc}=8r-XgD}JUtTJM3o0F5Qg+eO*j z*z8m?wMMngYmL{k-YBmF?ir{Yo9kN%XA)X2Bzmn{>zKqZ^!WMiz~)l-R9(xabx7tz zXtUK^|Gfj7{|wt0q8&%&MLjN_xN~TP?U8`%tIB+H+dgUQKW66ZC2WsgxvP@7HYpby zDY;WZ_geL-^n1@cOUi%KtpD{&QuX0xhp=+1E=2yGH5<#fIfqRw|Gq75;#0NrX15O3 zjn(CKy^Of=)_g=(etfsn?{xwEi_6JtIo{{ukhur!&N&Qysaj0>dvF6`JNw%9gnR4u zM3hK5P&0BTA=hUjLidx;qz!X>QvF}?Yc9$3OCJ2**!orU3*%5?!qXqQ!>d<);8sxd zc1y~`KNQ(YJaR9L6kXWvFfemh!O_$l`D~d(`2#>BfWh?}$sRM^A|aN<_rM(>Gk`x= zB-HQ~>D3$VmfGOoHnDb}~n;{c;3+ya;D{)u|D>*=L1v>tbSvee>8b8t-2qFIw zvt8NI6Tc<7ks=CRe7c;F0HPFg67vst(@C2LH96a&;)59N-O0EEf}e8}YgE3IX^!vv z;#bjsnA;lj@Z&2JhJ(aATV09+ht_t^5DB0LCl$m0XbYFQymc8eB&Y{IrNm7sCUn7o z-XG}d8$?+wDarWil%p*ZhrK*68Q?CG@j=;+ME+6RSAqrIlk+TYeJ%D@Fqn*Qak#WJ zX#>a*Ui0K22d^(ONpMJ!utK|d5`LX&fTT*RpTJ?nw6(jsy9pZ#GHYP(B>1pg(rATy zgtWg@lW2Hy*!0~e!>0&FpUmpX?xW@t`8DyjeT^Sd!dA()ESkQ@S@mluwNpcs&!3v!#&}EoT$s0TiZx3@WKHZ>^j(XH zqKxAh#er}-P!ykfC;UnLP(^X@6nAe?AJBKo{=W#Fs7s4IsCBuzpx*P)n``3~8jlrY zt`>rg`V({UR*Uog8F<*r6nSI_r-+lINT;rwet`yFkoV{Ju@~VJhM@#2mAD6v3vipx z*eSO3mwvNUf(H7=6+a>rasBKet)e+-rY~@~nbOCe^eCj>9})Vt*x-J2fZM0kaNtni zzXOSzcc)x{M}AFEyGzT(p)n|0M0iq`-7iO+rtJcOw}5|aq~i(f3vNkb>_e@(y)9uA zJx^Ed_XMk8>i)95^l?)c6B=o29X);Y60z7){VnG@UO$D%^CMN-A+BLHJ{L(~2n(kh zv{envpa_B9*es@32+Da09;J4lhexvq;#10pkdDg5Li!>mhs&jBVjVE;CPvow)ZwG< z8srO7NIZ6n^(7P3a`M6TPPDySj3Z<<_l$kRdj>yZXwl9Gv-;x!O+r;&-=Od5FoE}I zvfcsrErtCcLVvQsslRqz|JW&{)W`FDm7lVJE%~5vJ%JMkkJu5yG z$$5VvT}RPS3T%jq*n|y9I6WkV=>gEIkdZEsyO+uC;-=w81g}Y6fP~~FtqVh&WoPo9 z5*Bm6VwK}suGar(ig2GfH1s(hpl~}am|o3jaj;nt)GPGXSRept7!9g$Q>qbkTiVQ; zy7q|uFfhgClMeyyOQ0zptR+wAOQ_}gl~&A)j4X$DW9cwdAq+%D5}=YTj_=^agE&9 z@p(z%j`MTv515m{|1os-e@Wf_A3tzVQITWnmX#@~rKJf9-UA1v(n`f;yJ}md%eLCL zwlpm*Z$PMJY3j1Awlpofu3A}I*1GWq6irPO5=)ympjcX3pr9ak=gZ@9emH-?;hYce z_v`h1lI!1+;DGv&t2y*X;mE-6=oj&M)xLv&&X4u-}Bp@Nu9b;8vp?Xg*=3tQ8tGowJvtEx3aq% zax6h8V0CeWSPdIV&c;=Z|Dc`8K_VRdFcb2a3SZOa&c}adRzIAc)nr1V4Wi|U+Y_RJ zD5*L&n6WVz*w{pj!=^gsdOl3dZ1XZrIWJd5?=Nr?YI$1tp#+TK^%9j5RAG%$kY;9S z1&JQ?Rvl^77-|U$-oxAEo-UR{m4NWeHg+QCSojPq*d9Rvq5&c&Q!uG<-{K6z$q7iQ zI#7>0`YKk|%9pM1NCHNeB|JSX$GJk1jUEI>I)o?I@j(Y6fFCAN&)CHLydcLABF%I~ zC1Zg3cjzp9J5*}W)3;yu9kmJd{OK&&76L^Dq3C=;b%*!QLL=c6P0yv2LND1 zA|b^3FtMS#LN~VGod1n@2sTAa=ieb_M;_i7DZuzAtSHl|H_Mv@;kK_ta6I0F6GaZ% z$x@bAW~b$ew&|y#v?+jhas_DkN;f!e3&ptq$HFiZuF#yujHSa`FC~(fOSTi3-D^DHkreC8qrJZ^qbcgT8)eBO-w7Wwr+~;=jDd|GJ|G!&(_0H{@ zUiTfq^o?>-&6*#p4_8YeUA60uwtwTC{A(294%fvuAJ%VZnN4W^cIx6Y>W=@z=%qC` zO9M&Bxi5rOWz1rpVpT_@kZ?n0&X=twwzd>H( zY?c~u)eiNy83Q-Y5hnEQ&re~|Ns%?TJy*S~M)TI+I7z6ryMeC1-M$caqksnYneVr5 zzt&Q-qrrUz*TygwvE~kS@_P&EoIT$H=suW&u>3@i_CvkrgLSEM#b5J~*Rt1o-b>)T zlImHR3A!JdFCu+)!rU`PPO^>LVQD7YC6sKy6yr|Te6xV&2hs_*yTpIoV8JK``R4Q^ z+Sj#L)j(etJp0mDKtv9Un}qSBdcG_*SjR)^UktX)9f{zd_&0YmnAF)`TS>7W-8f(c z4gPfBLu&DFy)6}nK40-@cxc*V8?3Nc7@4x6Z;o3~D1RmnOK3m9>6!2-ODh)8?KPIx zGu$T8*b>N+g(}_v`MdO4L)#yi{#9GnZTCTv(&2L-6A97F? z2Z6_Mb1eR`9;%}XSB--p(DF8yyY8N+2BDtk_jJ8Iq*klLnk|W)SfB_Fa-jC!_3vvJ zPi&%L$lcB&z<>P=_z|wDw#r^NJlUUJQf$Ab@cTX@yS2( zB5EG5FyU9T8k=SxlPHL9>JdIr=D1%HP+F2DJgNqPFCZKTz&;U*6`bS*@@f)Zo-X0V zdH-@-AZFJ7VFv;MyKC7t-g~Eaul@Wr%e2R-@TrVJ5h!6Pl0f?v(Y-ru=~*`s&&b5o zh1WFB!s>aSN&9P|WST&V$Wm9B;JnCLCD~}#VeSd78-)kDijK|_tov-&ix#gXBeGE! zCqTQw@|b>)$j1yii?nIObWi(lvjF~HN zT85=v#=!c_Jcf$P!cf-x&=mJYLdv)f@lE+2Kez?;a48a{iv`>FG??CMy{Xh8J zy^Q#03HKs%t#WLcS~kdU(3R#pYlX$?QX=P-b)uYlwj{fa2w&u{|Br*nXV~EP6ktwz z-Q}-Ke-buh@38F$6!HKq+2kNi48HLoz9D=AoNdHGMc0+ z(@KJap?q!q3Obp=Oy8~%Z-vP5P|}vwyxx!2(e+@1PooRV(lF>N&hBJuXo&`&XnL0} z>SJ-Sy!t2>aw+SA8aDYoin=Kn7~~c(=;o8Wg2fg7<<3!Y`iCgw(>1BitLf6M2HORu z%&Ykn&JXCF3w}ZnKWxjc`HG<-S8Ezv`ERmWw*LN-gxj5)qsn|;Zd^Lu(8?IP;OeSe zzi_?&Wi-;#Wi{dxz3Pbg`z_{EmFF{O*0Ccd z{No7HNcq(cq<_??g8g3$NNG?z`=|ARzoNg(pGG@h@(9cGhm<9YCl#*buV64DvFG6kX))BkO7Yw5LD$>hOW;5mP#0DH)ws= zlxz+F7O8A1o*okhv7AY*gs`?=2H<_u=BStMi4Bqmyu+bVvbIOz!W4Ujl6|&j4Z#&h zW{Pm$^#fgbz|S#Bwo8p!#uu=6^npC_Gao%V>=I2-^_{1#iIKhoGUMu1kuz=wek8Y3 zV-NbJHNFIt9_BgKm;T00`NtZ9mY!%)a2`LnPs}80~`T%ltn@B4t>(9q23+*2?-TF{JTrR$n&&bvs>k)fHP3Pfj5idr} z!zRF`TU{Ywk2*s--}~;7&u|!9^~qKaLf(EU$WVpMf}615^{j8FYcNMn zE7{N3ru~$_&B#_ITnbM;N5B@Wr$JSpeqGKz_!OJpIAd@`wnwt!8Y{(}BIFC;NLrRT z)UfeXk9%IDqc5Ra5;Y$iP6>Ix1$zd#Dh`_S#C(|9#xa~af5sxAy~svOyxMHKzMHx8QV6GDc&|ENc1|8)K@vw$_1C5}Bfs6Z(HN55T?`OOqQj@RKMUM4rJ>bLGWPBHjzD;A!&{bKl(`G|ggne3mr z56O=AtQ&U)|MSV}OZC&GjbJKjzWzBP}m9RE2pKa4m}BPIKReqaW>@q@=-XJs%Q zWiDU%Z+;sszG$W|;h;U?TtLik@;oRh~PX1dB-e6~NJhcr8BCbQnkFNT)p zi)P{bB2oq^r%qY-yT7Opd^n#GIiEVuZhDIxb=HF|T|YFLXpZ^4Oi8nSP6ec$os9F4 z%}=U2gBc{U;Q|GgbfK9G{E4691nWU9W9F#$x#F^1brG-EN@UkYpk9|wWmmY``gZ;x z*isnXyuC8kqoA~PIT}_M6Im5I&i+Tr0{77DVJ_ol**0o^RvL7ld}PvZV)xJ> z|I``tX}_?4K+dOlG=wm00Q^%|HhgxOe=09=Kfi0bB&=>!s|5IwdxJYm_*GweXh>h* zRDERXU+-X+$)@!{0O2Q(yu))Y3X^LqIs6{{ZJ;ITPc^w*2nVB7tH(Hy1pI1GL=&7V zzmHwoyKZaA*_d;>sj?+t8D!)DP#v37(0y+&);`3B&dnxs!b(mT$rzK+|IWy{bY5u} z;YRqBk8(}T_7C@is{_bJU6?PPEH67|-WCY_2U>ms?y#Fs;!Ddx>1}h^6gE=PLh?Fi zn#%vb)6H1{&tby8D+z4arL2XYV82-weUNy{Z(XD_oh204N%!s+=406xg46XOQSi;R zwvS{jg%&0hy)V5L3#6dV+~m4yk~7gjzC^H0tp-?KbR29M*SA~c1FsEkVIlxM?C@Y9 zY$u=xkq3M%mMI50<-p1si_VN&YA!DK@Ovdr11uXx_1FgD&`-0{Qq6Pp9p@~F6#b^m z8APwg1b9UN7xMo7;NKQS4HLVv8v0-A<}E;z5^ zo#5BFBXQNS4y3Yp-8vVmssw`7xNrB*52bP(1EacYmo9xoCk?c%(fMMD05k!JNT=oG zr=Va(n2YbsN}0sVxSq4J_-Z-)>oB2w!(1zxdBaofk1Z0=bx-c2I>v`0ICfhx=p(kV zn=s47iD!bLeTf(xxUmiCFRE53qSYnZ4ASz8$+s-EHD7efB~L#*N?8jQ{7!ahO&r}E z2Wz*5+2wnCpBe~85zC5i6HgUi^mO>Tv}hgn^B5C?ECae@JNf@DCwmt6rPpH2I8z~b zDGb}281raBSYdbe#nX*U*(diny;(j?R+U*-1?LQ{%Kc!HwzW{Doax6fPvxcqUR_wv<^ljY&Q> z4rTkNvik0ArAjKbX?Mb)Yg*9MG{;$uya*qd8W4_d4ECIz0dF>x*}X{I1W_(Dctf7X zkuSaYc>5U?jzn6c;7pz+5^GD=tQ2gYW*fe>t7UhZ}jbQ1=gcQb- z0wUZuviiyxCHPQpw5MqegVPd@#HhVGqkB75EA3JCFYE-M24iIALO83wJOJ%f)R`y5 z>^(lnuQ~ZnO;>KW~OaaWVGDoMa(lP5S{GMD}kG`)d)W_P+YBx&)WV@cY z)#j7U7cT7E0Zl*~^Dn&nnh%5>g5E|s4TF!Aj@k;4A6 zu!^b|t8PVyQgfStw~E4~*?5(obX1TG*G+%63e{U|J) zSn*EJ6@Za*p8Gngov?f^wzW95IwJ1QlME1>ge>)@@ZL(I zsZn9^)1!%yBYbUjBlm!G;47_S`2gdd?cx1;rTLCwtJ|jg#~+CEN`_M_7cY)8F2x~F z0q#lgk;+zlT#;>%CLyahzKm;U2*r(-V23{57qz5a5|$5kcxl4!5KOZHGv z_@6*n-=3M?lI#zLIw;EeHE(9Ijv}l_Fnd;sizHa~mFRruwt$sil;ktFc7H$#%$ZUN z`ciPQdZFac&hqf3Hw!cORI5He@4xSCbZ_veU?o@GaIOmNM&oOo?1T~F0^XCn{BPhJ zd*98TI5qi?`Kqe=^FNcT9c<3b#3pg+q8eEgsI{8fpxi^86Rj!f?eqQ~S9Qn=VkE~2iQou%Bz2yA zjH;3>^y>Cn8(`^34w9!wOQF-`YBA@%nkm4~iG?}2G~NMmi${HNA|vk4?saYLiGksaKhoa!p2U46z_vG8UI}|_!=OfM z>Ilf1i|h3a32|TL!Fx)!JTNyYUtw?8yZ0Wm&OSW!6c8ZY*QwS5N4#BH;qSoTxFoQC zcL3r0Uzo+f=WLRI5rq5i$+)rJ;IKZ-P(m)gPT*YhNyxSDR{cnW!BVY*_XrqfFJ}OS zlpwU()UMKDacW~dfHN}lE_e*V7?WEHC2Qem6e~&=jSLJg{n~+4iN+Z)oOXP`(d*Xc z4c#%naBRKT2J25pEY3!pkOD3jw|IS4a(JJ78hlB^{syn^kA~U$OG7YZe#+UGHD&+O z)Bi@b-(6tZXD|D8o{dfw%?5fLv~0vk0Dj;8)M;xWj6G~udRr{79q!o~=8-@ac{M9h ziWWfKOUw~3Nrm!AkAKPW<^(dMX**kHD^tMI{}MCCNlb1SMg*$E+|=#(F4K5&Wi*FA zDT=M8;svY$a|C2vWuUP`DG)jr9Avn8 zd?dH|4ZyHvK?pTD>X4D+^P-Oahpj^s&bFIe^`d*Cjg#e^X#5wprY4Pji{B!#Zs|glW~@6WD0MVflF{4)LAS5 z69E91C+=;#;K)q}Jq3V`gyR^yrZgm@V~d-yH_ZTw5H?Ailyo8uv{fP2mmEdyKyKqP zlbaB2(}`4e5wHLOWrh_(%H%{)L;@biDeLV8DIj=s$a|yN z#D4U!EoTF~jo5z3O|9LIJo2VP>HeVxc8m}!nnkJLCy}Qnd*;a|6-8|BCgw!R;yYZ9 z#Px{~mj5Lf`5yODi}e=408)xb1}aYwD#>aoar~BcX8RF|_c})DPL{c|J*eu@s=4VK zaFe}|IW$i-=xKiRkkw>$mNQNryb|$1(315VlT??`v}S%Ls6qpxT)KDO40zPBFGaxS zPsOiR8%gYLam}uMIm|6&cmYt8%G}R zb{LH(;yPF*s7V7I3E@dN*_UVygCBCtPD60t?a95zZ^+s01H+LobGNIQ?@JFQAtn6UL^*64@wywE^|?>4=}VqY}w z&T+hW?J33AX4XEhMbDWVyrT%ZyMJ!t5logT0XUj6j*RLTxh#dL$)_kfm0~*YHTY z2$$NQL5Ge+bqp#>&FQeIQ+*jxl)!S4E@nv}6h!CAiU-S+G`NNsd1SlL=rR%SO}N73 zr%lEssZ-~Lg=iJO33sJync#bWtZ;HNt5F<*+eM}{xKIv+)Df0DLAUn<_Si| z#z@|S8)1FFmC&b;)DDn8f3ycB=)a$A;FY5Is4eZ)AqDQDnkILoh;mHJ$&W51^Qk3) zUjJyknrw{@=3GVh$fqxI;Hl5e4W&6wnM3ls0Y&*;;=69yss69I+s(@tS2Ab$<;-=o zqMDi?#PkV+x=ZnZctGW~zV`Dl=kp=rXP!nWxTB4(+gP} zM%~0EN{UTqtp~B?YKI_hDQ?OCSF@6O4Kjgz=cAoRw|^1PR3RY3Q){K!X->YtL2|o! zWN1-zbf8}l;w=if7zexs?)2Bt|Ir@&S=cmYG_0daoRM~Fbrr+j89Wo}zKF}RkZ?l5-x3~$kIm%dT7oMvZUdLrrjpiiJeqlbVR~Prp75%iyJ~Zf5nBA!X0C(=}&(bqNiY+g^#e=%OM z(W*=~H@LLw`nIY1PfFvd?_2D%fQ(s8dRvwb_pgb6Kc`iu*dG3kI_%NZh=hB7aZTkN zdH~i;E6@3-JjHrQk-2{S1n@3D(;HGbL8ZeP-12~iS2niOoV!zPb3LD*kqL-JhCl@` zaFHs&`Ji-{hjU~-EUd<#ev=;@ZFVh^a_iie9Bp=|X1P zvGC=avm;5MuZi9(Yg9BWNtP&O_c9A4+WvSQBm|Ov7#Poq6U-OShc22W!lP5S?u#|I zv$7sJj*(VqoLV*A$s~yhk{u5O)21>`QY9$mJ`TfF*b;r@pZ<(^oKTl@sx zS{i0?dt?r=fMLD=A=tKZC)M1S!anIkHE#tcwgS&K*%UZX2~(>zEjkE9k=FA48@3qR zJw7|G6Y|fwioIv;k!4LZe{0%F5Mo%gGHco5+P>IX`yqDAROi8t&WNd9Q&yAt`QLZB zi`6OhJ(X?(=V(wp(gti6!*({DM3U7Ws}Sn(6p&&)>)jVx_#(NDxoFJpfdH(W5N3h< zR%R9Kh;L#zYI6v@sv?xiGm4(^Ahpm@Ka_TM8<>~M$Oga`PN5ARSln8mBdBj*98x^s zVz>o!lKI?oS|`2`m%Zjv??nzgTOUN7pLMDOC}SS|C`74~c=+~nqxpX6op z+dpj3pd;~N85hTh1-xp|Nw*@Oq5+MY7*`2}6NT#Rm`9tcIMzp1P}$3%DLQ04SgtjU z*(2BMpU98e;XMTmXb>7CGdPg=eNZo<>IhTIH*}J(YK9uhNOLf}4X3jbcD@3<$sU@t z>)*%>f2XAFls?;6Twnc2~{j+LczH#_I9;6p*=p(A7Qe_Sia(yiYL*N4Ox$TeLBaC0xCRM)P3rpGfsSuRnB%a zo*TIKXfj0r(tS)c{)17lVLe@$D4Za>wo6p7NM8PT>HjTtS^V%t(`k;TmlQovhH>49 z1)S$>MmgTNA*jSFoZxP~JRwl9-&ALR57j77q|t&O77kWe=@c1BuiV=g)B>nCnQZ}P z!dX?Ppb5qsLF@gINLG)1n*EdY;jm0lH}9K~0@bCxwSUQLi4+h|A%;FzQlC0`9HjOZ zt5lzNA^sHX>R7tLqlxGN07ichS?UfIpaiANC(36Ornbo0#ywp3_XsShaKJ&c*o?M+ zq@@TptJTd&-?RIG3ZJzoPh*_@C_|b-+x9%Lf^Q^1eHK2Q1cE~+OS>Y6s5eWAWXa^q zFp7X!6{8cwxNeQvOiU%W1$s@fjZ&(kpB#HnXTb9TBWQ!^6Pn`UQIW>v4J{ckv4bhe z2se&`DnUq?LLA=u&hf8#Z1K2+d>}v&;XGf2T=TGa-QxBO7}r0nNVjO&_A7)D<|gWW zaab7EKii(u#f_5FoY+~af&vbB8t?%)acz?q(K$)GfVsP9oT}Qc=GfKI(X-z5uJ$=6 z3!QJtpTFq6^Ef=F>-I^h7K|r=Cq;vC9!X1UEQ#aG?^jK(i}i)gsFpw3|57?q7%tcX z0--Gy1UWo32Bub%_6Fk-?(O%~syBW2;)Ia5_*NFe86cR_qWQ=g;oAiuo z&VrvjS#Sn+N&4Dh-)Jem9x<{hx!CG|dxKtMEj4dhL5$aqpG$y+KvMzBcxhjZWiZ8v z%razPPmu+!i>u`&#YjAAYoa;XU{KU?{&f3LB4=vIH~SW%$<9nb(}e5m{iJ3VWWhE< zxwBk;boMz_&We&KTW!|iMYX@d^UnpZL_Gy#5sm!@0l0c<@VyuqIS70a-=A5QLsp{g848a;ma#$6^#~Q&$#@uMJ z^fxmb`^tZ%cG#1w`^iK+pe45&_yWFSf^f7qNteRv5-PU$cKshA3=j)W^kGP(O?YN` zA^?#bSnXD%Bud;ej_X56H9*5Kqn(*;Dbs0q5<$h|oj` zWbC2#`mpn(TQ&2rzw zKEQZrXH($pObOV`?J3tyq;eXcl0y5yYlkMfR|es@*KRW+BCu}D%fIZHepKXz4L!QX zgm?P8zNTvzKXC)T5OWoddyB+SAoghobWu^zj`I%W=zI5*>-1|3(&anK5EeWCR1M;J zqmZEJ&DxO-4Ip8tI*@Pk~6l9)`&sAUGg`R0Br9a>n%)5k?j?^lzC|M z_-|qvJsSb8&CYWMhxqPbGqxw~hfg<&%KI6*`zK9o`S+AS^&-7-RdqKwJ#DA@aRs>K zy~*e;-5!fVgZ)RZ=r|<6FfM4KXh`64V=-iqrwIX*+w(u^D1aoc?{vgD6Yz8Yv_GPj zU#P~5-3_qLt5XxqJEnI$+ed)yqa^;!3@I!&dTk?&(bK#fjnvA;+^<(JI^cuTLh2`$ z7cv&_H)00tebtMQGLIJ4Zz;Qbk3|rx^_seEVNNFBk_!}Q2k!b=bagLz0(~3vVhhyg z2CV9FgauTm>IhHDOAe0SmK{N}HXcbHi+V5Eko!5oT!y+ytoGk+riML!gM5!kK6%My z4P#_WbC96Q=}<6`RQ8bPSdIvrhgoaZPJHuHR+@7fU~^J_S)t#$7ARO-w)raOi->w2 zCOv+LbiRHMev)P$ir(UVkcTENz$1xIk6O%g4ryzj6XpdRf{n+dWK+lP_{M;c0LL%& zz$eEY*|r=dU;e{_<|=%SWdJ_KLD|rg4?+TpQcr_36a3S`*1&wvA02I{)7DBp+;S@a z1wKWQm4V2t)pY73=(vvek2P&K;SFsw`K?#QuUS()-p=fSPE}1X24uAUjZe0yq-T9r zKr^AGZN*0l-aq9Jeh#II9ox4VNDreXM70L0JCUSZPDvA0lCs@>UF){`SBgdIev;^d zs!PqnN=9+Rl=c}{k+948X=%h|^tCyE}x+^5e%Q0;^>n(A+C?M#m zrR|SQTTj!orxJ~t#R$_rHhK6!Vg8Tn{rQ( z?kYu|LVkp*N-_e#jm{GEcBn=#u*Y@TBLb9I&BvZG0nK4aT31e*tS2$~h{Ibo)kk5> zt2IuKUs)zNCE}ne=1krrSdi66GWD^Uq7j@iA(Nu9ElCF~`(5Hct9hDwhcq_*nDcjj zCOBN=@Y!McFCk?uDqN`1f3?tMGQ%J1M~2x~FB9_-rgzYA@9QA8a4d6Z!rz(33>|G( zGltDf5zvdP8Zv#2`yi|U)fn9@PoLZ5Rn`K0QuF(${eaT&uvb9^!pTvHqhK-LLe27Y zj~nIZy?$SGx&GA8OCC~*0|(K!l`1^xuk_tyWJJarM2=M%Zsq?mkflZ%Bsqw1Q`^WR zAzPl9X{)ug$xUVzu+g}HPVSnKtm%$y28T;qp ztW`6UBUm5*~w3FL;ZVADIUbqjFnyOFN$ngv9*5D+gV7k_4DhAsGi zZIeHfyy?n^dAhoOE5hzF`Y`PEoIBLB@VUE!@0b_Dlc$06=2OT7Q7LAXH~d(SG%=a? z@;g1q<8iR2v|Hlq<%=F-k1TLtVB)%rAHroo zheA>6)|_;+UF5i=BWnH(D*<+UAVHnh0mQ-C_uDXuoP#o<+QM?nhP>dH7hS;(*7Kon5z6i~TVsNgP{%P9a8ZlvR-{_oxKw6D_ykj5HDExIC8ZPc!Yqc6SYN^trP zk%ep>mh+W!ZC{=6MogsWU6ubk2{G*RC*pAN>J4`AD4au?zmpFRN^*ngJD@X(9Dnw7 zdGk@nOKOBca$lOqoFH`dVdpqa(H!b4J@H;~lcJc`yaCY~cY_5j6KI4>4J(p$&Q?dW zf-qk8Gk?@aU{y#{kq&)M^F-%I9L}iCIQieFU1N7d!VAUmEv%1G_LCthk1u`gaur@9 zHI!q`B7XbokgmJdUQdZ}pAjbk=93g)oD zBA|jaou5J@+*16zyw6CrJ6`kY5o`47)JN!u@;n0j4Rw+`TM$(JN}}xmh|#-}&x4M{ zKGiDf5_@TkNR=%!PD>}DY2wVt^;vbfp$NwSLd`HqZNJIqpQwnKVqA2)psEfaQl2oi zi-J%KO9w0dL^4dim1d;<>UCPAtVkD>H(3y4+Vk-bG6KQRdK6Q)o zl0P!t2%)AqSph__v1o)gNDuT7l*j&l*@-_v1F6^YaCkk}4qkNT-)c-83ycR9)<)_D!WWPZfUkJ4*#9o##~wC2KMmdE zvb^4q`SC)C(A;iwsYQXy+d%~DitVw)7j;u_%Fo2jjN3#;B{0fiZ30w2-XoKQ%5rvs zqkNm9IN7trjs)`MGmdY1GK-Z)H+@Ag`Q3xyShlcUQs-LVk(bc1(+>@Q(~Xn^)WLX0 zS?J@Yz*C~uCDSFLsVsNK9_oSneN%T0<1k~-N$}4|bSwwc zXzaWS(p0Of9-37a{*BJqgye)Hc^-T`GhcLKACrc4nlGp3;WE_ zPY>c%9K`^Zxb53vN2t`;$I9H;Qy|$IO52xOvC!kn^L?l}fgk0w?!4r3VnpJOKw|?! ztIsl7egcw#23A1M6A+EVC7Mv%ndQT#vYk7R?ePg)D*>So57xlKD5}pZ9QepJa$bOC zWoNWP!0B{&79>+=b3-jl-?GR1KS=&Ho_lgOS8@;UNuz@8$IYZsPeGVl6iD)TNK%Gt_tY~_4N%b zvDTpeg!;;q`hbcJQIR0mWP``B&#MQAodpb7@?06YsBYv}Y-v~+`Zn~doWsrofOoxp z6O_sMD;t)jKuhATb;&Q9M4l%FTQyL@Yx5|>{4yWmR57^dx*G=*gLXxS*_8ri`1%WR zBaLdEYKKF&Y3R0tqO8aW`HRR39Gy9j&shx;P@dP9x9fm=lF@0!OXgx()&A6 zXSJQp4Cj6h=RtWwTZxwBTOu34th8I1l- z0xz>k-4&StPR}&se{#Ooc<^&+XS0u@F}s&z=a9!jGFeh1;^rAw(>}7aYRVb)J_;fD5I28i=tHOgpgXLMq4-Y#`VCR7yxHA6~{uV!qHaK2AuI;NDZ zGLE>8<6au_Z*>lJ{+Cl9l!>;_MFes>R!p}qDai9g1Q)iwt6XqwDT|LAxdblQPjSu} zErx4rH`6n?jtd+;t#(UPlm8QA;fnwp-FbfY#MLnH8WC&Ns$#5totT)Pebms^)UJ&% zw>}ZjHPbAIJmX>*u_U`;%yak!M>odTz5W=S}~zpeUi2dxQ|E6Yah|4ysm z*0C&X^Nt<4%U!b1Ma|Z}3-GJV^w3Y6!`z-j z2dZmyR;LH;{uGGGtxCWSB?%w@5jnrmV`Wy&<#}^2WEY<{NcPBpxX$6bUGLB&oBHD6 zsY?)jM?e#O77Z#&me1jKF*rWvfgxgvCnG!^z^g{>thUS^18hELerR`Ls8<7tHMxfa_#Ajt6hUF*D6VRoepXSZ{sup~P6rkul?+aXA@VtqYX2-C2H)iHnqxYN@MHX9L9~GX0?~1A)D8>I_ZQ7 z2UkXGKZq@v^Kkb4P5T}2SAx=KeZgKTqLwq5UJ$0-SggG=nbDRz4+j1is^EqxnQd{` zoqe`~O{Lezt$~(4G_VZiTSD!v5=imwBdl&z7&0;3A*{;wyF>{Tm z)>t2}M3{>raM9EVV2VqSC!F%(CWZbF6z>ZR;3g(;U2kxWN)(oG!RP=L#tv%3h+BBO z-o(lJQ3~M6vG>&F$__9d^ZB7)&FOI0>9xt*OQFL92E#xo z5|1|vL=K9x!wELYNhaGwl58ias+?Af2!s6Z7Wc->&h53yGXLsT`e$vJq&c&&%CLY$ z(c^6`m~0MtL79WAs?3~XYjLzA;25%hFL5fmN_#R7d6wnHZ1S-1(1kIiRW2%%7xXJb z%rdL{ZME7gSs5=ir6fmA;~)x+O^7gB8=^;>6W0V`Evb<-|DsB~x*`M}*(d~d-~^x+ zN{}FAn#iGHwwe@*E9Kv>QqMDd^b2li>3Wz}n9tPwMDiwC@uAUNrJy1xNZyzZ{VZkz%Op+o}K?!*x zUS3R_W^_{93i(}KYc(IT5qsNwLTfTQME)igNli`Z{)#& zo8RsIzvbT?kH;w2!aCe5MstwWwC=y_X~(|~Ou99xHBEL;5`WzwLkh3`G;P{!KbHt4 zu?P3aOqa|Da3{`8fOWF;Ea2emR~^Y^TLjAr?<%7}!kJ)RT9)!Kix*YWRlY*=f^lJQ zrd0Z+MoP_mH%;kW3wPSzOEi(hZ-^I$>`$Dj_ZXathE+*4q!$>$X0K|FUz3M@wf~KO z)dUH<>IU%VfCH7>{N)2?f$PUl^KaL#JS6yS^KyN{n*sPUb#7haM(-zVRMnKO^e3Nj zW<`0L1IeHp`ycLVHZ+iwS>||rYG3xd4zGr&64K9L#!<6PFD5zpCh7Z+{iF9=JJ4+f ztEv><+A5)f;k{!Er{O1W7fhj z#iooHk9JBv<+_-cr2b-}j9APnMPxX$wNO^TJix+?nHT}zIg^pCp1r4iKtSDtZf+2` zcJ-!7Fa`8#jE(0b6%g8gGR=N!#vYYC->S0$Mw}x-x^blljCSE)(;J-8?+=cG21oqiEG-^4Ru9f9JFomG($QdmOe>NkA^29in; zI4{qmx!eDD9(cTGg{Q`P#U6)AAj#ZM1@fY{F?GbB!RPv}8t!o0>B+`CTh2z@Y5IDc z0=$e4^T&Fc$-RgGgkMb<1NW;J_eHbSN=<`baqsDxbz7ZSdqjcxW)a!Q6J~g$H4hsc zRDd8*-A3(9m_;kcUk;w8>ZV3bui*MFOv*6$X6BZSVJDNVka}F}G4R_~2npy=ptRVG zLPTQI`i5rpt6Upo8eV*_8Yr8WVF&mNC{0SWcV6_M$a4oCDx1$iB%(EfV#~4dYt<%D z2XI1 zIP0IQ4S=fnie|Za6)snqFA4t`00HfniDqpuU->q8ST?u zkl9m%>uA_uED-nvp*c*&IZxUK_vD0iau>l}-%Rno624xgoe$SSqnf_mpo{^tkusi` z;b8h&Mr(6MjKXGH`=gG=Ooukr#V9eG#;BQ@gcMj z>bT$mD;02V?yLEWle|QD^(G;6vmI5Z zwEV7^EU?8!KGl|u!H4vf`NszDnzn<5)kQ;JTi?!XgY0biaSQbhelco z@-SbAMW6=8B5rb!;Z@d)(aA}Ox++d;R#%qw7UYm@q`&1(MfuseU|h;-W^LJ^8>|__ z{dTX2{BPb|uW5cuFgkJeyLm(sMd=ehk+K+FQ6q+4VBjk!NNAl6R*eKS@OT~I)*c;*X4mk!)`?JO|2;$ip%T6 zDw9SeZoQ+-tA(c62YReeiwk&~w+MCB4dPe9gwXs{(*;1>3WTkvv5xyA_h&t^RX!~3 z9fcNjyy9zG{uxSIg~SXd&GPyeHQT%fethwO7|9;TbO0*?Y1uVvwB ztT`0wwR|51-m{aLa+#5T`bH>lqa=as;F3hl8bN6@?bn_fA8m{$t6hAP*jm1-wcI~E zsSo=qHo_(FOF=>4D=7Qyg^#;A0Ugfnu`Cdo%8A3Z``5~<2SFjB)nCY-saL!8tVT=b3kZnwG$7vj~ zHh`sB-V>ZTH9SHLo-J6ZTdiM}utahVMLQ%Wx*F@71D>P)mP$c+T@Y&BlJ$|vz)$(f z=PUYOLJCyr&m8Yrb^QiSzT;)6iZ|rEzLrq` zzoa}&$oXIYJ-74|sT*lKQAQ82-5KmSdYBX9I1$@Yc96lXO0Lo29mBy7n6e}fdM2!u z#Y~fF44ls2VQZ?q=<)<7s2%~|oxSw`Y`tkzQwP+xeUcMMAftdv6(Ir&3PK<#2q7mB zEGR=zY_)ZOiq^JTK|w_s5)!H?2ne>?s(@lEt(4h{G9(ZXkU%1!pbQCvf`TTHKmr-g zo9Fr7wcbBp{_eHUud{a6+55il%a(ER-b<&{YXN;X?&^9XE4`Bt$JIml8RYkGh==N- z<|jU1&o}${fhH%yT%ngXZnZlyPDW0n;8diPEmX4t-MVRt@iDmci49iu^;o>6$eld1 zKU=~;OWJ(!^F+Ao^CmrrGe^1lBm>M64fVumEen4pNH0=bja1%g4ahL&v<|hX=NSut z#sIsEZ+@R3IWLh*Z!-e{ae}EG_cT+-daRgKIQt~0Xc0~;x{TRSn7J_J!T44)77RAJ zP=<`b^Q7Np%pe9;D+9Ad=js{LTh9gwj%y3HwS$&}=Mx%8ylXlP)1)E$Bu;akIR^PSs6%{*&PLiN*8-+~*o zJJJKfK+AB``LV|c!R%PJRRj&{qszTiL--<%ZB2d)U^ z*=Lr_1lFF}3cR>@u?|DFOm5xXHOZj!7cs@uum-`8)Jc;sUa|@-LN`+aP}N^-s_H=X z`Qe^*q8j&m(x*1<;o|H9To0$a?(UT5WyMs^Bwag1wH3Qsyt8U5M6V8T|JuXm+f9F4 z%*>jnt>0tI{BJ0zG2rOKfL|mhUT20_UES4&?3!&qZFAVw_1TbVV}N4?GguP3x;V7| zVydHaS6O@7e|ubU&$`;5?wqY)wo6W|=4h<0hP*R&p;K)SyY^Ifp&A1=Rs@(xPFNYc z(oQ(q&oqfo+k8vF{ZDCU$HRa&$$|dTP%GmD?PuK3r)&;muRZJ9(Rjh_VZsy5Zqqm6 z@7%^*d#0T%+6pz=a*?)hLRmSZdS#8tj+{yDgLDq)8wnp?)en75!5vw zg1Ud#hP3+>Ff|KcITW%r85!YY7dasi%=_JG3B+;8ypGK@3{4S;uEg0*lraT;a>3I`cDaBz~*Y9m!K$Br_l#~(l)`~@@Uvb0uZ!lwg%(K8%F?nxeIp) z>yVC;BqhsWPi&glpgO^@v)#{mgX{;~a?2a#q#0mhSkTg=>fgQkllnvOb~Dhey&AZd zX`Wq5Zm3`uu@O`WWgq&cc*4+Z>c4$sK`uKK)P!kU7)*N?BELkaI2{7uAr}Vqce!j! zB*!ujn8s|a1vT#TLFTurxfE$T5Z&eZMKzVGPrnQ{fwm)byND4QOmeYP&?+82L|X2q z-Y}F;DecfYq4xVpP^cdiibj$V&scU)WrN_l&Rzkd83H>BQsMkN{yo=1L^-3_n?!M? zHhCMfBZm8+tb!Aujn3L2P~H?U;N;r8cEt13*`aXhVySL{6cs1I{|sbi ze2-)6&Ta8B&s3Vj@i~a8JDuIPZWC~exP2gNNYOca1CNSrT4N{9sX%t0p;2}v>A zRcK~+&>_}peas97Osc{<)^GC6`PlH>#j5w09FXCK-=W)cmY(+=nDkL(ZZg^6ywXDu zllQJ-Db$sEqq4wfn-FgLWoxl#w9U7Be-n6kNm%9Ej<}*$$}G~~0%VP#*<=n|TrFNn zIkD03hetlwtHpW?>mNbyMOo!Nt2&DFRl1kU@sdc~#)mUNelxwHt>I!A*bK{Zm}Ole zbOAl!E8dOM9#hpk6e(GjA95!jU0E6GT6|!&kpyJ;b%P?nYfamFi>)@l5zSW(0aerc zB-GiKX7_JHU1R|Zwy(xkEZFA1!#tazMrYmRt#JKM=(gv7ORN5035>pcljq@jMp3aR zVUwg;wMKp4VhfPx#i+)5^tZ3(`IUK$xgOrRS;ACVy!*jpVM~5zR(==g^l&8)QT}Y~ z^PX>^gnwrPvAcmL?bc+S*Ff4Pwbx>e78-jnQNEUjsCwpg$&+KKs3PaO~L&qBCy z=iK)se~<(uTD)>tVe;2+ojaa&c}zWA#RIogi>mg-{8)fsS}Yj5YzjMDD<2~2o(cL} zW&CX8_;lhMCu`^cH^8-8_U`4oVo|7TW!8<~ep1;SLRBT98iU_g2X5hqX|6Aj1)*iN zq5U_m8cT%6ix__J_tk+X>u1leSg;p#l{JL+|F+AEl!~glh`M{+Si(JMGD?Un`?_|8w~ z{mv6f`WvH_Zb(r@bwb5A-NgUii=Os0<|Wy1?Z&y;gr=FAUhKdqfUgv7yN9hZ$K1ba zaPWMcl4neu_|oNNi^(bhAq6nUoN?or0vyZq%N@#QQ1JajEye(5T_$5n&-_6I01^lw zRDh!T^`SRj+59&WaM}cD#jW1<=9+ZMyR1_cGcU1exBH2IVlff_ZgKt7MvbS26% zf&`fyd^mcy0s@eAWnmrY`Bwj$iDLqZ*np)YRj7A!POK3cyRxkCj!%F{^gwf?r6-;p z?7uB7&l_gb2;BpewGU3i8m!1{?MEk~giWzK3e;f`Bo|N5IkTfnEt*k^y4l-Qc;xe2 zT#b@rJ5Jr31m^Z=8ID836$;*S*1)NE$~QRw_WG%y_$id@4_lk(>ki(=ok@kPnzV#d ztX#FKRXyoS?01E(LJ*AzC7QjrXHTmZQM^9CC{cgwx+=*IyP)v#X{=mqyvKfsR_-UW z&s5q`VKqY)AMjhK#{zg5`Ys1koa=XgGr}t(M7AEBsU^PjKbvq5i7crYknWIOUXCrl z0)GugRR>X{r+Xf7%zNX#3oBcf&s)@{F8-A~Cfd%ro8j^$YC3DiBClvLcjBwLr`Bic zOF8<6Op_;<9Fc+8jW|S0S~Ll0UqFDzLlaj6Pd`_o)?V5=+qy_ycZSLMNV-1H2r20X zW`YV)C3~l>B8dlrfQm!UtfJ2j96FH3I@=$ERo}&s0_k}kXS1OAWne4k;RTBlQ(e`B}3qr8vAe2|#~`5foGIB`!}B9K?=aPngZ z;Yan`$Epa%%HyZiPY%gA+@by}(?cT#tdLrckHb~tQeg4G<O7w{ES!;ly#4{@gq0 z`&5Q_+LD$8T>E7x=Z$RhlJ1@!h+@`m^dM~W>`*Fti!P>=dgo zcclOdxj0pri*#}&j)xnQLjAR>bu)-vG?^=07U;*p(2&xEYKji3fdEJ|UI0Om_fxpr zHe<2LpcB8DKolAfh@{mvm^@ra*C0m#Klfu_=B$<|#o)5%a8#suk1~!lTq{rs`udtd zkDyGWwikmW%qW-<>_0a2R!su|jVceR;k0_mgbaqs*2Lep>SSP|$qfL{`~Z=QnbA|3 zDJSk`e6@M8PERMbxfk-*ERn?>F#*=*-NL?W!1=TFR?e7U`~J93!))3y_n~D%D%+vH zv&Y$?546`=9-+2K4;d>4$*o%|qI2U5(I#dH~b9ed{ z+ypXy-uj$U;Enn1xRt)ehh$VA@(TI{ETChEcW9mk+Xss%9!7UTc#kRdWM+O!%pm3& z>!1?{={T2OlujV8y`>^ynn^zKGF#(k@Fs>43`9o^=CFBh(Q2MojPvU$BW{$AGyn~O zfBw;DBzM`0^w`8L2pFvoAJ7>RM}67qc5sPE;*qe}j+B9TriLq(_u<-?=y~ilx$i3T znEnU;;u3(pLOVHlUsa=E@;}?=zC1fPw!*N$l?J_w7a-5(4}q(vGQ)k%eJI-* z)75${4Dz<(_=iN#ohwV}D1EQ&b=a&94+!PE`}We4x_7P*C_+LO-s4kQf&Izxn1~(O zXHtKmUg$pG9BYgqUUTw~;O^L`a1tVHdIw<*6j}P8y<_{^fR}jj9kvJ9+7vI;>vMt0 zrYdQcS24r@l5yM}OdThGpq^HVt z`VlSfuVk3c+}h{(JaSa z5f-_g8&Hpv?n0~j?F?0($HP7iidOfrJBLye?e*qwnQ*GWdoy1k|0G%;W$ks15j2sW z&q`iqAEZMY?{C%ob`ia_34Y+;CP8@wBw=;@f4jo~Bhx?L?pizSH7{x5E5lc-v;o|%fm z!ObU_@7xd7j*>1c#BVTq{nrNsy#nnI>xYZvZQK{(G9K(phNW41e%RhOq`@u$GvxhA45KXOWWhnIT-ZXrUJI2cFq@SswY=Wf4z zHkq;JQGrq)k82INutkqUwZu#^4STky?fn$)`ae__O|Sjbg#MNU=l{wy;$$3Du{ml%DUDSNVEw<6Q;DA9Z5B&56!?j% zGkZ6aPU<2@Ic+YNrcd_e{2^c~3j;SZ&IbB8I+Q#gfhRb%<^oCtUHYLgZEgeu)>MA4P^#0G9=}^(&#QlDG&ebo8CrsHhsR7m@dGLn} za~DIO9vM&H>Ni7vOxgzT+OEQLwr8Boy;9!PPu}ZZJS)+V9K*VHBpQmc1?!jiyL~TW zN}u){us=VP-1J4}685E+?vTdfg=P^l?beu+z}v?YcT=V z03nyr>F^{w2S5}Xz34FCkT?hd0HnwOKs?8i%lYJn3mfcainrua+xW^pXGU=B0eJIc zDoi>g42-mI1L&w$R;5=mWvf4Y+X(a;IL?XTAcKG0xDC(v6gr!7Ft>Wo&AwbBAOkZ& zj@b)TkQtEumsQ>xd*?3|AL4-*Br;)HP=dycU*wR??A(|`&(mY_BLQE6k9K}yta1`@ zM`)+aY+Xy?K7$>#X%&aO7HaMu_*6Y@NgP#Jiofs#Xt-z^jy{{9dI2}}kOf6=XJps1 zeTFG9MgVR#s#T5*>nv_p8V%)tko<&;9NUB0)w}i|Ur$|CYBLQ6(NNm{=(QeXP9vAt z)1tSNw+M4*0n0%40e!$FL(Px%8J(H+2zy_Ob*1t`K5#wvyj<*-WWUmKbb2^QMGe{4 zndGz8#W(m#Gq3ZN|JK&yua^rsOXprZUH_{OICtUXmmnQG7EvevH8X~o14EWSTIV`A zJ-|5pk*piu0^*uQttSO_t+5m;j!Nd($W6QKh?Vn#H>P@st_x(W51d%=1s%gPIVL#c zz%as7!5l2)Cn{29+GCJp*@c!DR7cc`ENCvgZ@~lbh>(2BMr0NW&g=AEBZA-u>VCE{ zDDwCcyMKF2m0z16RNmU<0hc_2gf4aqRxwlpbr2ah?wp`ymrS@p+iT?2L z-8qXl5OeW{H9U5FNH|05TuhmI+x{;x27|TK#1)M|RCvy%0hC;EFJghW^}1Mk3p5kC zJ9eOF{R%B?>S7om{`&k3g#Nv3_yKzA!zs)0Gd(`y@1m7-TPMNH7pEv`HVmqrdsO$o zjVW(~7=dNIK;COHNeNW`xo{rX0`R9{%QFuJM+|M?O!uUn;F;xUT)N>*ur1r3rU^g2 zg?~dwGZJZeZ?LJ$=wvV))+Fy)Tplyb>FK$5x={c?L0^*}I={3}4Z{`fv10Kq(TzU6 zZ9;QfYBy9-=Lu^S?yxNw9xZ_2@jhWfe*#r#ATKct4MlpbPNfKN%2 z*+@aik>8*V*FP!|m_|e$^!n5<(oy-qh&+v76wN+199z?RdZuUB^TV-aA9I@MQDuv& z`v2lj_$JxN4-pQg&ip%jx^U;o<*x)4|MVNaSx&s@E1{(|Vq5Q>#a16oH2g%^+AM8E zzr@GGoTFej2+u8@ER4#%yP5Bu8W9=qx_p3*N-JFjgMQ+)J6eKQvh=s54n7?sjap<%n!+p|*VU_HZ7%sI?UT|0D{JGiBcgb<2zEvD{+!;kbcWwQOAq4?^UP2f(8!M!#^W2 zF*?(k=m&;k;(0(a({n*vq%|mJ_W6&d?k0AWVT9|F-uuumf7U|xe~Cz$iH6GgH5Z1k z6@q(TN=eIcm$rZE1(}T+=h}Gh9P35sI|Bx&^oe3X4@>yUV1-VvKis18iXJ}eqSANq z(^k%jZT+Er24Ymg)Piu~3A-&7&px>B^tQf!EhG>}fAVU>5Vc(f?F5R3qc+GVTXk@k zDqakObDeVV@J58nd$~_kN6m)jTs;&4gFoO5b`33JTBhQPj`mbmL763H*kPG^<-wEr zEx4WQTZBV!V`#kcG6$oL(*aNTO4r4diGC~bt)O;4OP?o@orR^krr6@VT;b7&ZBGaw zo-_i~m$^k-jc+bF0T#C@jOy*t&&r>L9E*e*1v*QDE6bkd_~OxALh*I6SKpq1a-TwL zSrLWvV;bWh-4+S*!gS8JQju{6q`Xum{l{laxa$*_BJ!XmaCGSd@z^NC$MGXu=SvyS zg`*EIMBp#Zs;4t&v@h(y7uXFHHqOrTud!>sFXA5Nf>{@ zWArOwV;9(zDxm)<7}n`EgBN^i1vH~s^PAQZogC_zJ)b7OcfJq3E|nX}@8_XyY_U8Na=ozn^2|3Z$xIX5xCC(|`be!%o!( zz7Y~I^UN3kYiWM7mDRFS!zCr8USuWCUq3fMzPI2)coAR?{#lO$ons6)I zy#UmM)L!HyirPZmb=6}qh0)ND?Tup=PicVJD=NS_HlPz1yB958Ma3m1_#gq|jg zRjROJ?KP`9kAdEggV!11wxuG{WkDIn|77EY<)2=UB+Z=ZfE0e+^to*2d~Il&E9;m! z?;>6oMVv{C6o&7hSH3EqN!7(q9v7U|x6X2Le=cKjz-Bl(M)q7HU zED!SrBpR>c?&;FIl>&2*A@_k9X8U~7x#cV7NUI{{9^!0(=4amM+^*PyOZWPAMkW|} zoEzfnDzIY0eHalIX^mO4d;S1X=&$>l@DHYylm6TzNqB1i=l(%{lxL6^Yr`n3azm>r zx#7l>oRcCEi6d^IQ2c6<0?8MyB95(@f}mrN9R2|n05DsMbLH5PkzxQdOceyGKlhKI~r(ZFmf%Fay?dXYzXrKrV*vhp74x$u`z}CnW;vqya z$&n_=S+aL%4&M6VJVTl-_!6+6P`9P4Fh$S*hM)epL+34Kg;5%33fmkE-J`hSm=FV= z0si3Z=Lkt6O`CqQ#XTx17cg7e6)sdCGj?rjK=yBnn{ie*duM)p^v;b1CJKE#5{ZUq zSlOB6ncTU8lN*}XWPbUOVR*hJx8<+(moe!aw@L)=R`)4@qh4tv z@ZP8P2(ei*Ax_bEJJL&OLK?s@iE+x}>_iX{rXV1d)W?&8Uv5)5`v0~fl4{%eGHW)J zcNHOZ#o-%>9w5LihtKs!=3R;QfIlfjtt)IC5Dmu#Ba&*(HoKkepZw9@yRh#K#Vs9w zsnoqSRMOAS#Y~n0P}&^2FHow?9$!6q>8*P@A{LNxDPM746V6`~M?JlHh80WKU?=K4 z-IUwDO!dCDnh;e%zBbg8#IP){7Vn-+aKg+uk7QRXkr)D59&Z~qyRAQNDUFDO3KGfd zu)ET#+^~;w^ZEksD5n0FiK=icp{0n$wCp2Uw?8j11g$2_;!I@bFqow=Se{i=?sg#- zeHhlqQ&U-u1n>8bgBKI~(08X_E({}V>qh=IzcG6+C{WuIhpce)Hv-WRvUj|p2k#`hRacqZ*SnS|-g!QLq?3b@R!czkRz9j8o$bxINMeK15 z*%z1iT@k^yD))1&Ha~Rdd_)SG&9vO^gi3C%7hpCovqX9@oJk_h9!9^Q@os645 zqYj#E(j3uHd`wX0fs32A`7+qc*Km&U`gQEH$ncF6|C(ZcN>i$LdF=hml>$bGU+>Pe zTj|!qO6M)tTpK`F>P|09Hp((tU=jCcHDWpM1n|SL4d#+23Ca0~O{i;wy0>c2d_*(n zdLVB{Mz4S5+KIbHysZVhw0ftWnE&q(*HL0`pXhSw^68eWjoaUXjvJF)=BEPOIAPNxY`euoGpSCFB^J~dh#2uzKC?X6@emMO*wPc6UoEP zBLg2v%(791-1=}|*Ni=x_Vf#GEgJ$bX2rjU+`1V_2O3e@Y4Cvh)*ko9;4DUS1*7=X z!fg!FqoUXzhoYtupwBUuG5Wl;ZCt!-UX;NEg(uKVxqwi>(SZgU$y5&*p#eG{B(KRN z65vDv{e+%OMr zr9j9UgsGU#bc*v=wq*Od6zS(?X&Ab}@Bfb<-{bLr`SIQV%a6zXKYl#r|MKG#8~#6j zyq$;1XK|(I|MKI9PyR1I{z7#MOIE5Qh4~V?#vJP6YP>ZTH5LwYB`eow*#%ryq?y_KC0%RWS#^`9h8MMxn46-Kd5(HYnMB3 z*01z|-8;LwbR!|)n2SG7m!wm5{Vtdsc11R*A@1BkLmNr49s zL9IHrF@YHt9JUmYT-Rkc9|kBwrhwv;ClMf(J<=CT2-r-n#mn$iKM@t#MQsN9pC}zi ztJsq$q*4*6%gP7d02k)TnxkFuyp zk@1e1M>yuhkAPFHj;RcYceXbb+4GbN(}lq^DY|p`)7n&cpD+j)&5ZC;j+K#>MP=*Z z*%^@o05{vM>uTzWK2kgQF#N(!FY@N#Z0;i3p8MNePfacB8X3ST(!gE@n7@I7GBS09 z3PRi`C_h@gaxrqe+qppj1&088sUJGoFkiBtk*(xO+2G+o$;}n1xi2s)+QQv1qWSC> zi1VuWkg4HqteilJ#s}b7t94O`z)i7`M4#uH!irp<-TlMXG-8n5kl3HmnL#jDexioW zwzMaPVg2zGqv{;u@n?P(m`{o9AB6eO3oj@;IPxRg`9_OLB6>1%Xx4^SGtiDDv?wo1cM@Q~(| z2HpDzWnaTrh@;9a5KZ+*fd%rX>HFD9tM7d%at|Ja;~yw}Hk6$E`~3NV3B1mMGzm4< zmeB>a{>#svqb60lp?|{9S>Xn&HV~Yj5X~`{S49+fzV2^zyqgnh}*A>-g78bWEShvB_N( za+VmZ>APTmosa9BLQkbT5f>&2R2#YEd+d-S;f>?CS*xN_W#pxr|EL32U^t|Q2oNOH zs)#kp0Ue2MrDA}`4i%D()4Ab2`*QFHqhv*mAE?;zt4u6mc9GkM`7jJz`R;2)Fy8s z2{(#uF~CML!3rX&no?tR0gPEtkcbmPJ?LiHoanlllHxptqlQ;j4dIkD0l77_#&)LC zUmDhz|`SV+-DmfjuG*huv`75sVPjeC~@7(UK&oK?XOq)ov0B2P41eaoV z>eU1skHqjlABwliTVNEs7+!sxMje_uxTV!Bs?+P{OfkdhU_cvUr{m!ZBu9k($_p#a z=gwyZAkEhwzkBx8F2n!{Kb4bYlZRM2de-re^DW2=8WpP1r=*sQ4_-QR7oLqhTp~N{eGz2T~^2+|Nfa|U7h7`;)f@L zHhFmsHw}q#;Jx%SaiRa-ztYgctB*D7jey?|{dds=&A6PSpl&~)E?P0eSle=~e$4&E z(t$F`zu|^6xU}4a%dF`ykg}<$zKDZMXR#EA<*M*`b0mG!%%FlpWSm@9-k^Dzq+wfc zh$gs6GR}y4*l^+(?9kcz1Lf9>IsNDgKb_@nfk|lJozp|AB@#V0I_sSZ8beq3Ybz&N zVc&eZid7jRo6b_~G7yNP$Uwwb5r)%&Wilc?q=^%R{?^dLsTjZPRpa}c-tPUxuBzuv zp&yV#05m;c2K`7>pE_5fRc{AtGT6RqTahsGOa@qLNP*{DEZ^HXgXjr6f!jijQTTj%!`8Do|IQd`)~=B{lAbD->B~ zbZir{#@&$cT37u19(}D5!+T-+E(7D|tJD_O)8ZK|a;YOI?CtQo6H{jIYjO&qG@VQ$ z=q~aMPzhZ};2GKFJv*u5f&F1HjOYfI59)=>8yekTdM~qQv^S0Dre{bs{+S2E;s+MZ z3ie8PxdFD%1m6`75|_!ZPkzN5V#VB^6{Y&ybBOM_1*1r7au3D4dlxQj$p4IGx%mbg zFA6Q@=NI%tfPdANz&8oYQ1BLwmjfiJ@>zhtwK=AXii$s;*EbaCv|zqePzJuQ{Nxc~c1(hA|0Mi$?HVoPf>X3~Mb=zR zU_x$$x9*^VmyR3g0S*5qy4aG}+E&tYjEh&@msX3G+buJ55@co*oLq?nF8B_2o}We` zpW6L6$tU7uP17Izt+^`u#7v2pWf{+WxQh^hgJlRu8hYZy9S!LhefxvFIBwpSueh`9 zB-_*b=sD)Xd`y-V_$F1YYgJND`Qo9;dkKqn3$>kiBlakhL{%ZqI2IKLmeYVVTQ4(5 zd*JF4II?iG93$^Rs~r4Z*$K*?OoJ)?4%q4bEAZ>*uR*J`dn~Y6U(_!n&%0jz;yr!N zJC6CVpSbD>KsX1>|F{}#*DIS#Pwqi4WaFBVmP-2l)|v)&q>t~ionGP|84ze+Ab<{I z1bZKdqKfSA{@QiW6BmfOVa&RT{;s13Xzfe=u24@5!^kj5LGcz#vlqzti7OKFdL+pk z3ApY}`N67AfC0F1%W}1Y;wgKoZ!)TmS3|Vo3vG+kW)K7XGXWpj5`U&fa)ziixC4F! z8P9+A^_brzRdm6Q`5O|QMkcA5GaT!jEL!6@? z3@@b$3^S5v{?!7(Ixtry(SGij7?3t$z)+LlTAq0PwDJpsqx%z6*$&m>$jtSg?4knG zTEqK)=4IlYU2tPa)(6KZ4cSjzeeh`$ccJ?5m8QFKK?O_tahab>l_NdX9OU@gv3#Y% z*&k*#TxKP-K*qs2`mmswu=3GPY_I20$>#;;&2~xOKx4QX%9ht_-N#Q67AnyP8Lq1z zUzQy6_Liv&cGlTtKG5)%6f>xMl{)>-0r?%2(Uo7*A=b%SYM*wI&|X$R&5orCe*})- z1$FP98y-CV_lH4EpFa)1^X8$bf&0M51lfQ0!hU`D4k!rQ;B&pETSAk$%Qwpu_OTo@ zFd$ff>wfR8%dCS1LYWBLTIm0!>k~WGv(LIJ?DH+R7f+P8amWHM$Bk2>cG4_`h~|qs z5aDy)cJPR3m548C1rEl)ES+MGDNIw$@D8?9R_dZQu#$`rfR+SwRc*zL(P zLX*z>v_?3>7C0xqy6p2ry$^_xFt@R&Ksf*)VekGmc2N@$?k%6xxy9C8^ zU`9Q{qGvxMyW^`xRZW0zDRKvJg*HiTqJWXY(D0bRHh=?0YLVeN@cq32@>&t$jAaRr zHOVZF5il(P%&i_!{-wC_H|t-v?ZI>s&19yY)Q8*zg4M)`OK0=QdwbGEPWsTgXW_+` zf|J5{AII^4v;}1=R$+Hu!nH7>=C0ab9Y+cf7$nmxonyT7WdMM)M?Z!!Jf`Bv86Av3 zB*TKJx{+4q^;o=8!JPy=MI$v^i7PQn)TDi}dJ(ZG?t7dd^t`0W4?uS!KHxf>?+&98 zS=vRM%s~9QT?flYVYZ%uavFIu2Q!-`3DQCAY{r)~bc4CTozn%Lo`R!=r+%|`ybII` zVkWJMH{8oJefnK4jj}QH>yeD}A24LIJk2STmG!K)h(dNeBdblhBH3WKeXSwzuA=i< zOmvE~n2RgL-~XehC{J;$$_-~$7Vm{G2j^mm=0FCX$o>5k|Ivqu`^#yx7GcgG_DjbM z$)9`NX6vZeL61c1`018hYav+X^0nANuAf$4lLILdLLvwCAY@kHEiNtjYVnY%PSi+fH z7ZG=>B@SWb?dLm;)8vWAs%ZZRIctjm&-=ort~Nl%d~5X! z4yTQwpq%RkFirVHIg-ZtcCr5yhBrLV`VSE|@vZV^pSK19eZ%aJtOJ9naa+o?Y?ryt ze{RG4aSjrvzNimxQ#_4*5z=yo<_4CUmh|aa87p7}%|Ka<2#99<=br(a>r&TP%Dl8( zcD1ec{5ftL!?+UJ3b!UUH+IVV_9=jFKNz05Tg+-#?_ORUhGh+CH1rEJWJl;rA2>Iy zZILJ$R#uUTP;*@6;gvK+u&ZjSYUzRhS6%?W*ZqmXBev($v+0MeUzu-9FO?=jxr(U^ zzNDMx9Q(e!zz&X1kJ5f#KB4B{+1eX$jhe5yHW*+| zjxN7|>b5lfGf^yoZf{>!f2+yc8*{ThDXaI#>YX^>GHuqnI`U$}bci8%)>H~3^#n)Hw2{C;uI{^;yoEs7b~*_vgC zq8AfXa(RydH;(y!-qxf~nbe&Be4+M4O}jCzsmJ{nnW@cXW%2A5Z8u3YN6oD?M42PR zQf4yUnQBD72-SfjDwKs-lW7j>#zWQ8IU#eO0tfd*v-+aThJ!@{;(P&gv%#Em)M1U? z^(h^3J6|78o`B#1Ax+#DJrY(?{OCja)Dm;$dR_G=ehrZT90Z?P-bW;mS2tIRuCL&gergHoI7lZpR?BSEZ z1;lGPsu(Jd$9tTmQ79}j5waR*=j;cVo#Mje-|f#NX!Zm33Q3COKIZAvKf&!tAHmDy z%k*1td7{%c;dwuSL%{;`8dLrkrsTDq!5-MbIDGz;p?F?Jw&}OLljMPPnqf$43o!(r z0`V{AUfpYEj`|My-7{Q^nkbHU)<2*5)pZKuJ83k$Vw2C6Pgy0u3RAj@C9+g|rq(dXH!`vT$Z#h?Qnqe{XiWAA4C1m@H+;z`ZTRD`B zm@%H8k=}haQEquUm2YJQW*7wlP-$P`Gj*y~cJ<;+lYYW)nGrqBE`Nbpr%1=Gk$Zk~ z8d(E#T!`G$lZDOR$dxbkz`wuZydQJKXV{zBkOREauakPa`>KB{;D^_Mkll?IBc5Qu zm{JBXn^AJ=6J<$;SUHzM^reZanS5fSi|3q0Z4J*wINK#&ptjA4=U`X$Nn*Q4dHn=a zlR`09y)LLhD$Sx_l(SNjN| z%pI0+3=0X4)=QYb%Zw;n+ z2ZlM-lX;o~9SUJ}LtZr(VlJxwy?2R^dh&Q(QQ7cO>0wOHYQfqxpdyb#Jf&IA#M~=P zHl!6C)m-#-b96uapP}b-b9-$_+(-E|L~=7Hko#2Ry~S!@ON*NM%k#|3caGv9NCG4b;(=xWDKMg3D4Nnx zn4JOIP@TQaZ)Iw70i`QbJQtlAMXYA3bGmcGyz1Gb{NW?ru49Dt~PR3>9`fM{oUTf3AMxyhwDvvRMFB$wcRt!4VRPH-oxL)bI>z$v_5yz z)mp$?7|yKUToLR@jmKhz)GVA#BeRSZTy8t^HG%jJ`Y@s0Fg~^zD~=hjbQz68_w}^@ zJqSN*ckJCM8%kT1|I_r55GPsqtWr>VpCzLX(tKdHw%f-d0DW=H`N{_=7r&t>?qpra zrfTldKkt?RT>T`Q{^@bGCcESEpB8J{qxl_m?Rf+W91b|MBN%=R2fXhCAb*3n!FGEZ*z0+CO&2Io{xnhYb zLEkB9nS{LN1P?w6sjZ~7GeB{UGqlC8?7YFKiQNc86@n#q3qA3)qk9hptmVGSm>V^<&BK?XFnpwwIm%lk+VDf6zYqTi4Ek&V3`hO1_AzT=!&vTy zTAaL@zT=_9dx@XJ3icPl!6SpBQhQKQVmLL0HS+@>sr@;AU%)D&z8wyV5^l_0*FN!x zkwlFaCFq43BJn0IhOyDQQPNE@c}KDHi<(Wb^oZSoVFu%ZR4V@3XYTvE zn+k1#Efy1mIYtQwL7-0S_Kh%=a>*Ip8KnYgxd=#yb#g!-Z~S*;KN>O$haokgW(s`- zs?&7)0UOS(aQGW@Z=8B7#oTGl~Dn*=owwF#9{H5^j zkI;&h`^JWJ45@7L3YlxqGN!1F8T`NEMooOQySpf`J%bhm{w8R$9H4rp5*&p;E{t2P zXjr_0^-_*-ON?x+SdPP+k%6%%C)j5^9Nw<2KYwm8XhSo1v<}Od-aoF}i6Z9M{3Ve6q!BU%#pIq}n#cFPi2>GP=@FfFw%YFOr z9%lqi`1y&Swmk_;Gb=2j>LXp+=yQ(x4s27>%Idcr%hVX;tg@t#iqiF*$`&91K4Ek| zYkroc6!2ad47s$l5XAFri~8jWieH#Qu{aBzd^0$YYb5(4l^_AD!SS)hUu*&3{!$Qg zX?^!5GXU@u0G+sm${^W(3}eVClgH-asZ?Q?LBQg%+y&ST{dfWWUzCX5pZj(V@M4S0 zyEM*;vq%Sf1~C2EfK^Z3AB#Ms7Cwf~05_VQ(yw?gI=D6z>0V{xWLL=9rrw1<8{pLQ z+;e#51j8Y>6!~AU3|TM)$UWlk?btFQ6_G7Y5eXyCH$<)fyfXbRV2htd$IW!O+7mo~ z0j1co0X^xrZ^W2FO&cw0eUoFhGFmn(!kdS*yZ;}i-aM*_vyc0pWLN@(OaxkRBN0%r zf(Zm9K*$85f@KMct=@G3#a4T(1px(RNmweVKu~P8Edq+I_SOmtipr8ekVOIs1O>~I z2q-8^0tqCLWu83GIqx}d{+dkA{FO7mb6wYW`J9PhwBf!Cq(kZzPEXB=!v3fde&2ix zABmS7LiM?$mc2SEtC-ws0r3!=UY_aOb8d*oR*sh_E}_`vr1wR7huDzE{pB%lu(nH( z#*w&653GEGD-Qt(`3-_hvpmJ`LZqW6ZEUbjnc;uShpC(NLtdXc=~ z<2S!o7~IXC&NLR3=WXQ!Aliwz#6vQHqjCT;2J@y31=dcGzsC%Bhi96H+r!W-G-`pV ze1Jk*f8|`1q4M(JfyHbfeZW930Qt0=u02XM!y$TlreJ-8mmnQ74bCR-hDnc{Wa#bl zYxS+Ea17ssgKUQeoITZ6Ok3zOk7J-g1xQ$gFsb3tO{AZHpy+BLH@^ zqAk4MAI?D3F*}5w^78onzR8hc22syQAHv07ztVCeAj(y#1IzNWh+DH1J>k_93^~-L z($F%D5$UR?T9X$g0LRi2_`6Ak=+HT6(^?$-s%o~RGr>?G7=&tohyAereBF$P^;KKQsKJw|bqUWmCdMb`6DT6BTYr&-5u>BlKtGnkF?J(=Ucm7P^3 zEiPCne5Av~YUI-=Qwyue6f{B|5(DJ^b!*vo^>x;$%~8;(k@-+dRM9WYx}SNahb_ZNkSVp!*RV{B?-HqyvV0$ii z{R1HnOcBkxb6cxo~%NR{`Fd=&YVG=}2kwC4^YNAl= zX*x<0S#qY_J2WT<68cIM%dJhLDgWxRB((hFe7$yUp!b(^$7eHP9sM1^am$jsBDF>! ztRfO76UxrjM5(sYqv!4p%npB|ATgQQG3LP-{T>nY6B~$I5v};c`&SK}NjOSH&ps71qh(~;sNK_8j2!7<=1|remgJw8^Qxw8=R&4r?F#4P8!gnB{f-Ll zv}5|@guI|%TgSF<@q0F083lh5AzKH^``L}7s=(s+hQ}{_AGL8eYR_pjR?F;BazNED z8h%+QZS`G}_c_1Ok@s%`2mGkcbjH08#mBFH-+i_gk*;8$A$MVY%?v#4Z4!vcC(9(< z9(et{JVmYj-m~{GN>lWGsi4$typdCt-r@Am$k_0YLy^lH?mDRdJ<~q=b?r%*-%v1R z2eR0bKza;Qt0Bmf-l|NLWxLg7=O^O?1DQ)HOrJQN2YxeBS#*VWajkSTNiCiYqFdW- zdaFCLOOCAhkkh@3z#bk>iXKunoBz|>+BZ3b)Pj|#=h(iQnh&*W5w`63EpAr7*eNTO zV>vBDYh}+AHGvt=u#G-+Dk~HdyDgdcR=f6{reda7+KQiM=*<;WS+@3?BE}T}_p$wS zSyu??wXdAgW&(dTdp2@Fl6VmlB6Cex{&rZ>Moak$$th`)nJKrle#rc0Wv1-u2u*X+ zg01vPy0;lfZUxU%B4FZ;Sv zgDksTk+SYrq%=<)uE@L9IlaD4@54)5d*)4?RT7>8Y-?#p$9n#=j!Yx-=Pgny(0W57@IFzUV2t7Jr8;xaBu# zqTP8-s4Ko8{`q_qPGjLt7ZS!RahhpURr#h_Ty(UoDGPe^(u_CtW$=rhOv0^4AGiEM z`FZ5Kap;^lap!E)uJ5ZqO=ry-uIRLW=+XU~!GTYR5} z^@ET9yLRkOa3(?))rRk+zBjfYBZY4g(DS|;N9B#Lfdw`wU4(T)l~jSDJnRk+?&+FO zlpW^^%eP=QRNoDtO!f>v-)@5AQiLbcMI>J)8sc{#f*F5=nhDBu3lGI-&b@2h5s}xr zY!{7vNc>5ULO(e@Y|a5m#8QJ{Gj3<#;#8<>LHmDet|5uGb{Ga!$R>O}^@A=VT=7ar ztF}NJGrD}Ru!dw~#cXrIFLRdiiR&_~QCSUf%8trQ#pMe`SxT}s8Y}&Z=pzk(?}%LG zUQ;KdXKYR3u`+gGvCxe9U5({|d9q#2f~={h=^oHX zHG>22E?aaGw>%(QP42`eY+e!GN z$;@#epxf~F-Z6#A1~RMo*nykY zB%&uOc``(R`nhF&yP8#<7&}iQT*`3)yL7TPHwgt)Gk3$&H@7%Wb9L>?^o<{r7 zEi?nka=F@ zP{+nbOf$Dlmbq|7b2ru!#1)V!SDK*<fG4IbA5+CK&nai+>}xgW@MYZ>#a^?bFyS;R~K$V)}@YB%hqFMgOeAl%{h876CegsX(v+|*?Dt8R(SKV zk2#-Q=krT?k3?1QoN%dQ^x)F??Sz~&941X>oEu+)hO%=hSwqM2F=)J-(*ht)c0l(! zVJ*$avMj_v;1b7El1mxS9dFsSMaFUEa{@n@Yvfk4?3bNmHqgH=7JN!tO+L~5E8jj7 zur)|ST&Ky=kZqEp1~?nWbI#O_HWTq1<%B3Zn?y!gz;vizYj#HMbthuXcl?pDi47_@ zn_@h=UVP*~@^??=2W57-FM$-M`JD_#>~g!9IQa{39Bp3fa-RS8Rt%84_M%@F`mzrx zHVR__bjVdbjb!hX*G3t)tC^}3;B2pe1`!!DNZ}eaH+_3vl_5zzZeUbDMh4T<7ir3l z0%r_vX9Ak9I->v^cIUy@tnh&zz;O6j3z0DkBw`yN{*<;Wx_}m%gO()#=j!;3Ts} zyHC2xZ?2%Ze)X@aZd}rMjoMum%|KHF^-UfXDGxU=Y5UE+8>8Lk!|u>CT>?75xYKq| zvmU5E>z;h=@`Ubumn4HO0hOY$JX=OclFW>lerK%)+Puqp663;!aS1M(k zXhUjM7ON12{6O@0zBu&Nrnm@i$!YXax7Cfa!y~gJ zBkkUYmd~mzUJM-yLR*QXotclbc%L%8-?N^HPvx5L3^Kwagrd5Yz5DU;i-oM08?fhG z+?u&EliBNyMpm=xqQkJ@DLJDPX01rJbdDySz5Z$I?$2LDTEkB|;e;6IWA|KlOobIP z8Y_3lt2!vMsTV$0Yin+~?55_A)z@yjd+OM=JH_5aREISVL(FFAo%6^4hv`6D(#;6{ zq`)Axew`XeDF8e>649+-TNFcS(Od?6@K35BQadzcYvwSxgHckV>SM1M^TLF-v#K}8 z#~q3V*VJnX3KJpU@l=_OVwDg>$mNjr4N_e&cP3o}^5c>H-RV{iqSuAixQ&LUrF~5X zL-_-n$!BN*7yz#r%OR!hCO9mlo@v)Zc@NRHeqO@i>Kv=78DUon3HdO~PTP9d0lRWM zXSWJ5AqJFUB`*p9&PP67EPByN9e#zoU)!W zx_*Oi0!ls0)nkDJf=xFPdeWZabP@{Vk3|wI5ClXS;(_eUf4Ix{owqq$vEgYIFHtnR z`L2(C<65@r`lx1pgHiz_BjKpvng2MDp!KPWOa7qY@GTCe68m*XTG2Fcd1u;^!A{?(ovTL3+Z)Il(4B|2s zI7cWIB(GzRaQ)@$6aSG5i5VVPG(Llyh_xuV|%@iB3wBedC?z?dQ#1MO>19i4_*O_~g=J(e% zON}+Y5~&xw%*w+`mAa+^v_;;5u?FxMs^i11Zuz1MhaS~-`s;zeQTLKv9ExQ#8P|=y zITLF3*%)b&gqCo`g+g+$*rmcRyWmNRo-B(G)H4C1c)MQr2-3*sI1DWNIye(`}ftYlIUj{Sh zRkNXEEPGiN6XY6(iG>ygZdQxwQl0?U6ZaCDr6Ns3EhFCE19d%ep=h2<#wLhWzTOXE z!8lK)BYRWaNwpF;rG-K*G5i6bDID7v;o7qPHO-|DjcxbM*zTOKLnEsUF6kBIc?=`! zm-U4gGR5_~CwYtqGx$|Ig%UwGb97Nv0T(nryIO-n818d#av#RsBt|Y3|6$#LAGz*C z`iVlyeSGEn_$?~-B8>_H*27hex$@v0{S)za5x|qzR&%CHjy_b%`sO1nhD{;nLL_1c zTJnmX%8oGqwO4jE>hSeRRkE|)H^=M(g00oBh!&*Py`1(w3D9rmo+IJU;0H5yJZ0{U z;=K!#$X*U-z>ceA<4bAp7r=ctOs%KAxbv`%O()7(S0w8);CnHd+IbIEK)6IoF$V_R zVwaR;WR0j=*R~=aEU7I$#w!@rQCn9WH8WlxgC7^0(tS}n~A#XzJ(B%wyMwlM_|cn+k!gsNbEPG{ zyBDRj3?>TrHBB#+2w?Uf*O8Aa|4)TG|23O3|l<{{D@sH_~ z{u8wfAAHk~V-5J61xw!W4<-IvT@6SiHY*xWTYEQ*t0(JQGW@p>l7IEW+R>USC;q$} zg&ezAUyVTn`Xm#~bEk6VQfJx^gFQMi+0)xp-@r6mWv*SdCq#y~14{ff^-=U3ykpNo ze5Wy|njTfmrvm(I`?2Q(DniFTC>1=9S3a6!c9ZQ2OevD`aDSrp`M|axhVK#GFt{$8RsaUI+LA^p8Js25v!X#MX4oKgW3C<9LC zFq1?%1+Ck$jZoS6N4$f{O=}G0-Dp?TqIEex4>19;pq#WP-QTwxq(mHR`(Bod5TC;^Ng0=_)UUjdd zxQ08LUpCv)7v`Fzq^Sxh&Y4~`NsG5Hb6dBke>=r9AXoUjE$GRNa#Pn6QQ0c%?aHNH zy`pgx4!CI1;r`IM%NR>v<0256oKRz#_$h8=`@F$dfB=T~P=Y-5xHHS?Du_IN60^>v zW`kpZRul?TiN&E?>xC*DwnQ)uO|4Z6!Z@ugL>F7bc@7vRFd%ph-$xkcW9gqtI_&b*%!RQ2zGJEOu`G3dA)`7 zn;vP=@^Yo1-)-Bc#9UXy=09hztT0Q3__Np8jSs>W-)*FJ>7#JZqJEx*hc-`*@jkFh zXqPRbM-7p?FQnnSx{KveONGrN5{P%xBIbw-H0h$WEk~_!et@;VnHmdMW4}ME`!4V| zDmSQ{{V>4K{2Ktam1yEh7RB-!E@LSw`1-5!bWLy1aD2b@4R#5e^Sj<8uh+LaLZB%Z zKpMZnX;J-uU5=W#(pcn}znM|&9k}pctl5=6hvD4Ah-Mvnx?WjWza-VT&gKg$IF%#>FbAm2xSG!$UzU4esC+ghbnKX z|2H5FMOf0e`#eb=B4d1nmIWQJldET5ESH`ZoA0oDRW^b%Hj2(cR$a|fv=-xum1mr2 zuUW4gyX)^!IpFo3&onacx7Art6YtWoAx>jLtZzn|b+K@nL896+DeW3}tdU`L05JK2 zdz#p%=SiY{(HQ4d%;Vo995V)SRjA~o@@zd`_EV0$6x%8crDZ&mn=mIq!#MYKX2k|l zMQhJ(hbFGNepocA{JZ^j*7*jcnPGUk%S!%JyBx*Kfm01^Z<%mouwlz>d;X+t%)NIX z$_fT2V`>J=xK7_$9Zy$855IhBb7dbGeO)if2K@|G)TD~DGM!A4vb*13aL=xMQW2C% zsubLq(c&u7)4uSL#%(Lj4C&h}`*C>%r%SrEG+B9btwO2W>l@S9Ji-v%$aN!5E>6yv zyI=eIBxibGv29IwB;%;a4tIpry}jn)nX!MlRTAW0t3M|8cyaSOd; z1rDx_sQ|s{=sm5r>3!T|>pL+4n~VHp>r_6c0^4+aWl^o&wU2Na;V)i=T4)KZ*KWP6{Aeq+@l zI)8@w4_2>jo+|#Y((r5unW7}}o3JhNnmW=^kCY;dNi@2F5+XlXHwYh_Aultw_6;Miq!g|+fnz}gznMHQ$cR- zmo#w&$-bo)zLkFK`myn4u9>qO?k3nRBF5P3J+y}_@?ymO57Z6j>yf|o&yKjx=RAP_ z#BZW{GuaOpZB_Wx32n*6)MV@mkyz$eb1TG9PHi!)8Nafug`fLUfq07!b_44Uw<`Op z1}GYop`UMvNP%yuN{XX+w`3MB@9kXHl)6!rF=H}&wYjAQt9VUWzON@8TfTK6ggeWw z2>oA_Qve?1bE`UL`uNjo^L4&pLOn&$a~@(h!7#qt%ETSx;wou4Z13pP`%2e*C7&dl z=_OTvfd?Qy`gEsDC4&#J1Tz9%Htah56(|?UnP=v#RtlPo9WvSEe=7%&hg~iK8MVaU zWjmgMJ;yf3(qj9cCI9eTeAK40`#I$_N9p8{@BU#zz&U(T+tsU)T-WaEAo#J3z{mAEB`>g4uB z*TB!WD&gya?s6eLUQ>-d{u)YW+p^bm5SrJoXB?0+@Dkv!ey*($Jmf zY4H?|;L;%fbGk1q&Ay*=KXhseV*pyanwp@AmCN6qD7k5;B)$%#f(yZMuEB=LZ8(w- zfHl7(YJ$QHE?+{&9%szEA4=X8tbdi*am9x;TP3f$Y3e=|*VNQUb9rH9*cIJW{oH8- z==R=h)3v{xjuuzuKgs?I1GrbFWY7@XcKLwNY^#R0C_Lk=q@1BH1)g!! zqIOda!Vt1S_^JyRhy?bZT}Rhy%|H5db>&$~C?CL{$wgZxxOr7wDScG* zxJbKv(DQEly8F157hX5;a*yi#qYf80#R@k`K&INvwZ5G9qQF z&%9+t9UFKPbtrmqpzW7}n?vk<$Gy*;`ElQ&i36qsYhk-?G6~s#yu0j+!|x6yeOj#S zR?miSDU8fWb$-K{>u3LU-+R%Az)m^GJ{0)Z*_i*-vHn@S6>nhw8qoeZ|52PZ`xtPJ zckxj4Lw?tTN4bw;j_Y+UPEho$CTY95&ckS$Zr(1)3rr0T`}Bd=zhmdiH~DLWm)tzQ zeRuTR+6|YbRYr2?m-Xkj@7L{25kGRgk@25kKX&1x+So@IW}k`wdGy`v`nneS^8-!w z!Besn>F>=S-P5R>$MU1kAF>s*znlM3bCS@%s=ed`Zg+HPbi}tF@!t$qm7R?U_-)!d zGwG+8?3}27{=6_YHOl(-#mPr?pCXn|Ggk+fe(L#2`+@E`U4*}PX()JLW%9B#CQqE5 zy+4w^dDim$4zrgZc0SIm>)!Dus;F*ZprbBqqH-3E)eD1}#?`YGPilTJq z^Hs^GAATvyOFDW>iDeY>R+28}zQ?`) z=3Jq4j6VUfGh+ZJn==vB0LU666do+kb{zA1;5hR!@bl1uzet~ua~i=ODySZZXO0ve z^f9p~VJLDvv&0XqtYoX4m+Rak(%fqo2Ss6$RlX9-RFuETrw>w!wV^1eY2rCz7%v35 zi@8(pe&QVXxzT6jP!Ij3r73{h-$xqHP!~Q?tz-jlM?5SaS>}W3r;ahE()^FcJ;QBV z14w%w2m0^um5wh5q<7X@IpsLX{Je2eNe*XTy2#5eLMms+Kwd9>KyiTmo;!`_wY=bL zql9n6ZLPlz+?*k9L0bY~g>02O1Fe{%LVRpPM_18$r%lBM03S|!(fRJ?}kzAdnm5z(5jlZQr2%>{wfkLfk(PsvebbQjV{4CNOM+SRD z?B)pC09&tC>vVCIx>~I@!&Gag4*s#YBxu&iRdzH+eQqc7SzeF_5-6-a-Xt~834l%|RA4cgIx#llpcQjW^ z8G5?;HA?#$0I&dHoQHty-Mkm|0Bxn(x#00fl^=FO@AB)S3fR;ialXMMz-N!FwWJZg zGiKp_-WKBepv6HtVa&l~;HBBhz7!c}3lTgjmGfI8BM zPZtOXt6;*9Q)1@v@@J%hV?jW{grHl~cxE@fatqb~znCg$MUL4uNk zs+aMC0wW%IYyLB=q~06fjD_sIkzleQth+$G$uD>NQ+-)SBa6g@_XhSi)q*!yqdhhb z_5Y_;fp?^;sf!eB95!0&a$Y(Qjle>@6)T$H&IqbD=T#>+??W&I9A&=B+FaeplSol; zWZYfwL7fIE#bboY3dFwgsT4>+_x=W3Wj^2o3qCp3mrCNJ)IYz;u!Q7rlkg>-aQn0dleu{Y0WXB#%vlGAykNP;$it z{XkD-pKMYxuGU;0jH@pYbwmB|^Wldns;F%hWrWl0?S~i>5h>B@e|E<=W&Jr_0cXCw zcD{9gGmiT-DyFBTJYiE|N!tX={;@UssfS>9gj`b7Wt$1zHsniQH&Cs&-eRoZwiib9 z_Z1O6QQ&vq?nD&l2WFaGHwF>*ngTXw#(EE>Q+93L_U>Nv#;wm^;rD0TtnO}k6g4DX ze&tB1D-C)m3IU(FyrJTPEJgkEZrMLhzkOT6k6F|_`G`Bc-Ev9#Yu*Gnzc!t9VWxF+ zp=03y;r48Grd!kr75;-uOr#xg{xk5is*>HGU;m^e?0KkhD->r4oL`za_qoC|)mCqv z`_i?nDY|r*>pThP%M(~&Qg}*5dd!XAKfjlks8>s~pkZ)Yw^64k`DC~PdzJw|iqKzD z;S!y%ciz1@Kpx-sqowos_a!GhWes}O%qT5LF+7fK63BGgC}YCX`f;~iwygrKx@vpZ z^*uxpTWb6ZD%u{!@Mp={^=-{k{haZELw@N!Kz(E(TaugHkp(ggD<&&Sc-T6ts91h}XR>ml5zD zRwIGU%d;A6fz?gE^)L0|j_jsbOil^(`%UHv;^lCLY0u!j6?ESUqbDcGQ0&ZT`sQIi z*zX~|ceh)Qwj1e-h}lmzaitdjz6!jV$ms3bkdd~uV0GXjXJp_2$1S91Tuf|K&^!JJ--`DpTs`O$+_I{r5118hdgy{d+fHFxzT_k-cD^l)WV z{>pYmbK}XGQ8#=U+rg!h^0{ojDO7G)V8fp~4xVXp@z`LWHb4j+pATjCm5gyEO`OXo zep$V3*!Y6Gj#>-0x^^3-y$^xy%({2>t&g+YYQ~fEig7D|kZ?yM^AFLK?v70-RRCW? z814#wCQ=WK#w-RuPaaRCEE)bL|=!QaXY_`Vux2n z8bnNOVXTsH`=O20F=$+zqBxSn$WYk}xSz)tts%qZ0j3Us?MS2T140i!#2!(@02e{* zeJL+IAMwG!ZlMm@r6{OY3TR_A1f5dW>I&sy!5r{lrq7IQCxc%-REpX-M1`NDzTG)f zJWS9NwnS~uIh`WlKkyahuV-iai|&~YV*lMm*P_2bqX&H=hDG_CT6ZiNVcaEqlOKq= zOF`9F9&BJsrv@~?lC`Z-<&~}xrkjjv*-nh8QHU_U42W*AXsOnUS2=ZAZz42;jbO&5 zQyeU|vX8#58ZHTj#h?0b1wnTn!-}RUmx%kt;ez#1cF%Iljk7V5@i8*gL>HK9n^czm zg{k~OnHShs$dmocesir&hb zTHroL?e$(82z!a{uIp&@f2qNtn}97n2n!iZ_-tS9fX=kejJq+4@_;L7YNN$8u`d6* zsHa`T*YHDI_?3Z_{UM@m-5pB6f1r!C;`fnCvDrrot_a+xn@`o6J*)pN3(xXCzv_uJZ?tvBjGgHN6|kzmRHelZT^>4 zhW_2I;)b3cuA_d3g=S_SE7c46xUv{^AC*zn_X!C;&@;s-e+?IZ?GM2j;Og$WFLI&g zyG=E7p0o=`LZxP}MV~w4^<9tPPOQ18qydZkWhF!I)n1c93&ZdZX_zD~SU~00diLE*x3WAU6Qq-wkkQJiS?(+94Bt-QQ-^J?L1R@uQh z+PJQ=qS03Tm&G3@k~4Dd0(!ji5Hgd#Mc({I;`)^zvJOtsqY$Bg<|OokfbzgzukxvWl=~Yi~f@kyHj(i3&}oBJ{PwM9N9AZuC6ex?ENy(e<`Qh#%`H_ug-7g( zktjAt{7zjzj_3{@ZUa|t2O#=3;f`wb+VSW>_N z_2XkLN4p)!FL^oy!ST(elBp2W+^l98yNrc2J@02swvMZNU}vDnxe|QFAp_wiJ-ui& zwB5M%@@hkwI8JlIdjMFMp|Its91M1n)muhaOjWC7Bz7Aw{)L$RoU`#E|LU5{Spnia z7jj^7IS-wWBUXN;nrxX6A8E6lvhVNHFATX=oN8c(7PQ%Ji#nIHw-tD8APg)nQQh03 zi%cF`y4z4{DW@+f{0*b|=(QEK=+`?lcJx1C8UAPvf6aN%W|}LlqI3iKp5s z#)q@+dxkg#g?&Rshs|r>tVq(|))-xcv4UPU)BZHpWv3oA^3WDBf$K84(!EV6AhDna z0KDl>gcQmLC?|&lK?&HY&MQ1{nP>|K-}v>ILJ*Q;h9iSN2-peTIr1(Y)3d6R3&V%X zPLi#mhd5ATtT02M#|<0I_!C%$?KFxBq4XS)K!Nhr5fcNNjRlG8tSID8Yv?EE zZ4gUNNn9m_!N4i44p0({WxX>X06=*TjA|@|rFc?kI4s{-i%2G7jmoQ$6vQWVTaX_b zVsF;F3p|%2JV|5wYjkB#6dl%fL{t7inlew1S(o$%qnO29kpu)XC=W0F(Vny9T6IN1 z(JC9JE2Put3_v-P0IUPHn!fhz>;%r}`yfA1^tnN$6#kVk8h!gt8Xsdu)YQX(?2MiT z%B3HhlN$iQLd4{4!>+Yy!M{CYXV)%g^b{J{`75a_Ty z+R>UAbK*lMB6<$JHH)Mv6E2hYC;;ZZBzD3EgCVCAC<7HHi;VGjp(&tk=koBrIF0V9 z83_*Wqti2EvCF7WHR;>8nFa{0B)!(gZ6V=5Tmi;9LHO056iJ>q^6o2!gsDVo)+t9> zFe_=^Lyh*oVQCK3y3gqO!1Y~5maUT{CYKwk)F)iqOUWu_^ZX14u=y;@)lyzGe$!y( zNwMU(_k8qim`eQ+GtbXanv`Y${$rnu&LllG4>H5NtXLG94C<_Fnn32i1@Gf>t*|{@ zRcgb(-gEC%fo_Oy(8MC9mo_eP{H@9K$0n@$BgMYU>M91%Bq>tl1_8ALo?T}bsN3p; z#FDODB)0tF&#Udmt)VG7`}RqDvKr1g>r_#u+bNmbLGzeO-H_mCyZ}mjTL~#{p4weE~x8R`H7TqRyM+sdYz%EGIn3)qF ze=6jIiMha+6LvIq$H;lwum#)~x^(pyY^b3-ZW+3Z3K#qU)`}-K6y@r8i%HrF#(J0# z{s5{+q>bJt@T~4N-(-hotv_>(QGT|G<|P%xi9ut_o6Svr+J4KB>5cOhU3F3QQH*4j z^i*#pro1`;+X6+4eZ~1+6BfzeV)0)PZGZ zEtNFWvhTV7r7%+w2L3Lum~4-l(G^R3GrGPKX3gVAhv3Q`f^_*Hi>xQviib3O*D zKnrRSMIvXi$T*sLJ0BQ_b({hKmWvG7>4!+E)wY1&(jg3=LUaH$iktzVLwBR#Io+tj zHc_zjo+u*VrI<7V+A8F5sgR&UF9?WcVE~E_&q3=Xn$Vj0hvD}VKXyY{62U% z)})o)-p;=v-kK6!&~KVv+?*_J4n)1ST=k$yyJ-K=iN7IJb2K=a47>dA)HuVI=Y z`jk9uBAr>XzT3onCjEG>^+oheL&Y8k2OB4=!a9wK79G}hPxRG;6?IhrPw7ZGL5ipz z%HwwC>rl2#Sd#l}*f-#0w{DOQJCAc9i%8p9fU_8g|Jh#kY3A5Y=VBkt1GXQy>-!rC z7-M9%h6I9%fI)GGu?J2U0n5s8Z|xy>jJ?o08f&?&1EAIz+ut!oSZ{r%ptu=>ZKQt_ z1!y7DR|d^X-_iK#Tp}MT?zaPpDk#X28#Qn-lrmPbb}^X}2R|q%YJ@$f_7%A-Xc%^ibhIVNJ6O%>cM7SM(6&JXHx>pLcVr5_Kq3`lEI{r`2I^KZMC`~D z-i-8^)07=A*I{s_3|gSr-~}oV4B%56v6RdFy?oE02;)R)Mq=8sU_~*g>^ou z$B+?ZEJKed78%G0Rrf=n7JE0lh~rm|M;?&z?a8eYKDY@Lu)!WZi4C}mP+lp;%UC;D zfF5c;Q(Piu(oS74Ip4!?5QauvD;fe9Dn6sCyt{CKm--+r-<3;wuS?%g)lmZ3>lA7L zwTFN|_)I~6ZJLMA$Su>OSu)f-THa#p??X&yl3;bFpmP|BQ6*hRWcK1Ms&q5xtR=WR z%8p)ce#Kw1Ja((8ZYVo6#S)Xl$$}EhgR*m2jEM=l6QLj?gXU(Ze{8V!6X8zyo{6A+ z>+N))Vn$D##Gp6)?auyHr?%iba}Nn}&Y~=^Tc*G>jdH-!5{Cl65}N7~H@!#?@35_A zq?{6n7~nWfj1ssbyS>u&$nvJ&e{{L_qZZ*EM<$)(YX>k!>6SK?1{3?p|!CCyC`euu66upE$S)pZYVqB=JpFt#RUd?O>GzNIDrK(0U@JSXQ z9B`o|Mu!OlW#rt_Eo3d#G7uh_EbqjUS6%6G=C1gdGrU$h=ZM*U9Y<3;uAz#4-R^mf zAO9-Q5(ZTwb5D^M#|NFMoS_p}wM3Yv@+qz4IIPM%6qC1Fz14zkTmTwRRlEQzW*Ii4 zS}k`EFrl0ia9oL6F@0BOOAKTkf;DG?Qk|Te)iOqUEut+hA*b^LZ^u+K=Gfs}#a;0( z>+%$c7XX#jyI;K#dGR>1ESkW$$ai_QoRP@p zWHjk)5If+cp-dOcImB!)9fnrSnQ3V|6TG*0s(OSDz7W0<60DI{Xs6mXStkeA!2S4utrkNV( zQuYsl!D(ebFbToFb`;;BFuN!={KQt}@CA*Jq9=&9LIANDcSi|RA^dz( z1H=iL+FGFddsudY<~eDGf$(=Svpv$WhTyQo*Qpa2^NHNs+@d1Z5OhuCF;qe2sISiV zqp(SrW_om#3fGUi%>Qj)o-&J&om`JU=x?vg(u#Y&>!QCIQu;=c4@_-JH*mfe{GwgU zQRZ;v&H+!hG`hT1T$Umqqq`?xF@k~0SBA<^=gXLhkz%(m+v7$R@PaZ(cfx4nec6x` z6|vG!!@&J!uY%Dzm-tngD`n91pfb6^bWoU^zP~Ua=5Vz2B~X;}>~`-m{)(?WTcG_q zUR^*b$v_<{2-iP68E&EP-^4%lh56jGq$cYdZFvDvKVfB~fodE^Ho9TvOMrIA7NAip z9=iY+U5FnpIHLsvd$5y%m@4HzwoMvRp!Lw!y8cAEh?hhdE;$4tnI{|e2~GF(gbwjk zo-_wrZ^fQ{F%FwjBw0^s47BtkQ@6Y*wT1T$=;voOrJ-=lVUgfBOuy;Ue8Dn?sug1d zGW7Li#q)9-3;d<_Er!`yng+1EGQLssejbP~AFpD;IXLRK3>EfrI|b3tkI%n1?`R(! zkU85bfnT5J)MBN}C*vEu{3rtxv4la2;-N^(oAA&jFl`rRrdG;`q|@q^94(4a!)(+s z%<|O>t}ilK6vd0L}>qk9UpHo*1)CJR1CugSmYHpEXaLK^;K~#~-5w~!8gMy88&UdD|BHk2wRs&l^ z8{b8b9hQ7RQLJtY-lvCNGa2)N1wQZ2A4y;CDh%G#lepx2zp6A~TeUIV14tIoE{^HP z^3BxQ)V0%zB0Ua1*Ap+4)V1%!whtQvAEI?|pm9vwB*9;+I}p8q=$IZwKve4=Yg`>9 z8wp_t0uzK9SUCty7SXA4z4zT^3&LrXJt66KO{+*$O+16m z<5QoL)Q2P_UNMCBd`(`t zNRd_1TArwTE<=?g4H1nVL7CN?14i0j_D!yA%OQH3FC_uw1r%-zPUv<&8RITij~$tC z`F)%0q03cre-h`e-VYB(7$WO6MT$B>#(kCsfd8(Je=sJrOdCq`OJc|)OQsAO7e6zB zq>sY*4&QS@77K7h3NYa36?J*&hfzRA-tqX{*dVfPat|10l|Ww2SXM$&pg$;6OOxl3 z$5JHN*Hj0R7Rm=iKlOWg`fptckP64Np3{tW`0%eLSi7Q((jI?Y%Y9NMvo^EdRe_XXwW8VQ) z;Uv;eCxiQA9&pOjzO-VHb3UL6AaL$#>VyX!@V%2Nq@_vzx%zMLwiL;mS!ik^FrV~& zc^CIDmJ|g6(QeEWLBd# zJ00;w4T*V4IFxHSv33i90o`ObU=;2Lj9=#vLd2be35WX=bn?Ia=E>-wg=`I^W8^;$nLn-kMHWv`+H;X%A<|ObamB4?A z*+;VN#*11ztp}_}wqimT$UAxmf8)G8F7R9pk~HDVyY213SpH(35#D#U{7C>`ZuW_=i-)rVHf@DC}O;aBN9@vpa z_CCsdj~IBeGNbuLcPx?n=9<7hxL-dXNzBu~K+y-7kR-p_M*o zV{NHoyL~C0j!or@sEgwA)Fe5XRs=6ipdM7dO<3zC(_;Nd0n`%Ph&0(@P`w>cGS8Ul zjb(X^yQ>AC& ziFS6LwMg8LdGtChAh=_wH8PLVzhY*MVow+`c2d@1b)wy6#$S1!Iy?HCPl;o62Q7)k z24-h{p&0`I#mFkiUp6vtXw`S%Rhi($A6x_KMs7+Ga^e0b$fc-hA}7W`h)GYF${3{BtAYHQZ7-innqo1W6+Ja z`y1BI+|lbg#YD6J%7*^Bl?{p#Z7==Ky5+5+XpW7ft9>>-Wzlof=xA}6T9j_BHFNAd z?7%M>ZGD82KLQ9b4v%}=OAf7b5r>y_adpgS?W(LjT^Eszq+4F;<9#I|G#4j{?zF}GL)%V7=rzdJmX}0y`vTA9 zxGWd;M_9K{@ajEwo?!hRP%dT*IvA6~7!$^T$*S^cH+KYc^d&UTjl4Xw@jy%8iocj( z=?a8b`!A2YHaI_jEqm1g`0s72<{)r!8la>c zv=VLxSTXyurO?Uhs`UEn{v&Ji9${gF7rSKpz#{~r!k{9aR8Co&tf4{oGM1^;q0&gQkeRfE$|0ZQTUEF8kmph9f~jZ2h_9Fg6k zteYyKl|V#=Qq)!Mmb|<)8e0W3ND&=CRIue+?@XPX<^uW zi3V*nLZM);Su^^%?ONtium5#ul*)I!>A<9&BjEaTh@m&->vGkP8NGQV=zYAOf2JZK#2)#mv%%k__BI|3+f3V zeDqw1Qo5Pbb-l0#i;1UhoM!9)!1Ip@F!|}In!>R6p6z&PT^!Ijt2#vywd@%X1!T6% z_qJxX`ZZ+H2;xyxn>ylda2U~*=l9iPH3L$UTiH11K#uDvIk0YXU%-)PKKl0r3@Sjp zq+izyE!vDl*Uh?d{-t%7)$0%-s4Y3J zfY7=zFH9^%IS3xBm*>OJbBtb7x@KH4m|GIsliuw8lF{v0M20QuQdayawh15rZ%?B$ z9r|8|4-7RX#LLXNXglu_af4_ zoIOnhgVWebl9ATt_^c%t$~=ZXrb{sP*O=o5)l>M7y2*NH&D@G_bV5Bpmw%3AXT6#C z3UW*ld&&@Q!TJ!jno02(V6b3O2W*DC(dujkqNgL> zu>#eA%A_I#cBJcE$YGl#r(3&_3%yFQ5VY(hNhZHClw9jqvqCDmP3a}Po^-|N8+r?S zoqC~0hG71Jv{Nu2-qJ}`p@eaT0~pnXBZ5egzHiymm_$r5H)1kQYu9B5URD`u`}amE zfCCxJjCGs>6f1l|nklrl-dnxvW*vOvu4ff$Dy85y*fYzPkTTYTRVE!x*>iyFa!?_5 z6ThUmHMXl*n4P2>PZ3t&i)0;R4lq}*IQB(lpo*3|l+T{k)W{?A%R+dcfEoBFlv>=p zbu?gH*6CMM=#|eeR8-X(Cws~2F9DkA&#zFR$*cwuQT_2#9!r~H7-cPAy%$>_QHe3k zo(k#xOJ|{ONfe+adpm6rLqP$cbsYoalp1d7v62Q_wL6WM!M->uIZv%~Vzno0dsN*)HaS_NcN);G@nGz+)rg{Lo=+VO+B~A{q>Euy~ zjXw*<0oall&PM!1RkqDHGwy8?_hjA5-V^eCgdH1;rI4fcCE~_QcH)OLFLnt(6D`;H zw{9hM)h&Pc^K*aFgRwx{U6xRkMt>n_i0ZNo593Bd9d|hmBP5C>t2{IlqkI8o}vT9sRs3)lS5o^^C<#bHWQM3 zN=V5uK6nya_XmA2m3hN3k!sw(WBKzoFt@D1H8=mdm3}FkBO$WuA`q)ul?v=>0f%Va zfBA9=Ls*yGY(bQBxPJX12W|8bRZeWmd&>8gw7zuZ4XeY8>ZY3o0G&4#bo|ejg~=W6 zxrXVKOOc9&^&Oj$Rjqi>pFC@j^fH!k_X|?7EHG(cWx+oLYtum3(@6a??)oToUR~S4kQVWgSt7 z5Is`L3n0l`!#v-@l!>cX?~9qcXDvFvL5NI*O7M^sWIiShezm_fJRH1#10CQlo)cs0 zz}nGC!@aHZ`!u(%gH!HWM)1I7R(#Ys&>kxM)qGn0Nj+L=kZAu^mzx-7#<_k*^+m88 zzod>A4?8GEBEu%Y;oY0@QEgAe&Mc!O1ry7@Su^q9U2Lz_U?S~3!%_mAz~JR$UekVe zm)|E3@7>uV?YiDF|LY4y9?3Tn-!`6e4C?E7_1}=<2+gIX&PT^(c31FLprV*MIVPp= z`+edavPq|$iGnSK^j4C9!O=(nH#Z@rzG0t`PVVC zSR3f|oWmSdqhS{bl8z}!c(m3Q3e^R&pi||#@J&d$v1O+tw}OI{{VK@MJk9<7mf#Wd zNDb@Lmxf@cq|dp-SG7+1f>6)KnH%?1%3qz^DNe@@z%joWvLZKF863S`mL}i^^I!48 zvN1W=ozKmSv`rKz_=)rQzge}k+nW#5zs?%!oB0P=c|^~wETT|2g9vT%0@=gyiLs#R zCC580(#DAXAuIC1inT8>*MiKljKs2-)3gy<*;8duwr5@Dha!V;>mMUsWZYBT${IPn z0wb2&K7PI*@f&ECjguN|1xd0M|r|j@Z?u z-U8RpGp%(R5f9Bz0|g-UD=Bg?`^EqoyuaRQXG-ihPs0atM|4Y=+SAte8#~ERcJz;XnqAIWx zNT$2`t~79<9!<=H3;L%a@T}%RdI)O(A=vHc0nJOS{a+L0=cFM<%?RtlA^2%&uLBof zaLV<5q|PB7-S`M=x8iKF;!Cl$VAREZ|-zBWytRGDbbQ$0%*tv^kw1-0#%K6G|0?;S!E(u>HiIO3Y85*ilM!FHA+m5sx zSYu(T8Q%~*3sW3GX###ae!3F*`ordR6S+VD&>aA{b3VbDpYW3pZDFam9q4ys;BF|J z$KI{b9eZ};}cnJ8a)D_(>EQ2)|SRcRKwx9NV{0etH|0kfjJ;( z->7{N-$zeLrh!^nd_FIZ4j}6^FPh+;3zp=lj0rXWJ$veKq=KTlKTt?MJRM9GXl?ipRNk=GJ3`=f9nDbLh*Z`V~_%)}V~2tHwFP z3y^YUErogWMa1OYJO%{jAMh7&9KAVb4y@rJh5h;dB6MjK6J=cu4LrKrmJsAsXrpg_ zvWKG70ST}RxVSA|AE7b{V?LAva0sIG?)7PjsOfbxSn@~X-~8(HaSZn=)?Q|a73ZI` ztpJ$@1ImFqyY4HPzFfd*--@g1er zz@Rj~3p+!+S#ev0?0b%23=?q??d%x?l$+D7(!YC@onyPpYC@VZ?U3 zmV5vCwrArUo%T-yyYT3R=bil$7IXU}w(7rw1sYq?5~g?hHJ<%DpXR}Yr`Lo#>6pWt zAy?C{=p*4*y}3}qk>Ym*Rm~b*hOw_|Ns(Sh*dm^kI1p-tAwDQ!7xzLi1ijaJsR7#! zAtWi0wEh&Il>B+O*aeltiZ&wwrlm1aAtC5a3bB-gk$$1W*Ec?f3t_H=y{zDLwGc|g z{y~8dXaiIc>Q+f>b* z`e3`yRPG)Om<}(oJQV!Ss(qfk!^4h?x8*uJXZesc@1?{VGbEjbsXQ)EFDI>VpAmjW z*nAZlXpJWO01W;@_>gu0Q3KS@xRR+4g$^^up2F6cc+yRA%t|GP$3cIOc}~v{#y#(> z(p$@lYNapNj~3n}rsop+qn6RG`a$h%xX(q_CjH;Ia)0Yq*0^4>sETy+Wn4~O94Z$! z(3Eu#9KzeNV)ZMnB zn>IVIP5{0hgybQU2T*`oNCzD70VrAr0o7rSNL5uR8uM{Hu=nGdWHvDn+J=HOMg{{p zaz^6QEz9e#LBRf#Lgp+!PENrB45gedwVw`l^FXdv+18LCN6Gg&?%yhx>LrgxBiL~B z)CF_UOwgTxUR*+{^cXpDEe5HCC zuz3?2(p5(GK``nU)(nAC;s4j3?l5x7qCI^t>844v(u+`B!oQAr8I%7A_xu~0X@%m` zts#>|`^^rC|6hAa*8kJ~uD)n}xxH^IYgDhw`hVIxroOp+MaT)B+rV`Q7lYic7}y|e zfa5CPDXeYvq}bES3@-*WkK&B_T<9YSw1?MN?J(D}s^b{Nh8ioqEcFbxK=sf5J8PkS z!}ZZmRlqcU3Ea-U_wF{MRV8U;^L%dhxe8CMmei~BCo8OL) zkFKyd%-XdR|J5u$PoW}|$=bHe@LX(RapH$z z(}^j955_R#Qy@-{3e%B?iwUW%xi*lJNfXCka%G#oByr_>ah|F8P79#y}Xe~LZ;k4;O?a>-q9{=e!! zclv+oTU*q>BD-ZS%QoO;rBvw10F$@r_h=!=6n$`S!2NwjIg zNJr`6eRbv>ofzH>5^v|l!2oFYhG!xXXBcLtc3<_eB?Gh$Yuw@p$dUcnjlebW2}0~K z{OFj!e~`@-&GfqElxFWj6Ybh_jBw{^gotLCC`1$n^>#nYZQv6Na|`B~`c zXQB7$Cfn)ZkregN5r5HgNI|HhRhywQ0bj)-j}S%o=QH;eK+X9ZGVFo}yGU;?zMQ7A zrJc5<&ANIu&4=R!(r;5`-y8M$o^c9e9%yevjl2_Eeb*5ChDe9{svSR;Va_E7 zzoETEs7M?IEn#@k@KH0Fy-fj_PE|bT?B%?HgnGHJN$AvtW=>sy?NwJ_-FIH+c&uW` zV>|3cR&O1Ll94i*Gj+nRV@nzPe!&PHAblFJ6_^JVA;_se(zS;(7c>AZ2~_oVhkx+D z0bL5vC-V<>MHta+=+c7jaSqt6?0ra|tW}!kyWmNCio z@Joi^OP(+IZ_B)J^+$kDfWa`PPK~6YTL@@&f@S0?bnc&=kwUH-(A_h0D5aTl71$#& z%&vnd`OD4DgvW7Qj7Y3;!YN$Lxxo$YG>(lviT~jV^wV zx#Y(vM&eAWfW)lMIUv*~4_5vs9)?+Gv`N%Dqp9hg4^Umg6oi(uNYZ6?W%y%N^IJ38 zje>PA)vVPcO6CfT$XRR1(5DlPopbBJQpcpx6>%B3bI0(CCdeI%-EPSr zZZQZv;0DJ)KjJw>z|Um-{<#V-ViA3M4WrL3JBq?%l~)O;60qg!PM99*9?IxP;346m z4sOd=+k9OS={GN0N#a&?+pzog06QSuUNL!)s2X}v{Pu@!=;WXYTZFS;47|)PjY?cS z&yw>3!SjL8#M@ASP-NTy-GYTiI>5?XJtF9V&c_P4Ia8>V8&pKK^W;R=*4IDw#PDBW zxj7Q>x#FtEiEh2Y_7;a)aH-(-?C>SOZHUM+1geB~3<~>H6HEXesW74L(>`AF^v|`z&=+TZ~B#DLcUjmk7>>3bjqaCeqqR7$#f#|9WCbM z&iA6OX%$ElYx>3AKa*o=4p$)&yb(2Bh>}7%$wE6$XF{$YV2-kY`fhgh^?_AY+Rqvh zyM8GHcD>*Al?`}NA{|w$0W6`#s8c~kO4y)+fTqzL2=lhl2lk&-KRLgFjNv6sQeZFX zAxs$}w88gu_jP8h<1`sxKQW0ui4$9{e@AR~!G7Y&@8dnq3wY<4Oy<|#Y0DvU7Sg}2 zqLG>pS7#v0x{t`@O?!){dDEQzSGRO00zQ*tmZH{0J zS9Ps~$uht@zPua$`QWVXjB!;Hsx`fm{`D!9)8+`eIU_?}%6N|_?5A?dr5cRSr0_aZ zS+!Nf69<;Kh8i!h%jc`hU;;zKN;9A&_zP16_s*A0ZuYN!O{PSiI@JEL9?cZO&?ir; z2o462F@&7cANbOs9O!Iqyl>1>isaK8ajtsOs~10nRp&N=kunvC+hn_R-2^Kcpv~^l zc~@fXlx%=Tr`UClWNE?zP0~a|QJDh^6oMsnd-NqZjPN=bJPzK>ibs(HcgclG z@BD-OUR7a44K#MGX|LzSvGR)W2+tYE04qW2rcXc)y#%&Q`;w~eSIWSO^sPf{Tu-Td z4v3!!|J*-8oihu)>Z^%p+BT8})1zwFc!4qMS1m#DNQsnfoI=z4z|sD$nKlVKmTk*S zp9(PhRXcoJ0%Jpb4pwMXZ`uaPVcf>qvQz&C6mC>SUPr_?nc^4Cb1zIRlX=FimIau@ z4Yx&E@1|dZ(NmlsytMQtBG6gBCnXL>xm3002%K#B~5qd4^?>IE@d_!I@ zxdTmQl;Yl5>Iw;+ahS~Yu!ThbGU4F}oTYowbSvP{-ytr?83aTbjR8k-dj*z?;9_uI zBXkS_(otdM9)AhrisFB_WP;Fp9p7vTYosj)24Nxv0P&IY>8 z=Iu7n9~hKvm-<j*Dah zK3NdP>MumQ3NGy<<;C24E<`0lIuU!F7KbW7(K!-GoNDuCp>WCYvNdAq>G8|*uR?`^ zUO~0GyN0Qi@v_t#gL`Dt`3r)i=@669RZ=S$9WySAV0(B;QBJ+*m!qkjlzjq?T#Y#ZjgO&D`cygXj__rSEz;_0Vq&&I4Nms?Sd9W+|h z*TYCy-p-t{I8R9iO0o`aJ{nbq8pMmC&e@TsXM}b=X$2qR{O*?7p5 z2D6Ju;Dow3LNj8MJajFnNIneaL$;#Y7~Mf9fVa}>(~{BH@@@PAvvvL&7PRjNY*3;) zL>Os7$O8b*6v&hs{2p^*WxOXvnR&E+X+L-)lhPohXxos?aoaQ*-&EDGq-#4tfzncJ zeLbqO7PK^sbda%({Br&9`UKAhpJxgB8;ST9VVQ74xbyu!qn5EjtI$d#7d3IDMAIUW z7iJ#Q40_X`?9lS~=M~$0HGARdR1ku`^4#}A^a-r{F9$Rc$iqC&A^Jsj$vR0Sm5l4M zEn0P1XCrS9jKllOeF*`1a@c=8C!Z_{Cn>@;;e>D*Ha^_1v~3_DXjiH4)y4`s zG4m5@dW-2D%4--6l`&58uGPN|+5GOlM#j869rM%WzMHaS(t4KfyB>|;x?*Ha7N9R_ zP{t04%h-iZ4)KQ9FD#afd}ev=e8tf>w5bsmY&?EWlC(K1`pIzVEfs9lB?sl~Me2Uj zr4?Q_^-?Wsu&y5stAd{#-eUB*wIO0MI;k!avC@$xr_gY79b=&kHuE}7#4i361K zD=c|7sSVLwF>`-+RaN#6Lr2I# zC75R>hH?;lcZwEt0?54cBv-R#6Z+LG(0lD8BVIFbn77wsJSA&jc@%nQ5c5g6|1`6+ zrM$Ah#?BfSZ}rLwOW6Vub=5_9zR$}l%Y7d~wMpDq28oDds>)qMm`m3@6(eTC89^8C z?7u>Y|0!$LpOw}L*?y4>pT>z6L}1vwHE#xTwlGqDyL=w@R^LX_vKM>B88=dP7=;}Jxg!}L%(>h^&AopdPAY<=Uh$Bv$Wqop_g z+U9i%p;Iq8nJ(*E!nP9WDdzJD*KMQrNN-#;MON&pyrlHub_v~M;6+>WG$X>A4_DTl z8H7CEl(YM`W`q2ux0Tx!SLA#gH`7^>T&V-c&Cx5;E7*3il1NUql`5?oXV# z`BUh`ubVt}oO0V=F;yd{-a+X8TJ+3}6`DZWLOjInxKNPfRDI}0;hLl6$&V%Nij)`E;HR#_1AsM8lkzh z$tZF~*Kwly9ltug$gDESK?|@2TexL)RiYod!*5tRCCit;yAd?BSM&HGT=*Wh5EFQj z{-yC6Z2J6n>>}9YHaZqjxQb7?9r9#09DH}8%Rjcx=vwy8mrHlrpUXsw#&k+=_B0+8 z#?etdDTiNU;>xdQy1cvP3_F+l(t2_&9uOgg8b=35haXMM9(f`Jm(N@4&%)!QPe$;^ z=qjJaf(`RyH(f7XCxqaGm{q&dJ<>b?41s2ZrqWeY{~=nEc?l@{i$*vABsu01uXuLP z%2@k@K-Jb2s@uIl;Iuso>Mw=`(}(~<4AR#niUB&lCW1Ap4KP*BAL)%^MMl5}>GbsQ zk9lH~+!kt99)o~vGR0S*eOZXPMn8oS^N&Xs^$6tkINw}l&A@&WI^D;XrLAb>NJP?jdL3IVM0wznXn9q#80CpI*m6H=ENF^BK z*7PR6@iKExzK89a9u&ttyP_$NaScgqen$6@5H|55;D6B{X`kyIyMK~)lf3_S-Vvzb ztY}a4rP*&4AeFTx6*oT9EE%S5=h||h=Y9xz6%1`m9{1|t^9K`C25-XL^?ja8RdKJk z`tm=mKTC7Vk?m;<%>DW2_sUnZzk55{e?v(FQR@zakdC{V`yF+%IQR-|MJK)fVbG0_ zYobCo-+z|PFsyt~d}rYk_1cR%bNm}{PIEC$zG|8EE-hClh84s($-pCn>wM~-cz!JQ zxG28&M8JaRHw3c&_V~_=tG>B#$mf6jj*bel!C}XZ?(Zm=x}hQ*?jyN+D<1RIMNkHX zjqgAz-FS+tE=BMiFY6P(Nx=Mphxg&P-}E{?E&p)XZy@FabE~tVHYLE8f)4ip_tAI} zm$)l*dt%Iam?MXflpAO7U0lR^j469=hkkM_)<7B~VS>1rm3P zX&3w*2gc`nKi-1RwVmWF0vqxw)m{_X8-m9}d=?Uj=cm2wKTL;m1}|<1kyt~EXa3^a z0&Zr_g!nHBeWH59Ab1K^W~(hLj+6K@c0d9fb3)98p1K#=3xys$F@E6}H203jLOFE; z4NnJ}xaZvi$`$92A{GEj(HweAW(5=C7i`GE%Ma2+m-&gL&&~P(=IwC~nfG5*QI(Oc z_c?bIng^~~b2giZfelK2V#U_I-u5CR#G6_#(wKb4{emveXf7grZsylaMC0$o-hPeW zJbqW$s3RpUE0HoiOzldsN^0^uX@AynVddgEeICcb6!XvfplO1PeUlsh@M*VMLNjBZ zOe=p_)B#iuu6wYfL(or$3GA>Qw|fVH$*%xAAKcchI`ni06!;ps$OBez=r9P6BTsP) z+ACRS85SdF8-M`-h9cT_5CMpnovQLiB$Q=DbL=^vHlq>?w!qgZdtP+ia4aNW=ugKI@h~8!*Aw3v==SVhJ^(bByJMEC zXa35l9imHUyG{GJZghYPnSuf_Vlm%44CQq*(UMpoG17y~5CO2zxw=XVj!d+bf4w%X z)jlcx%0FD2v89Hfj>j;lO?rx#Bl|gMtgIX)8~)cPAwc3LXYAiA4cr4%N0MnK5Mz#A z%xlU0eU;}Kw3U0b*fqb~elNH|K{Lj<#9NZL;IB-#pKSQax7>Qi%Leo==d%V{{x1p1{6NvyI>3gaUuNJqUm(6X-N9{f_cmkJ_M2s%!%d-I&|4}ARxb4 z_N~V_f-N69_|Cy;g8$A>0xKY< zmVUuTSAr=ry+gDLmX@p+g72DIf91TQQG`VvT7{C7V@<}*71=m3>aL=q2@iag&hq* zvqOuQx#C&kJPjOWTS)Dou_bId!vsB#+2`lZp$JrF6A1Q-B9}GBhNP;!{s+NyX*eax z*dYQX4g=DiT07!bOrzRQCgqUHCpu5~J2<3`Xc*=ftQ|ru-hVON@#j5Q1i*3UerGz` z-`l$rOvwC3Y09bZqx`F`ek`g9-qDt8N+)HS)XCI?0J+__f;Mz?U%D}+c(O}6h*Oz9P5;MoD2A0#>Du#6GvjxWZBLQT67{p@DH_)E|h{|2ULpM^t=&(61&h{`h zqZ+7t@h6ZW zz-H~%)x4_!8U_MyzS=EJVVc7CNy5J5N;KeAJN{Uv`57h#9vIx!H|f4=2E&Vw*52!^ zi7x2`f8V+*%{cnH_Lsn8XHF7y8Q(r`FkW`(`R%8QshE%M55@Q2;%&b(!Ax3x75mud z;6T5h|GPFd``h>-L@JH84Rnq zk%0m1s#TtLaABaas|5)XO@UhMSlNkWSZ4*i8kTAr01)xVzR(A(kfC_Xo|{5RL8u4- z8W1bTwlk#uRkrA%1UOMRC?N=K>t+dYev_126_7ZNrvyzq&ih(mE0#KdpHUDdERrLv zc!(mFFg1hr!cX&bVRuad0f_Mdd{$!H@pz`7SV)E7jH!gF$uXrdzly`DSZ^m_X+M=uM%K=H{?7iHndag73$@0*U?gHtgMxg9nxbB6 zYKB-R(??Prqio*7-9=5z?YhKkKzvbD%JnIkWU%X#XIKdxYs1c~jTj{ij-pbEe$DK> zb`Tk7d-*&}TDn0}^adsg=zM8%DP5z=j)#21>7MvAyg%VW#Iw1WgV%%{5zkW=+xmIH z(Jm>+m3Zr`-dmS1Jl6RBc?tCQEl~`OQE0oz&|B)0JUTC}By48MU(x~IqOOFV(u5*G z_hx}Z9uDir^?x~^r!7`-J^ac6PP5;5t9|fRmr7h?J{U2SSQ!GEkstGE@zp<;)=VL; zPRgf5r-C{{55F$uxJI*KDw-y(6NjgGhhS&# zYvix%mS1&^(6ipsa;=N#HC%!;%`M%8uDIJ=^y(xrjzk?9f3yDag*TgjU{*R;XhYfP z7SZKVS%!v9FFKC~bm6u+)-?f-zZPQp<{*>jQg_|`M#@c3xspaadP9X&>xhsp8h4dM-6FFpQ5?ZF>%{uA3*kYo75Y!GMt~`3|pZ4*RVIxdoSwZ%w4*Cvm?R0d?an*gBx#SLqDy|G96ga%D6dZS;;EQ{9!|tJotTEtI`#BkBmsV zd{n+F_#imf5N;XnOyA8aXO3NZ(98Gz#>=7}3}_Ur(~)4!^Lbh(dk}h14HK};>@O<9KjU7iAFeq+36npft>&jT zFsAM=>_A4_==$G)r5M2PWUY#nT0z(&c^2z5srT2+Vpt4zatNJt6f}l};;iY8&h8>$RRi*?+jcf?i4}~Mu zkFQy{8Dic2bzks>S%okdA$XcnMVrIG#v(ep`@8N@@HV|&k{=*_F=}zY_6xa}Teyd( z(5iQXw99hWA;BDvF5@PTefr9JPBwo=tJs?7$2k$4)syLxM66{dZw*e9cs_nEljpow zpThrY6o2=Ayv5Jdy)3>Hj5KW&BDclNt5q! zyLI8ZP})Q5oq$H%b(x=#2b*gO(X5-Ht*pX*FOK~zbb4(0KulDdOpCZ{#!UiES)S0Z zLwlUMo*iQujtmyo%d%|@Tr6#Hy=YnwE(gip#>XOM?L#t6LHf}_gg{^dA?8d*9UqiN zsAC<^m9o`i!A5~Bxa~Qtenrvdd#eQ`v?(rtnFF=sfd8>=IHFT)7bRmjBf`y0W>}7W z2e_bGB_9oMGF)EN_*J^w)mnucPa3S)Ng9DFJH3r$bjqY%qxwM2>NK2Y`$;yNUOulk zm^5H=GStp`oHa+2oR)BDWiol2-Qp6P0$>r7fV=(c*nPO)F$< z9@KsP5OeW}!8Ah2#LituAPALJ?}?Q5j5H1oE&YPPw={N~`d|rY zl5Uta(^MLutkK-D_YK3k+41wa1Ht!Muw3qK%15Li$oK^RmmxoPIFXr zTBjPeAx!)!B;!_G6a;nOpGxi*uCpeCO!xM&Oh4Ox)m~cEY2F?mF@_q7vQj~ukw3hk zC?+~zf#1M43eD_2M|x($HpnSvlkX_Fey>BsOrSxZNg1r8?J?i2*Mbh zq=ETvvZHewz-G%dG!P88nPiquhM6>Q)gl=q0AP9!fPC*A2BW0+@+ouzf|FMfzy4aM z2&DJ`GpINqM`L}|Z{2zY>~P1kt*Ckb>#6ou*~DmKWtKms3Q@(XL<~ znm+BpkdyI0mHPQtiZ=%|zzF+#SE8JsZ`YqOzWaaY11b!~be2!$Vyypz zwvMwZmg)q!0GLExL(B+Y-7B2@!_rYE_A;0&wdb;7S1pJ3So2M4Qed*=0QS_n7MIAs=kn zwK7A*jii(!#D9`A{j@paL60^oZ2qO3k)mgLw#^g2>mw2#D1XnME6UA#Fwj1_ZZogYJzqA3TMip*^HwD9pbV`~ z-V5v7XILywdRmfLdtSw5Bvw1Vk8HkgrY8PeqT8)moXC}&re=P3-g{?Z#(?be2WNJg z3v&B!-hFAr+X=7NzCTV{o{hXGwYO*Nqx~yS2dm^$lw|H+)qm?ZY%3&`Y__&kHXPpzOA3k$;c1?buK?FtFS-u#a$VXAChAeRa`phD*CyIo(lpa*lMRw#=)R zjE@YK@XzN3B@l>+-Fz;c*O{&+0smtbnbc*5`ZS=`L+h*;(0%()x+;Wa#b^X=7>*8B= zKkZ4($P0Quwya<$-p$2ZZu{m0GttrCPiV5eb=lQ|zvtj<2goND|G}OT{3xkEHFRXq z&DQJh682=(yLLbat;GL{@Ql8feeDRIYrC=k+M|x^%@a+JQ;TN3n=2<|Dnqqw?NCRX zx?jK(bgKvA>}(;E)BK*U>F^p2Bnx z0^&A`!B<2e5{2qe0Yr>l@_dAa(Ptn;g~P^paDGoayAwFgBa-N5cTWwzDdS;ry{(_C zE^t=s8;q{a`Qc(KY~QK(b>@$Uy^5<(oUM)f>cPWpL6B2FlxKh%v(bzbiav5&iq71OO|ZkrBehxW1l#})wIfUjWx5@01mPy-zQ z+IkA5Bc?Jgnj{s!y5MQ*9njtiFsv)cVahq@95u!?u#l~ocY*6}^#A1@9-btfaw6*K zvpj~pPx;IgCGvdc#QX5gGg*B{S|+&5@>AyRR61m>IJZ{3-lAg zA8GO#_^W<8kd?j)lh&7E^vtfV;3u8oh$oye1rS|qN>@)jf}5;e?uP2zVE(|>UV=dg z7Bd({y!wW`(M)c|NsBwprRm*wQ>e*;ZQz zEo-&aQnS+X0E$cVgr%#tm9lKBz2@@N!IcS$rX~u7rKJXmrKJW63d-U6;r;zS{{epB z`FLI)_xtU3yWRxFenSY`SaRHG?ETYxG_r5~-Fhg?D!YQo*>a$_h*<*0Qs_LxCZ%3e z5>S!85n;FO;}E{;X>CP&0M8GP_0wzfq3eAJ z5i|a75 z5H_ll@6K1q@A_#S5}fCQQ5|P-w#m3GKQHgOZoc9WEw*Rpk{I{md> z$Fk?6byXAJFC>3|exec^M&7wcCqK}uJPxP7X```7+0ITryMfcCq4vurN;?ik13x*tvaJ%{!+?TnN&KaT81hc8Djom-p5 z|6MyDV6Lk6 zYpwA=p;K+~)FvuJfcF0n-iR?bHF83)k2gE6DV&A;*una4Cv%R(+ zhn7}E`@29h5U&cKuuwjjbD@V?uaCZ=Z+IL$p(P*92|e_TR9YHoeW{V!P;Sq=Y(Kv* zZl;$oK0sT-+DIvBS2c0}N^u2>vb_6faqIos^QNxPvpMp_`SU^9x|hf1jRWpEU%;&U z=6`e(i=+d7m9B$#G{>@^RG(`qV0%RoW;5)zFXSOxRQLI1;8M@{ zCr#a_aGzcB-D8_3y(L=B;=RG6H2Gb#On!CvReqoedQfmC16Nw#+A94$`@b+-J5??I zg%Q&ft>!yTC@Bp~WYvsppIlFTg?`*u%bXttG0=v%I#OpgBq!^${NQ)TzF?+mlt;~V zWCfAg)>EkvlL^dW$u>`sU+}uP-Bq55fxJ?96U4rS!7RN~Jt%R|ddSYsB7!){-2!>gfou&R*YGyminNAm6()JVx*D3W# zBi_{zVS>x)&##DWX55C)zXWXuC^Q?+hyD@_+-5sq4hF#)UxfZ@cn%0LU=)F?@5cMsH&0)x%exh(5!##_p?Pq<=> zDE8~WyaEB|LA7vTfbPjgO54ut+81Cz&{qEJ`BFg&m7z*guGM$PE=fWdh%>~5-`2(M zv1S&tXD8l1A!4E#tdj#((&>#et!ktbw@{dSL3Fs36DC8w{eFNI>;%oL+{tQM+;#H4 z{RS-@PpcAs`{Rwx`hW2U0#U+_P^Rg{njXdQc|67Z_5$Yewqpqu$3_?(Rg6bth^J1J zEX&l2M$KWRyHq%&;Z(h5?`Z zG(q|S`}W*bbJO1h;kwfnTKT=A>t1a*FY@e2=3+6`T?H0 zsSJ^6ki%&I?5Qf`?8?~mDRYfPBfC|0GyFN^Ku4Z_x}0!Z68f}zzH9W*Yo_vqVV5Y(etL)fHt2v)jX}+7!KU>^=C!cA z(z{zbS)0Eh^2-2zSI;`~hJ=N@*hd+0;Ug0RyZqGZ$#d!rx8`#SVT4UvCDku|ka8uG zU45SqnNB!M>(py*>$p`U^usQ$Hahmu`pUtw1y-t7@)*8s_4nA3g5(4-#2KyU{0<=P}Mt& z6$UwLmVHEz{1CJMFJPPBH?ITE``JD!x|ZylR(A^<$AA4#)$?q&#IogA>0K>f0~4fI z(k5z(C)mKxkHk+?b$3FTm9!%UiVe}mof_`OJw||zbV(pcOWB#*8Ujty5eABAd>FvA zN2zV#4NxxGM}rD+7{~AdTsdwWrWW3|G(UMETOwdAo!s&Z?QpoSg3G7C%HfynA?|kn zC^=Im2S%BPCCoz>(h~s;>kW#gGg0XwASTmttT1MhbDjJ^39(P%I^R>SzFE z)|o)2+Qk}<44n@I{yH6FL?q7fN}>ApO-Zb+0mVr%__xbK(gaE0vjXstU5`P}+C#au zHAy7L&yTK`n-=45^!GqnQNA~#y!PAq`yKk9+cU(KuQ<1r+2 zyNfqbYKvEk3scfaP_tWskkz~eEi9{P#gth=oumUB*hCxv=z0pWWAhG&|G1Nmz5-zh zS&19|g8XbPWX4arZxk$#fE~Jz$m`b6Wr5bB%Qo(-Y)nT{tG4|5^sKIvgMQ;%8R#0j zzMS(IvdsI!|2t216v9o{x1Z2_m4ARKk=mcRx_!{!!;xr+Wo&Ei3$7Q=~5FgDQHl)(K<2q4F~x99UGP6~b>H_=$ui>BB#WDMy%>B1y% z7mCJhw8b^V{tVz;U0YjqzWQ0>g-Rz!>8|mlH4>5B7=sIXDT> z4L%Px8JUA(4ev&janjIF1fPYDNCw4iyc?HVLJi`znnZ#cx)Lh^KhivO+PU-R+Exw- zm(kiF>Bk@#f@+zy;R!y-Oqd3TX^N*=9iR~fj`uz?kG2d_4IoOF8PmuxF?H$l@XZ09 z_p9p#`HBt&Qjhe#=fai^7`JCNdoD0;iebBrEcw~A`7b+*8OM?b_w*5mr|@Uq7~C4@ zfvL9=XmzEuh=q4TxW8@pu~%51Leo%KS1?@RW?r)Gzn)SLu~Bi559QG-H%_B5-kagX zv(B?BwnGsB5Pr%IT0oD$RTif1xkvSVC}#yEJYAp8JTsrEKJ=!4*$rKHNcQgSqXR#= zt)>_+25gxA^@C04d`ks+w{Cxixxp2CdBO-LRPWHB?E7@hBHb5L^`}KCJ85>gDJz=# zX%Q;XeR|Jh7E-A63;|Cd#I3^g8cZC^iR#8Jlc&x$jd3VHaoImAU(?l_HGPReV7AaQ zf$BRf!rf9`mfL{A@Pw_@sdKbA5WJHtgHdLe^gOx!{L}x_mdOyoAehyj4d$2(ob<3x zZlCe|%${m6<|#a6cKD~c4)j1@LB}tY`~L(@44Pabzso4w=sW={S4M+xtQY=pdYQ=b z>tHDPnmY>QxsOHj?p3rAQtDomre$zG3hm?YZ$Q!8pB(R`YTt$ht)Z{ZXi6WM+*4T- zZ@A?E)+aZXBn77q-hu;pUk|?dL0ZHZC_bvn+aM`#?kPjy@(>uiEDpKH9bB+HKje(QXM!!MwKBU zMB%z!XMUBx9Obf5P0pJ1z@&CpK@z|@11E*nPa$=6C9DhLsM7Ax4AwM}qFSuuI;jx9fx0SZMa#_q z#WuLZaozQ(`(s%8l>@w&nQPq3u5wiQj$cgroot8@zJGVAtZo}Tm6e}Z=#g|P2TLJ;_mv)Z5q)K8oam&#|ET#` zSpHdGmty;k?H9hV>2Qx8FIGkS-zPhWn@GDvti7>Lm#t!w_T3$~=d7lcH%3`pu=P8m z%cl=5UlI&9%;TPT*uggjzvEf2-La9e;(sP_@bnkA{ai`0APh{`|F)M0_*YB(oF#=kTQhxoQ1Aki)z1%fUdXX z8c{AB6!f`!pb~FWRpqvf zTX#QVSLIrqaL64fg)e^+I%!=Lyp+RR(~pb8bA!jNxfOa?iK-f}upzGR{@i51x^=+Z zNxkhT9_>jT*V1r_wmAhd(^mzdekax%e3*9_w#}ls?w`u%KLL(PsqkhRlR4T3o|9`+ zX9RLx!2Y2*WF77YdbQwfqEMq6AG7}zZkm%;{0m}ZP^Nrw4=sD=k@ttZx9HEy{=I|F z$dtajayn4`$uDt(PB8%t{g4ki`<|kN?TL`0oNAaxvV9T5b0+A&RAAKjN2I}#H11O-xJ z*O|}uO~LUu-R(h5P}3aWF~xN!cb+kuXfb3B0Rgq4KIqd+OTEQUo;+#VVZ5}yI&b@i z&(P#y%N?l;Gz{seygmg@pbg(H0=PcvsF1ET##D#!+AmbK+bj?}aZ z|0{)6v$mxivdLKZrVcE%Kq5h z(s6mgU$lMch(HQ)H-a?~F)`^`G5+BhM>gKK4zmknC3RgMap{xHYfSE|#9>)vm1xzw zbFyu)gJ73Bv2N>EbZEWf;Bx7Iy8~*~yDQ-o5ODTKD0PXF_B4DWJa{g>O2sn|Ar0!5cC59h|5tImZT}zmMEyfMw zJeW2Lj?7^bOqLf3^DSn7XS0(4q}-aPdrJoY-ua{MRjkd|mJbPSF8e&u{3K|KA=8)h zq8Bhct^PwlJ7Z!IWV_jc`YNj6<(Ronr7}6|Qb&d<@h_|huhQ9H9tKe2cWv#6umaRF z?{u(7G@=sB+Jpodl@z3jz~08T3^f?Pm*Pdt#j40(-g!=(t$m8puB@oA1GfmdWBK>D z7@BAtGC9Z)YUBPTS?F8NUpC&dz^Grg$WXY2mUPYb3^wTDFmge+5kLUQ(2;)3*0pIH zpu#cQvhFhJ#C4FP#u1PALAXv9k@@cuk(}MK0E(x*SNcr_@!CsH=6-Az41NhBORya~ z4EV;dF>$SdytWRnat=rl-^6FE^>L|-^1Ue$H@(D5O4Z#OCPF$IGaS${df5j{{=sL96Nb+rH9#I~ z%Iq-ejhIVzO+~ge!_t~d!5TQqc;QC{Eo9{r!IB<o-?~0^!6=tn_G9Y z7`cbQKVN&8w;hg)sVOTojz2C^rg3_0S- zHW{MA!GRW1Lr>5ncH2nf6G1`E?N>1tf~h=&p;v0vs*@Z%0$K_q!(X#Wi!mRyin)ln z^Ak^qC4v3oeA71-7`N&Nej=n{nu(+PiSy}r_pNP6VJw;PDtb1CA>s)wtyDruYyr{J zsm2SB2f(Ig^tjsyFs-r8p$)$f^4@Uh&*}G_-74;G2 zmyGT3bcMQ{T0%p0TtBa&(nigohWrORg;GKa$kukIk|kd(5e$V^PQywf@oE%6M1&vQ z?TE+0iF%Dha+s}}b3_?Mvuev|AE0;BF<|fWHR}IsEZ&sUi|3$#l6nRJ1BB#X&upe0 zBF%aSW}9eYa2711R?kCFC>H4D!El*WIsQ9gAkyBV#f^Z>Pgq8ja4xy!V#@j<9OT$Y zpLkrz_k{LZfMiG#hy(U!jbHfCMfA>=>eygoV!o2lzaT^jQiRhkOMxn(Y& zv@kR;1tsQ2{e^mhH7KRx-2$ZmwGcI_B089#d>!#&hHQX2aALP1sp5{uRaSzUYH@mXK7!WiaY}x2e!*ouL{vSUV6pRW~ZT;dv!(Ehhf7TPR zk(Oomuo}%6z|hCZ5Y@}4>ilWJOU$#)eq8sUe!L$_h{B^Dg~c2@Orxo`IX?xQR^PXo zFcz$hkYMO>r)yqdYD_lup1u96{0zE?K8%ne-<~4MGI2)OG_A~GY?>&*ylYQf67lws zV4$kQn3{uqMyRI=Z)hED%9oY-(#AFRIH*?$gl7%KcS*AX3s+WT!S&?0O0IQwFgW+@$ttFAcXuOiC$n=JW;}Xi2-O!K+Qv3 zIO5p|uZlFT^Sa3CaOt0na$zg?y$yio;fV38pA*Ac+9F!XMp8{jh}t}6q9$mBNe@*k~~xs5l!~Yg#lD3fWWlg zq}9blsOns zjn*XVv0Dx@6Al=;30jRcrUrEcg^PHVLMZ7gWrA)WdNdOan0U3nX|M&(E7lrD*j+ld zq)wml6U%C7)v0p zvO(}*w!CElqjq6~2Od!NQ_P3h?qQ61-d%bn(_ONw2$JQ%6lbUT7dYH^XjRdiPWbh6> z1MBC004Znt-FVyoIIPJu4P;MAKDRPR!3Vi_PJKwuyPU+uhBU}y2c(04ou%F?O@4r4 zw_aaDH$WC%C6!g$cn-TS)&BvmjH;e~F`RuAy;nsop8R||>=SC6mF?gfr0K|i{SJ#R zuov?0R}V%mk8^VF8kI?xGr5BFtivRD+U${UGz`D+UiOdaduQdW^3IB(r|1`Je5JDv zcIUA>h%=vmC(D%YNCO=_?7--$i+b?N>Fske(J7X9NO=#+6T&aS59XJ8znPe~Py(c)mVM9Sg#|(UMWMu?_47gE+rS6s ziBbd9C~xfT>0I6+ul{T{ z2Nn4wD*HuLe+PEM=}SyiJN)&h0pYrJs5NnCS6u))@0AvX zPfch4j|)?T%SdPTbYQ056h+-mNEy$=8{Qfg{RIOrnInYk)udxiu=8Gp(OxTPsN}xn zyz^!J80JA+2g=T4d!MbTNj1w)m*v-PafmWI9wJOvux<_5PY5qMFe&}rhSHUJZ0KqZl2cp`weSVcuB+D`WB+IoaN z0VgmC*pXbCL5=q|SUM$Ou${0_syVz7h~zF4hN1TF-_jAPS+-11QyPWFP$57h+hE3( zc1R0x6e)PwF=_<+@1nq`#_cz74x)(kf-d|j<2djoOSYZsXTW+0b~hoNwW81zvD*Q> zn;JRbB(}a#$h1&X5I6>i0lHag1RCUTa#X2J}YxG!OIMhKk<9#}b63+HTCT41?h4u^#)-Hxc!N6A^ z=}qm$Vn#(0L9<|`7%|hQ5;KvKRL;Qat#~+!ogQ~vtX6Z>%WS^*nGc?w?>`pdgV)t^ zrBIQOWkqO(STVDg#B@{RljeGp_OdzJn1pSQNIhvSM&#o#CKw9h)P)Y9Ea>5GBbHIl zp{jE%-V~G4H@d7hF@}XF#4e73#m>W4N!#wmJRXe+7@Pn;{53)V_Z=fIDba&;syI zU6~9%do2tgsy<=r^T|Li9rLY|5xKi@c?<+#?jpa&8UU;KKbHQ$aByU7%i)gS2g5PU zGRNEul@=o~i$ko7xB1m1{R3r}7fHr`@B^Yh9J&Hue&zhDX5aw?cz7*r;_Gu=IL?`O zbLoyzQLX16Ih++%We-&8zR9a!zTv76zNS35dQqC$Vuv9B`Gn%+iTMOgRHpJ^&m!+Z zjYK~afLI<96y@3x2vg9}zPdGfz8QKbP}gt7W@`7h9k{Ulp!Q41Rn{DC+UNs(wjJK> zrz{K0X@NTw9fy~(DJ3Cec|LdaGl%nFj9V;0Rc4K?XHam*AC8l^NgDu!Vjqd`{L@wC z85Y0)fy6nupH8a2x;_)*99;!>lZGDSfUEO7uYFojt|ehO`kC8A&MqV+wux{obP=-m zDDQycVD|C{no8Go9thy?@4IxI@-(C)jfcVZPuMtf!`zEvcGV+n<*Amo-R!%P`)^H3mk->4p7Ku?g4Bt;`xpOT<(S z?dKJ;nnfRNj=!gEY23a!c8 zky_GS+e-4{klu%2l}om;tHG9JJY&gLXE+MGf(h8qK}P6h1%}w~5Q<=vBF_g~Gzrjk z&M?EwH_+WUNbeE*x5BOb&UftqjG3^A&sOQo0V0^kjNX!xzS#xN8zq{l!AS|q{9hdI zeRZFpzxLD;<~T+$I|tf}V^GAJWifGLA)O_tZ!&m(dEa(^bJIyl&lA}YGB_S1inC>^ z>L$Wq8oyK;Tb4aUq^l4Numr5{DVKn<=>a06w{fD0*apB9cnL-VZx=ep+vH$f(*f{& zn3av25M5_do;mQo>QQ@``jBqoJ(A7LtKCd9{059mQT_@7QyF331e(|_(D}66eH~lq z1vI1W0qNYblB;qx9nuV|R!z&b8P#Q=dX_$@vj+W%mrk>)f~Oy;@3j6taggu8^zg7X3GIH3L`XnUubiei3o2G{gH+Mf=tDs;j6l1n$la ztMIGZ@KM9IrO@_-yGqX2{TDH}?Dh?NY0(!SsXjlNhZtV93QpX|KBcR3TJ?YAZ<=4S zm52LO7YP!1t63v^`>v)vKu-G!I$Uj^&II3nhhXKy$1;iJ&0=G-A8!ZPP5T zY^|v2Z{IBtdzEO3G(cd2{pai0<|OK}WU}^AFj`A;_PR&|(D#<)%PO zTwz=wtOqX6#kUZ7(QVdhuA?y8vk>5_>&>Hj?&CVL zUoUJ2Pp_b>Jw!s;l0*<+t#DDm(m4*1ZHjLq5!G}_-%VXHRyHQ$dvOmTwe_}ezg}RW z{1Vy6?0f};(%BK!BQ^RlhVo7<#*Lj?FqvAUFS2(@Vg5o6dngaDgtL9rR+IP-pGG2c z9m|9m#(n=>-6(gXxjkN`@zs2VpfT|W%O6cnuQRx~9FdP2I$^Ryt62%g@~0==V{Av% z6y@KzKZj3DZSF`-^`D~nRR0=B7wTEl*mjhJ%A|v8BC%XCF+1A6ICsI{T)d_Au@T|z zACq&V2}AXBWBp^#Yr|7TBG|YTF4hBT%;wr!n9xlU`hXG$?auHs>82dKj_(a9-ByurN4@fbP}x@%OOKGuJ(_e8-+*!HTTK>PN(cXLRvXZ*6*Cw7NR3arGTPKzUG zVVR1-o=uqNUS*fZ95WF6?FO$c(sVnt+Q(~AiV{UT!6ZI^sAwx>Y704jP@U{HfguuU~3%YXgTSulX0U9U*z8u`E-#<4=&cV#Q9unqhsR+ z4!^~({_c_V=yJ^Dy2zimFoa!eZFRRy3l5{^&;o{q8-qDiS! zCxq_vbR4~akefE**__e${!Ifl8Q??J+jCvJ8KZdt<<`7|**=HCqsR@Mq}naCzFkLb zsj_G<&V&POvGNx?{u4?^ZmIS!aZdS*EJBf&JL?gL%epefV6|2L8diqwli!id&&gC` zHRP^Op?%>cbgOS(p;EBDAs*a={F-;sDys`V{>)a#~^IXZ_iGI ziiB{YIAB=p{>Zl}dRqxT1HEC_ly{oO$|RzpZ0yzbl8hLkgCqUh#+2>-v1G(@oBo9+ zf?#bjx#UdRc<7_Kme~?)z_8ICE7A04$|ME|6=u*=t;ldF2UbG%R?39-2*oWJw_KQr zhJC@b*&W9o2KSoCtpcdwB-{_eq?%`zo-zSMgsA&mEMC~|ITXaGAP?{Y;cs%8>g(f6 zW-K^`;c$`dG0b>~1`72N3Aru*X+WXvk?Qo{r+5#AMIh_KdTc5R??oGCncolf8>M(cfR(9*VZF@8ux!_M1=fk<7_5J?3!Ue(_SD>o zC~Ey#e72*L#d!_XdsV^K#&tW8F6E5)?U+q82U|gX=~z-~Jj#hjPK^f##|+r3E26v9 z=W`w)wcVRV#k~c2^<1m?nHRIjaFlu-bR6#P1Y_Z6nBR`aV~hyf2O78THrPjBX0)T{ zR5MB9CFn!g@wt67KTrA?Oe0@ZKHQ0pQ>TIiFcC?QVEZBvj!nYQ|EO`5YlV!Tp>Yg- zYFT+TLre9gu(LF?n5=JnCvX4vi~N8>Mw#@rm=W!HvIjE@l%RxI@gHD#-ZWV!1Er-D zqY;ma`yPY2A^M1QfnT>r&|bW|#4@dW3Kv2yVdNI~?x zvvvuwu+Q&U3Mu};pHI?zi=1X_?Bt5DlKq^d8g%XVw`Qrbcg*A$Y*H8S>Rkh65 z?8jlgqt`jYdhZ)A&2goavL~WD@;tU>nM$L$_RZ^(1*GzJ;iW@h)zdk0Gm+%jD_~SV zOAqc00ZMa$NyDl2iv*$kPJZt6y_o6x6Q^<*s`vp12@e`>>-c_YbH2))%;G2K7XBJ+ z9T^4VZf^nq@hXqH4KkQJC+SVu(TeEC#`m-e$Iam-t#^HGuth#iKap4U3%<*|XX<+oH8XR03a?`h18XoSnIqMSfduK;*Jeoa^1B_zUqnhd;7QmhWR60osCAryFYW z!v6&B60%+2ty?jo*5W@C?y&AI_0}~_dYNLJr|ep5pw5mgz5EAT+F?%0A6^Dwt)^>z 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

go;*b7i5#wcIDq2%sT|5$X|x?M6{#FMx_M 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

bR3L&zzKCG?{aI<9NzLjoqgJ zYzy{IFMxv8}67!mXYQ~Zi{K(c|NH!G=3&FA%U zv1Nkj$M5KI+jP|KAEDK^!+{MHo7~F&CCf1T*xI5Y>TBJfpI@0@P$z^Qnmg8arB?S> zqB<4fLvoPKdRDAqJj{7DW~S?X53+CT^!(X_VJkqq2lX4~huW*=9E%|Mi+jUEb6G*c zMmGA|u>fFxsZFD4y6xFn%hzJNn^du8;v#k0z7a+;%7!T1x?~8Ifq{6kJ7qoI8}nXpoG#vMyqXD zsc*EAU0!0X_;NcXB0S3M|th&;Jwzz?PmY2+Kl6U9AeL^Mnh@Zr14NW|AXDzW%D#*WjbtT`*5zf z&x!jdL&ky4s+vbt!z+Np-mmzk+f}ry=+!%tI;IoaC?Exu+HSE7;hco`7i>uOOmmvq zjjMch_CBfppE|i#%w@>CZi#GpV9_Ziq@&JW9Y2b7#R?@15Fj(bF>9wESUh75EEtzj zgUr&6NP%lDjaY)da7LOdjoZMD>WXm{QPUx3*i0X0Vloy@~(wW zyjU{OTW`f1Jm)M8u@T<8-(zk>dDjOo9WjsZJj$!ABym>GUmMg{ z-Y*1we-;=HEd5|Z#*s5aBd*}Pt4XwNb`)Sc-v2Wknf8#))--fiwiH0tx>yHvS@HEQ z-t|`4>9iA>+Tp4apYJJ@#01R%NIu1u&f1Q-O8y12J@-C6At5p^dX*07AmY@}-TcXYBlJ02t`ERd!uV$2l0 zvx01p-+V9GduEkGCAIoiwi*>X2dVsqGK>a zmp9*~xDeROh=2jVEF@<&j{U`7oH2~kiM--dA4RE^hS?NR6Uv`-g2Fo8Y-m33q;^n8 z*-<1h#^x~8cTY<30Ke)BMWfxj)@CU_{W}VGW^>HWR;*=)uLDQpZ6rPCO*>fpwnL$Y zXMJDg$CN3Z%D|9;kvbI5P}z?8YRmK^N%7asz;KC^G~e_UXR)--r4a46C)}udJ5hT4 zGkhyiAH@%6x?GLK-`WICcR9Y6ljXVzh(amyA6nmZYaVuniSt!Oq-nNA1E zAMBLkv5#J}u}cK_JQz&B;yLbX$%A5e9L=Fw*AZk

3ItqTcM;rwGAg7qSjS%ef{Cfl zKc~a%fqMnXq^$m&LAv=hF$f0_c}p)5@Z0$h%NiBi+G?_hw>u=lf6!>O%i*&bg2i<> z2Y)q(F|gm01RVQakNfLczbbmtqa=`g!RUB}$QOn86vyyK2xWcHCr|=Ex3o#;!?`D} zgQf&fHC6USsuz4Z?33>+{N7c9D;i9pm!AQ|x1t}^#-nk9$X-bxy_HSx|1imRBusqv zJsw|#rubN>Guu)k=JT7VtjUXYk0fOXIKTwezKNaLI2UD?r?dw9k6ub^?v{)Y#g1O_uWM z$`=<}KUCI3|GOA!SEMvpSCyrEl488EO-+$)Y~Ex6s(xeaTT8da7#GvO zB(YbM#^FZq!%2omh9ANUha!p>eq>4nvG+BxMEUXg8~g4}B%1Z_a_tIpaxZ0*cqO{jG>4%?z~8fRvfO$r2>d z>@Q%k0y8~-{8(^%S~nEq(L3w(@II}TE82ZJFo^K5cYiS8mcE2P)VnP!<^DMG2Tih1 zJz)1>EH-(0EPbccna|Z}=U2glX_Y{(q}@<8dJ!U1|3qJY5rD?KEC+CCA_nI8x&xOk zmUs}eUuI0N2Gl?vM_OGap+=#tqCq^r1(S;7`zY9vlv1}7M4H3JE(w|GmV&9_j}(92 z-TY_q8ikk=c943{i{WA=N&$4fH8z5Fm-2Bqdk`(UMz_TK81SG*Q~;jr3oQm|WWP|? z<)L-J5y5r#SYA9nlI%+*Nf7=SE8tP2f{>nD;MQ7T_ae&gxE#k8k$>a-j6N-CB@VyR zEvFN4tI0eZ8tYYI&`%Y6VfE>c5uUJJ24EHcb7SMyU8?dzOm=s1Ysh^2tSOnTZ|zss zMhq<-@}@}fXtGsbV+ct{bLh5s^yi8I-t4CJ6oI|9Fs9j;6mp3~2(MmW7 zZI#{8M6KPL&JVe%qIqd!V6@L6kXp-;l5bZBZ@L zb3~+dpmEyCpxkFU>6E#Y?;|+rV0+F6DPA72zlz{)PWxPZ5~Ce#V)Q);z@0jJKfvL%a;7Er#zMc~ z*3ED$=QXCS+IY%Q;eMi$(sI*ytJx?W zY+EMH)(1<6#s7*oLsB{~6vtkh?9mm+nUMt13ffv^)&reXxdubYuDtre@d&j?$Vg@F zQ0^A)@16k6U>maWBuo3x>NoV(ixf*>Q>T#_#$|_hK-|rN=Q3RD!l5UR@nn#W%BGhU z@WjKq9yc0A7shuXs*fNJ6ICC8cRC&AlR)x+uPFsJ3u-WJN&-7=5V4FIQ2ZXyoc#=H z2{w|qhNCsd#3X?~f_wlNJu^2Y8o=dU1cL{_B?pzFmXl7AuUbx<`-XQEEV`;LhMW9QEws6MOal)v5|h zNquL$wrTr$tsUv=*qkqiBX9%4OzF~*bJ_1>-NA42kzEdQ_FiOkjq;G?@dujbXM3M& z=&RR}XH|lUnHlr#Kfjy^f5=zuIq6RGc%Tc_;0e)!km(UP^~JRSLiddmg4dK=xL zBsHP&byZ|S^(u3_!_*OgquRI6yz;kxud#m(0b#?o%8K3H*N14VJ?kp~1|9Is{(E|k zdOwF(U-4PbmvyhE&V~}ttz~~~5ia%@jBjuV)*tFmF8kmto_xHM@O6Wovf}J`n8rMe z`=x+XbH-+NiQbiCo0y$g&;GvoVEDB>yA-E1pXG}q710vV0LTq*X>aR|nwhg0p9`h8 zO?ip`5n;oK6CTpHbLT#wY?(RdLbgE!HnJY0Bi^4K@u&Akp3;Yr^u2TqaY_FlxrZl*e> z1)!Jl}05mwI(Dgq`6Ybphqf9YRMdY@T*+X!Dvw`amY zF&8)R=?d%&iZ6-un477UK$}n#`tOk`^sSS};z}wl!~6s89nGBo4UUghUzDm%S)U1W z^ICj+khimQnd_P8j=U)7fZf}HFXXp74o8RiUY?%d4`=xEzAu|;4t-U*KlJMo90?BH z#HSh?4~7DkuaJlFCv?@hqyW*eB}Smf{wBu~+(>!$L<=wRN2nwZ=z03}+aB<`i}o4Z zL3UgWxs9x>%CjsJm*nTc&UQAqZkPa)~dW?Q7rWICx9Os%KrL{rAfyaSWANsA1 zfO_%z=W}AMrcc4iskWHikoL6y-m1}MFPd6r4T$oXhGAZqzLv2tEnR5|f7;EEQYQ|n z79j{hz}mp+N04yQRNr*2aJbfFaPaPI-WrU3L31o>apNRXj{Xndmq2NeopOelPWUiA zTh!#o;>_WFwdOpz0m^ksn5;$u)UB z`q=#fTM@YCWDTh_pL#FMFk9%Dn~Fs`<@Bg6rKR!fI4|5Df#L1%=q2@{CvPKCrvs>u zreKe~p-uAVp$tTq=HE=9@f_3JHjO{Oe&l~B;Jjh-g2Px1UF{<4%W_h5|GSjYKE@wU zqI_shZ1t}G+q67`cTx1{2||!t(cBIrciUw7D^+68gTeU!HArs9Q|r-$4`JaRaaoC~ z(2QRlyKkpO*s4M5?DkvnlO{?;dCP;rf&d3|e?_=l)pcYXCuK(-Dvq2X3J<&gV^Xfj zIpJ{J4R{eTcXBbH!n5{OWZOIjpC0ixUenka%UeYcc^ifVwWK<>jdAn!ROI12t=QxX zD>T)Bi9m|zGKV1#cZ$qJdwg%^W|e> z1~#y@m1={l%%NTn#zQZRNW7lNW9@ayCTw>QN6;sO^&aozF3!eWZ7+CeV6OydiX~or zibb9aQt)?tTbw*%Uy4G8A~!Q&^SFJI%kXjE-bH&y7kokot+HHnoxu5iU&gR-66)Dd zwPBs5FhqT+g|FP0*l->1FRgIE5Ji0};_$bpF_6MbXO83th~E$e1Gh8J3 z;Mq>CwSo__yl^1?su3e;j@LLZjB$6X#=Ij^UT{|BcBN1%zGF<;`O%u3Dz@)lhuD_d zUqs&vBb98#;ZqF3$T)fHwe1ecY`-~=(6lRc@w1zDRgPDLJrn1%+oJOmpZuoo`2!UY zmz;F{Do0nYa5kbCB09yzqc~jR_J=IX>+1xA`tjMhA&`29 z@}yK%N~liAjSmydI9V(wmyueI4bk?AZI5Sv^He?%ELM>~p+*wq29VI5c&aRY6Wf^ zeXo=_({MQcGrT8Xw|b_Xo==tt?^$m8K07zA!Q7BM*Hgmg;v@hAR4e%)1E5HNy*o5T zMg_}ofgHcJKp|jQ1rVgUzCB~)+fAm$rtMH`ZUTI8E^Uu6*@a)7BRJ*zFw+li(!r-y zbN`7&w+m*5@yVJ($pyMGmF+mq*DLI6xP6a?kE5|RcqF@j%LW^JSN^n7!91GLh+7u5 zU90&;AHnMLs8-F6|0s*fx1;2xQVP)lkkcvvisDU<5OG}_fDhgbpoiD;ATU;vK+0PF zJN=qnz_mq5k)Yq+UYfkUq-yeJ5=hq>iRNWPwkF?z8e;jun0+ZrAA?Qg$dk4c{o{dV zZExf3Nr$)c8BpC)BV>Su8VlGc^B3z8gzJT)5#!-@{1(m_*Sq#D3g41ym-h7e;;F?n z$;B3VcG_S#b#u3Qvcyv`Q}++B_uw5O6S5a8pU4~L*cCY%p%9chqC3IVA}rraClhJV z_8rIWczt3E{ann6zQinujq{`sO@Q-g5P7v$-)on=+S?x}kl|$sy}wZUtdu|5&l|Wb zS*}|FieGJJNmzDb5I<={okLRrK<&`S;z#SkN11#t>8wwW+`NV2p0hRZ<1wX$9Ndg4 zH#?QBb!Y$O|7vb~;CWr_#g@Q0!RY1iT}_gsv#>o<<2bs;`H+t)N9|L@-ch`RbzZk| z7odu-?X5+I+T$F4<3Nf15ck>ReQ&yVW&9cBTvi5r3ihwg}#a zjQ$2y=Gr&KUX@+Ds`Dt{5S-^y;-I+tUFe%mXZjN=^*1X2ap0n2B@Xj-A^-c&Mwi%^ z;=Jt-xlY&mbfbLC?Lgc8XTAJlC1p$Kp*Z{tj<@XOAJs5q$+0!__)C1OMy(rTOUGsz zppC!8X@h{lxn$2W!pC>ksm|A_gZ8n?NGL5be0fKSE3L##;;HdQ`hh$U5AT@+L zCzC~?I|Bw?P5;E)wa;WDrsbuKd``e1!%vX`Hv!BM;=mpP;_d zTB(r1ATvv?Wu*eVr**tEB#{IK871%qQ=!jvRVNYaM@YlqXn{P!qKV|01`5mrO=3-^ zI%)xpr<0q%I;!CpSc{o25;nO&fX3^xy9wU|1;BneS--#IU+!AYY4tgBP@>n3k)<pKuNgqCRdyg=NS-Ryg)y;MjpBWMZeg%IfN^EbgrUjfm~U;- zF@T4>{g$Q0V?6Bv!PqW1rwmE;y0j^Hg-T#T8q#1(0c%r`!|KaNMMTy>4Pp`;1o7-$ zGZ*LuWbh3{m{I>tGuIYzTuuLFFJ-do6wzk03Du4T8uZzxmyG{mRJ`FbV3r}rtdE$! zhVo1Y;a6_@#4PoAe7!r5WFPl~=yjg&3Vgf3>$KfxJ_#W7%)Pk}7C3+sUu~W~Ek~o* z==S`~OM3UtLS65lTt{gZ5xeV8Vk)Q`?ZBWj0hlSE$ZVD(YDz8w=>zci?c40YC626- z?=^T}jFdaKM!-I6~tZv>a4Y2T}N~Pfb=C zi-eLn@XRZ%9d1@-YsW&C@hk|RN(qr8dYzttvF5)JzR^Sg>#T0%Pwo^je34(uRYw^_ zLAS<&Br1sshSCGs61j?PUvD+Urnyhn(q*q+><`D_o2VFSou>9OwHME=q9hU6YRBdn zt8FVacQ*pdwaS>r!L+_*4&C9>%M;`o`MXtqwP3LM;o0dFN>YS|mkpT}k~WEnn~(2M z>(jiMoeENx>T|TLAa;Ev8*V0{>&(ztr&hu=AQohzRxAT*<9ZDExO2FZClRst z$(VEa2&o6SRU5Zqam+Ni(%})L3nHtZq{>Pb=Fl~f$`;$O*NqeFU#Rac(6%^*$aqod z)(e19RvqbBMVdGLYBJ3}B@?IpFGSs#&N{jhG6Qp?!+Bl4K8*5*Xa_#i zY(lKcl#$WKc8$J-Myfxh5Qss^tnTTG=G zLc`Ji9?xf4O(z3dToONJM`IBk!#b;qVSnKvOq83%47(JN4%eK{TK@EP;qRxL{e^1dzDJF2mrWN^6YK|DVof7NPntMuS30cp{y+B-x^7d1x!HbpT2qhILDG%Bi_W^GwV$Z_L5yi^ld!qO0VX=~8MOn;GPYyQz)5p} ziEA&cet^g}iDjT`&Er(Z$gU6$&*M!(d!`Jba-^NBu;QIeCFN>iW!m7sRP(h#=i=NL zK5o%ZF47=rhH^LFVv)4TSZr$FY@8#zy?T(qdA)wwh$)OYb!wi1u2!!%AqjNpdL5;A zfrJXt&BbKTrsMw(*QC)(Tvaq7Qy0>lU9G1$d}zVPs=8gk*(BgW$nDq4K9v_VlWeDj z{=E@-Bsxc*$`n2x46IOXts3_{6oybwc38&VBnRMT8j={-yPt?YpD0aLVXi>wX$JW2 zTK!sYkDX2f4&NFN|KlmMwUS1k3Z(;BgInlwu~weaSew{xlY6jjXYMA&0EN0itJlZ- zRD=}cW-T=6kF0t>k{LGms)D=>_+TBpBonJI2P^h)%|PP&&jZ#|L`a)q*2 z*f-mi7?DeD(r?upeRS1N1K-1cEVkA!u5Ao8BV#{x<^0jN=(BNAmD@p0nCi{AuVu_H zp8|o?k@o`YblJh{ycB!vF>l|>WD5%Jr=dfr&L$6OS00E)mI5$up!-E!t->^2uNvSU z`LJ!M@-1{~`ei&<_&#UG@bK(aB$BE-K%}(U?~j<|WPH0Yizovui+Wvm?T7iXOjUnn z^Xa93mS~N2b~)Rx=|kA^DbcFQtjFekv*j267Z2|=`2|~Or?aL`hEF3c{YLSmMfhNT z9nVz(xtBH`GVjt}#MI8Zn|}xD$I1c!MkaqM;JzDB8;RHdTU)tz(M*%X-1x}&m8(~b z6|0cMl=;>YWpDg&k61(Pb?kA)nsE5$6S}2plckJ<7bp78RUS4)`M#&iqvk@og`XZL z)Ub+tjEhkjvn zqhIVg+IhGf5tE)mA7Y2=nTJGKOSI{p`oa^_IpB{#6Fqm&5F5);bjE74?sZNP91&&I zhr>)*^hrE#TwgJuYcy&Xb;SYm5}#atoT9J1fA6n9OhmO_ezc8%W!g-g-EhNVhG6LU zQ?2~OQyjj@&@@rOseX6)8&;O9PKLZQQr(~G{5(27{BG;syzpbm2w-n4heO0iOTW!?qFk)RO2EdUqcI^wp!{eZDYVe$!;^$;xJF3EI-5}7436_DJ$|Sz(L+GU#~%! z0)^i-sf8@I>9S_^%(BQ1lC3+EXnn~({^=h!kMEuh(Yp6SHu4{Z9@K`73~t|JSS;7B zGOH7xTg|LGV`o8j+SgiT+jvIW98bPLb5IdcH=b$zy10sP@Z#9xTK&>b0T8TQc_$vx zIw%8a5>1Fnt^R1q4h)`5w>FvFqRVm^WOR+mc>O_>loJPVO|In{?ZQWxl@46TbMG)q z>iTbZVLIQf!1ipqKJY#h=KE20v^-p!DJOtoIc#~Zt2={A2bEe22Yu$={11D^o>M2@48&2QDu_SUO@-Uu;awFLjUG8~ElEYT1fnE;6M zxmWS`EyLz4L%2whkzNRMQRId5Usv zu-+a{e^nZ@bDzvCf(3-Xry-7dlUBa>;wV0?x#d-epq+fmRxO-;ZXo+bt%@uRRimTk z>r=@^wDosN+h#EZ=#}5zK4=AbMjQE6k2IrylRNC`o8`RE26LWWpp*G7`V!oR5R*6c zLKOKf%QQ>XX-a4J{MH9S(vrrt>KZi|5^3Sda>LuI;1t!sVEuOI*fYcF+J@}qI^A%ewvg_qNhAFpuABvMU)$BHGc@CYLP@AvtRv0qN2M?bkY_WvLnZ zPhOf*FQTokdqui8E*H+6cl}}L;kHq)E^coQJN4h!L;qOCWS_22_~Jx_;bG!qDmVOU zR0`aMd`+_JKl|%}Z{nUDw+o7-s*Eg$Pb$3?>H7j~z{-b3ewQ-9rv`hGHb?of5S$D1nV!_9c$z~pFZh*j5a zb6lc0#rdGv@KH(s@%TWQ9{I@e?qhDGP>K0Pi{_3yH%a=WGnT6n&W?@?3U~J%N;F`P zvFz(Bjow>YHe=rY^3T7fy;07mN=^IXzZMbws{g|VBZU1s=lkEEQEWCiM&&1Q@#W>G zgBlilI~yNqS(@`|aWoL9><99I=W92mp7*B108$Bm6rs>5dvqV(lk zVC0Zp#u)xpPw4IW_t?ZbUDIzeR?hDZT|PdEfl$X;YS`lfxwj=gL_s{{V?k1Xr?1}Q zLyRd;Ug(I8!-UG~F`xJEfk$JH1mdtC&3gwTrI$M)n7%V7+o!ALwRk$gaYe}>=;49} zgG$(+8DgMCJllRk_l?z9BYA-$iX$4ABu5>@o-tGdeX0pu7U-vr_u3(AFZtHJJzDC3 zX&zZa-47_Jj2YZr)H#EUVbIDIk7^BgC0VHPM6`Jy?A%p%=ZV&g66I1w1T* zD5ha#O#d-srZ4egx7XHtZ*=3*l@h!on6FVvhpdM7b@2^$)^;7JX6DLp31xdNQuc}< z5jmzCQ8%|G+$8}xlc6mB4qR*jGy@Zbh_ye=)b4_-$}C*Qpx~^3{0!S^yuwa0qA|Bf zWYV>0n!AQeSt*ZKYYL`Rd;xM6%_yDVqyy+Vl2vhhrFPP4Dbs4w9663*;)sP|TgWj&)u&V; zPhyCBMQ-PewHYS;>q#=|_4R5&i=$_YQS;M)1nX)g>@Bd<_CY*^%w&kBfnuh7Vq(Z= z+M4t?hyeVX*E*+~gP^YYJdUBhZaR**Ow_{~2G8{{*(t$sLdFovZ+Yg*MY#&a6>v<| zDv|+YG+;L2=)(51;kq>a!5a-8Id_1XcrObNiS_I_>;3K4=4$eC*H&p{hC6usCCltR{{NfVD(UGIAQX${T$nEe>rn= zkmeIS6{duD=>d{m&$T%zRM~NLYos3)UyYbZ|1zGV2~=Ag&zTOoF&5{?N7+9T8rm=J z;q&g9Z>ZS8o884ZE*UvReb9oE?Z(qvMv&HG2psmQSE^F>e;j(u`CHcl_1Vjuc}PDX z=X~T)1IqCgJWfErHIdi=6qNX(T{O*i+cwSIfi%k&n<`8QipH~rQhlzmgBkF~cMnMFVEq3N98?tKP}s6Ep|rGViQ)wnI4CwNFIcvxwpF_9`BYCWH7zYKpwx1u zV%oFXR%zL`wtSMZiocO-l_FOUnx=C@7cn<@Y;(^B0%HIq&m+zg`h~#yXB% zj#Ezo63Qk#2reMp%7vq(ZoIi?c7($Stip@jJ4@1$mOY7+zFb%@TFrLhOZl7v5x6OK z!syzb=nOs64)mWw$|EP3`j>?Ig&YO_)#})EJSt)Dj>JroXtt*dU2(lK%L;RoB(wm@ z8OSFWC6n#36!XTeMh^zpQ)9*`!n1wpSX%%#41w#ftDOt+Do6s+k} zhnFJ1VLS-HC$4G;-@O8ksFB(0vC$RP@`g%Scbp9Y&a0$s^yl-!M{p; zv^ZP&(ELYJ6L}@)d_zi;XFI^MIy#04U&dj0>MyeKGSN7+`>g0Q`il1E@uupOZ2yLt z%}z?*-P3K3A3(R$*ZcVufyO)8q4Q~Ia&?=3Q+RP$=G%WQ%WTZJSvb&N`AU)9y5_bc zQ~vk4*PDK-G(tax_QWnc2Z^}>|K51rh2+H!Kko2gU_mwCz%id-@%42-G_hLe;_14atuLn#xJ3f+T$l{2 zc+A%R(NXxS@8Zneid70{&E^Vg|Ij2uoy&{rw42Ap)(=z+JUXrcm#n+FSY=8!pgY{bSuI5`d<|5|OS<;6DmE z6nEhPQDj8l962?m7c!uGx5lqTYyi3e^^o#tZ+Xl)CmFnL0Ej(`ro*s?f;x{l7pbsw!kYs4h1DbpkaI{Np_{AwU*rLY^wpd~33L z7i%S#Hq9--rXk)U7z@IUBEFELRCs!C&x;h^*}FCL0@WA%DHa@Oev&|wtovOOw}SJb z*}Tcg0Y>%{orrIhu4}nul|l^Z;juTM!2NaCnmT}|;0OV~CZt$EG+3&;gqK8*%%f-W*r@s6(|Vsb7n)x6l6 zfDhjC&yHx^jnk5k5o-{(>*tL zpIfUCN3e(5|EJ;Kf$=E$=7~ItN{#13q8<*;%na&_K|AMdqj0P`kKXStO9vgZ6h_Jt z_9caJEk|7BZ9huB=k?t~>Te4OaX~^lTUm`5J$n`wBN)=@(Xe>7V)%x2^H7-9OmN0_ zK$9<=e$?&P&8xl}h6EXvlCGV4$}e42#&vJ}gz}bTbGoM`78whAb&T74os$=sLXP7; z%7x_b#dha{DFq$`3w!|ZbBJkq8lE6NfI$B={+i~#y~^~79Qkw%09zH9>QV!hn`$JW zG**!m>vrtEzT|)Iiy!_u49S>yb$?(QI7!27M5CN|gYxDSW!Tjq935 zhWaH6Af#U?nN9UgDZU$Si_NuFHp05!ELhRCh^+)CNsA{?ZhJR%CCDVqwPc>;c?rO$ zBU(c~ODtE}YI*w#d}7}_I@CZBjy1j^WyAw~Hm5}G(UNz3k$oQ|N>07zYZshiCpMCw z0=P-g{J&5nO?z(#k^JD7O9r0?_Q8)BxF}JlsQHn^HJ9i0fY%~>v*x#Mr7(kDkv%xa zjAn@(2;tzkrBpmt9B!l~GYfsC`2R1wk;<@`qEr)*a{fF(gAtxmEWtA!m>yvSik399 zFbnXTTO`Lq%-$497hizi$qt2K@$w10bm7VC%siaIzpmdIMcgazEM77S;nm`Z6pHUm zv~-y%@E)~ditImn(y2=X$k74or8*=$Jhix@BS6{STbF;!61K&x!-wOb4p)0aoOm#z zu`>Nopz2Tj+b2)JTRU;4Qppmi6-{r{HPSbQZ3OpRM5QU2`=Da-Hk#nq2=Yuqa5nUF z{e}dwggC-E{SCS;yqRG>G`9sPq?9RWP%HBZOxny3180AoZsq%JMuxvwFX1ZCwYx0| z^8Id==#rSZ8!V(L_fs6hqs(bfb?h7&j;a)!16q ztwKy$8Z|%^)&7k-bsyA>ERdG-xMSF30I4DTUw(&6PU&RsH?V zaV{y!Zy&fo$Z}4*a?dC0SJ)8oWasRs`Rb)j;7U~SYU@Qk(2GOrgGWuxgWuZsD3S{`_myYd>WNA#%(bi*bn1sZH(sd$O<& z(Q}r>>#YB{6HYk@TUWZk68r^l%9;TALp6`tPFCSl{Y|*4)EW4Uw{p+bj6Br?^QGst z{u6aTv$u}SOIWShfifWrKg^4HA%*UGE56ot>GQ(}F@0maGS*`mc?yw&I_wMfFdy@G zhp+5bKRbBGRW%0=nGR( z96|XKm#a`QZ5{3Mu;;!pkzQIwS;qIdF*5#*UHrY}ye>PQ1hW1VpP2L~C}WqL>!ZQw!l-7US&lhreRZp3eK-LS30-P1d^QvF4X$A~{WfJ79YprlT{ z@?2l-g)G7g7O(OikEP7k?Gp5o!!%;3%B^ju^RW+v3WJu|^hYIqM9{b6l!&nahEsY) zk`6y9{}NdDn%RrVj@nbP*t`lr?F1NnbRzZ>>F@t?SlEDYNvX_mJ*7!>={YsFF)n5O zHTKw@h{XL{>2<0mko`g+Ik~%iEA?xD$Z>Q1gx<~R*!itXLie_dA7T?!XZD>f_224r zsV9Z><3@eZD&rh1kk4KJ!J#2yo_~VSUu!t;{lf6cn>2s`RLG`1+W$Lz#XNl01_~ipm+UM_{e< zCFreWW_Ay!lTv#s&R?0kz%vbWwfBcu`AAZ<-%}S)WEp|{Q z-y)d{Q~yxj;;6)t!H5*C zG`l_cs>B4)&-g^X^Wz{d#(Gqvz(3IPdy!=IlJxecA5)feEM=`~KOn3f#d8R7p|#&s z?)o8Mt2mkZ8CZZSKl>GmFK!!eANn+@Jwt1co~SRDk%xPr`sT!i=jF%e7^nZr+p^_< zmi66&kx4{F|6+BG`mV66LUidHx6$GM_D{Mvz7feYqxT+Yjc)zP6>I;`no@by29-VG z>C`=31QO_>pKsY$`2Dd6=hD#85?XF-5BmPMi$8@QnJr0~4}-pT`r1iY_2ZDFYqvE- zglD0DBy2|&fU0Wg9c}ov|Jd-+yBnTz%QDh{#dTakXHexWn2#D&0)Di!k^MTzpj20KGo~e>E`--=8w7VF(o%{yFasB_6hrL4FOSbd?8v5+zr6p40o*x z3yARaHD{0q&(5O+&+WM)FN{W;WnIyxw!@!Z5^|rxi(gWb2jRD)U~}(1^QbTITc_R zUu8MN1qF5Ncs=?|k~8VtGzX9ahY*inOWokoaXuhP@u*=W1Xz#@qkQhI8ZR&Z_z0(c z$kj?ifx3R#- z^EmN;@ZX6~B|ly`a_sD#hv%VP@xW-4~|Y_{Vh?b+Pbt0acBbGd4-wTW>#v^5GeLGV|;axTP>Se$G=bbLDhl_mP1 z^Wep&gop#%`1?yG7bDr8p_>G*sJqk6XCy!fH}|zv=&?!JXjN*gdB*&I(a3cYe0!qr zxA1fB^=gr1TFuZ|XGZIxI}-!oNS&ie!Vbe0WlN8W=q}VSu+F%XA4q_=qSvy{v$3`a z4h#NnS41fU5c99tA{0CVYWEjh04|^@csvnHqpB!cDVsC{H4lPq@N%93$uqdM5BBm_ zhvX?QBZy^aXvl(OS^5mTg%9a(uJ8JJRZ?3Hve(eZ>q}jDQ-vz_vNS)No7=OzOc`a3 zyXE8g_YuEUuC-#gprCYKHtV%poDJLqBDK+70Kvwh#A=IN*EkRGZ%ZTK+D z*p$2=uCiOt2Yhb?u#F3|yh&$m6gTE}z ze@|N$Sq679E%`!@yi(7zecvKC7JFKli57j2y3_WnqcR8EAFIDcbf>JsHo0+i;~qAz z^#x9<+?OM!o{3AE(h={ceVYtgQ>@PQ-1#To++5%DYg~PplXw?nIY~xDnw#5{+3O z#`9jj2|pyaK9YPkYyQlFcr^JO_$G4Kn2fxP{>d5hM1K7VucmSAWLj$3{qAX6-s)_- zN8*W)ELi;aC}G=&!NrF=7e}s{)!aW85%*HOT60&-6B!ojru&MLmOoI$(cKJ#>EnD< zYUEIReu5Xcb+YjuU{wZv!ISW&TYt*nhVky0sE4gbCyYo^`}lay+)-e?&)c$2nU*Ujdg1O z)j7tU8yAHoRt4bPv!bS*ZFU*Fra$9VVY z!*mu_byc@3)`|By%-h4Ol9So3odPPD`6z4J^WLwJV9S`7@0~U8_2Ie#P^25QoPY`p zoe+=%ku$D=qqLBLdw4T1Ke472uXz6Z>#~MO22(7907UvTPZN>+p*u*<4xAlkKNVXu zyIcVNGwMW`L>6-HhQ#vPydde@!w*CGb&45L{|D$20M-BW6%P4}C1ksFi)&z@IYHnI zBhwjLxx5|lEruYFJsdd%aP*GU1*AerE>Jo|{$CUz#J?<1NscRbA-b zo8dMGT79p@21U@>Jsu{S#?S~PN8U?`OSJv%cZ`JUB+9*G+_M%H!GDf5z!!|AREogQ z!c?V75HI-WI2~Vd4|ZHw10rf>4u$W@mun*L{>+Gd>c8|Ba+lIjJia7mzmHHw>7$#= zg}o(g27kHfJKe{hNYw&E!W_CnLvx9($v4o~*^k_-A`J zp;r~sRi&p#qqoe|CbpeI621)etR07b*etbbJ;GQeXvtK>mZRdyjmW;$xduC!^reJ* zopg<3J-43UM7gMmd)CidcBEm=06XPCyQzI&kZLvW!gftEf6X|Wq;jA6aFbA6`bg&R zD&tPT=ytZZ{G}tCKEe7#eGf?%cP59V?Cq1rLsBXtUR4khHHC{w$$GJKNZT+e`Msrq zrw)isome-Rg=Q{fGqNBo!i&@~@rdln$?Og0u1+^G(1mYUaAus`8dy};L|oQu1;d)7 zWwdI#xhGb1mg?9oIf!oWdFzZQd{LwS08qLI>+U!_!z4)@B>!op;(753JS2A%Ns>pA zNpl|?|Is;J%k$woRtDOlNy4uIqLru*))*mz4Cvcd>;vzd{kTK|mxk~F z?GO+k34g_i6~zdejCNrjxIr-j(3P4xeKYfT*R4RM37^2}i*QX4=T^t9K(o!bxOQU_ zoH6GW^unw6Rt~dM3Rut>-l8Jo- zXpifA_rLrrFKZA(@Ydk&Z4BJg$S|mH_Rs_7qATBQjCgQ9-8TPDq(Vqi0SP3 z+nwh*)=hPV(=b!cY3o@4By~ z*?)=VU;hjE!Ybqlld?*`)D(z(0~N^VRl7mHT!BI%X=}14y;k^5ga})Tj~0Ba7xztv zFyzG6Z6@mdh!I(hiQ!&L)hrK8lU<``yL-FVZuPw;x5fBWd5N||$Hgj!Vg~|SCtPLH z4pP01d!M;#lRV()Gv9?_)~>IyNQNlnJoQ1hVT-&&r!mum& zJt^#%2k#lVEgknvLmIQ@c(F>LN$6VB!>RcVy6_$fPazw8iZCji2cPuBXbh<;;q>^4 zZ|u&SToPdaa1`}&43byt3W0q{DsMQ}?SH+swh4*F1os4kWJ`#y$tsW3@EpYa_VIza z5x@D@$b&R5ABQxbV#f)=`f#@);BJqxDLXuv+tk8ZaJwy2rzh4ehCgX-jhmGkw);(( zR=l?MzP3)}gf;WwSXYRqd%{=trhdi&v=YX9j!?PC+Ku<5o-`^*{nxEo*QM3-tv+rZ zA7CSRB%;j~J*uzG6E!)8}#@a>$j`eq%#J7|&y<4%&`L zlY~$YH@30@`Pb7IccAwHqW7H^V?(2Zg4vv;`((Y(`$t~;K8B!F8FU^YHLHF4hVfRE zRc~Fpe%gGhL$1)UdZ?Ou@8a^)p?sJ}Oc19xCBWJ&S zf4|&3eG((i(@^DOBmX|yKfAQXc+t3V+;6K1pE%zv-cu)h328hoFy$vv@Z-L1mNCXt z4Qwzvo#XX+An<4taB$jhCU*aIgS9UW-2>{gE$TU6n3p7-(^hqt$Hmf6ju*nfIEb^rC^3Qg{&8aJg0ixQngV@% zNt*1oBz^YKqpL9w=gj*O$(fAiV4h16x=k?_;2F;yJ54=%{7Y1reoO`?K zV&m@>%NYMZ>AOAR{-kbw=Y9G0CE2zbW;@B8*YEzwJw_dAQ&@hQPv~m4@-~Rvl94I|dk{R-EM(!euRTc&DFLEuIu{o<% z6*}2x5Z#!ptTlhmk7$3>KQVB=Zg|%#$jbiRN}bEMY6cb*c6sq>Mm;M;bCh&hIKu`G zb!RWPY_I!RK>yHa**w(y@obcM5zZIHTT*v_KNt|}_9=v?`vgr~`I0Wb>PZd-stu~{ zOv?gw^rlm|M^!lGOY=d^lLIqn^5|_E<;jE53zyt8lzCX-bmUf_8O01k{ywgo`B)zs z+m%({^lM<>PhuTPRXxFW{1-W5kyqsz+|GN6)O*etzw5)<{%5&~RvZCPx*sIM8V6Xa4so6AZtVqS^ zeleAqhf?OkRG(%{8lk)Ydfk`}t!NQ4)4b0BQ%1j7@mf(aHpoEjvozV~)=AH`~PqqtF*_vU{E)=fi^{k+ZIWt}i(LT6#{O zSs2Hw(x^jai-T1CD=m9X^vFUF6Vm+dZB%$6N@SghG&iI;-7BK~N_Gfd@$z;dzC2~4en9@yqv#L*<(p?7VI?CLCSH& zHhzJdZRhE=C`6kU+j-8KD^qw+)VO^qt*4edH>llN{=}z1Mw&llZ9t6jbe%&FIX{4_ zlGLduPeORv$X4mJ;1u<}7uO;|$f*!UAA;tp*`7dT5)a)zfbEZ7m5O4Oy2qhf9yWNzmLl(~QIXN3mj5J%^= z>|w`XHSO!B_=bgW?-&;PaHiCsAqspxPUGeJL|)N93!0cu)I4BH--%Sj_bvqu-}MBv|=-E61q;)ihn|)WloNPqCD1n;(|B( z^DsO3m_zJKzYhWvrDuywy~f)GeDFFbWMJjc;A*M|s8{Z#gd{ej;VQppPIj__ydjJbWCiJZTf^nO)>JGM7<*o2> zE;`b{-gc3A$1R0)Sw#&Ywyf>x>(q&cwyw@Bmm~1dd~cpV?my=9vcpKRFh>#6bH8`6 z5V#6tjX39gihToM=|0RE(wwHqun4ti6yJV}{QENh$lKP{Fj;7cj#G<( z2L~EmpWTsgZ+;Z?P$T8NK4aMJK7CcY5T)3pcV}Z8T3L;x0sT_LJR~$rJkFOCH+HlCEIFpgO0<(?zxrInzeCf0J%=yJLboI5 z(H=0eL06PH|3g&8#5K$_Dc@t_4odHqK(D@%_0taVQcF@5^G?!iZ`*o1ymKPyB!xZ! zD25E9&WH7@dc|phWnBh!`jH*{+lhNWfUe~m8~r0>$&^W!V&5Bw$oX2K*k$!)hC5Gl z3SU^*Xr&nnrtZ#wk`?b!o68c7^Ddhq2p%*6% zSZLA{ZWgbF%)k*)`d*jmYurNP11yO}M`{LP7@%GzP>#kXw^LWQg2&7G5MH~~p&c^n zlw}PYA+~32%n@LQ;=_+Af^@2DZDiCJ9J6GX)nP8aotTS-p2|em7ge4LD^tfFX=!?y zW@}NVT{()n(Ze%uV{SS5GFS7#?mhgM8+%Q_5!>+AD?jJ`?)fkp7J1gbfyRa@QR_$+ zKylW!Y_oq~mr0vtL6p^|q|x#;f-sInI>qcO$%DHjP1ghOgYC+^GhhV6hItsYEDM|? z+o1ncwXt=bS;sP9rzQXKYpuGr)_Acc>$Qu+H8vpbJmUGzY-uEdk?@?E5puy;So-`p z+hJX=`wOu*nx5BfxjO$AW0VZiDzCF0ef=yP z(qy~lC(e+`+YQYw1A9}2`hMHEP7wno5ULc^^6zqY*!kt>d%0{xlG4V|)ta}~bA>Mv z1(T!`{K+dDtWIO#b^~GyB`a?gbF&AM$atLx3PFk7I?X!hj9v-?QEVE+%I-SA&@h6m zv(^enEqsQJ&^@YP%X0qgq##naqGl1%Ow>hERD8KUzl3P-83pMYKw}_te}=ZFo817L zC7>2t&Kr_B{AobiAq!s&+lPD~Du|{JqgopXRTzzZ=PGY}jHC?<1PJ=3*`bInY|uf` zhTzAv7QMS{p~`c4I6o~z(}|>o9A`2B%<^Wb`yR)7XriyBOt9hkiak<^Xq}o%t3w|N zZ?Ts0865<<_6weIP2(&AH=Ie1YQf^VI0&uv^1H(y_;UVzP7(^zr-2d@#3cGu6cf_K zxF90KTuCx2{H4S{4@xCo68H;;{VBPm8&`$L@iN(qZYvO$)Ti{#G~eON+3KDCp)`=S z+5Xt>=vLg~h%YU+Z9{Z9hnp!#X+Pl19P8ADo0nPX5mEGM@nJVOu}05CAGtWSKYw>ud?^nr8q(IHC#MuwFTy zFW|boS{E(;LA({h@_Df_$&U)%>vDl3JY<`EHIj|angu?P#y{=KtgRG#xXeyYJYPZ6 zj!t4cz6A}q@YBT^H?yJBZgAt9xlueA!aSYy#j~YNM+$#L3}EU~9$YDYs4t`e1lW9f zbpt9ipL=^CKEY3X&(j}j68SjX&Gvk@kQcE9v3iCWy%=c5i|(jDXmRJ@=1tnHx8{xH zf3TSIU#u-0KLb_^Xm@+5i2nuiXTleXdycom^BQy89?vZL4V`vgDuK1-4Qxg)!O~J1 z>2W=N&vPz6IAM)12m$2kliIcMsZ+o%3o1w*2)@p@MHcFVIscVDJKmQoRtft}`OeKO zNUsk!mt-3@fYwas?nttQdhWZ5eTn@GFWp8StXZ1k^vSyEvD?`vgcyTEpUxl_p}DeN zvM3`0x37+evl!d8ElBNniv4(qlH*jExkNYz`%cJ$msaQgOr{&Z(_;VC?b>x9&^xVW{dY@BNHmpQg#7)W}Wy*QK_M{nx1LH`6w3JjE z#-Ak}d%|>krb`mb1*{W@CV7;2kv}_fEhND08 ztAV1W*&W1{I)l+7zvOwT34_MGI22>F?!_gRsoHbbK<4a}bRC!x*9uFQO$JiNU?W%+P1jKaMQ=I5x$Zl?lTU z$D?md_QI-oB$CBhK}-sh^66pjVqA>zQZB+CJ=ICEw$vBlf8#wc#t)umbppffX48eO z+P@xs%ZLC*{8s{|;n*)@DwUNyg~L~;JpCdeU18@xi@YwVGWWvF3C}ebkWe-#-&fez z>;=dB`l}V8l9X0r?vLGW<1?e^QeDSOr?jKQRXjZBKY1CX2=I?f8So-y2n}UEW2t{( zLbZL93aBZX-q?*xFm7+6RA_|%F2Z_14b;9Oq^wfP)^2vS+jJpvc3nOZ`U+Z`J z#wtw2bB$L03W{Q@>Nkr;V3uc*8K;Z#a$QqOvCb)3f0hM~b@^Ct$BlBHVfa>ouIlR1 zgj=LV?+8~U!aWX;X89Y})Ydb8i%D3dj_LjnrQwPBMNaGxoqS6K+bdaUQ}0HmC%6Jy z@6(sEC#a!NZh2#2c+mc^ON*kj@0M}uYFl9{l9AiQVhVD;M87_Dj`U?pi!rHKP^ z-qW;JSc9k1n7KHC6qFmI++ zF}@97(Ece;crJU&70yg~dg77eQ^wt~82OP%qq4*Q_$vBl%KL80D|GZED1o{Vpf=c) z(&b-pV+ro0eCPCv(i8Y?`pZWadp^?}u^`2XC9|f+*j@e#=6njA62fyj5G#lvu9A zL8i09E80-KSWYN(2hNxeV^z}(pm2Q+8?SS=>^Dv*5o2nZ$qc&mZzP7Lv;6{q+1HXo zeCdz33&0AAb9atnwSkSdkwM_2eX1X>K}I|=aV2LcZVl3Wv@_&>2iCINM8Dj^E(-F! z4KA1XJwAQ&XMQiS^AQnvbhXX~ zrKg`6f3>hjfD5t@(x!c+;F|)a$thQ^3e(s%lH1(@lJy1kUK1%2J;95N)#Z44iOKJr zhG&%vywnAJtAGK)&iWVX5PMnwasBe zH}{>8V^qNytb#Lo?9OT)e*7C1T7Mu%+Q zm_ZMCD|=RbUvx8eir}B7a6i$_T!*@M=kP5@jsey0 zQOXnB2aHvPGXJy~fZZ_!Bf+L8IA_GoNz~V$c)W|#$QgHcTX=hT%80A`#(y-KM2yPn zY5|;QwoYjz)_CDnPFpR4Pz`a6;15CTQhe&n@s7y8gu(P>!H_wTWkgb8YH_%TN-Y@E zua`+}2(%vA@okWK@R*?x^kd{Qd@ph<93>=cL9_6^gd-NXIQe-t<4-NnyWy`Mh#Z|G z7=eta<%pr00GHpzs;K4X=omEc_I#~YUcxHxDl>2Wa_!R7Pz%31dm&8>L8w;J6^IWx z1_l+NEFQUA@E;Lvl#QD~Gt+<90xy`5uDP2kdS_Q$91J*qIll#a@~RbEc+-Ub`x7m} z@hH6uX=tV_J*6AvT-0@o%C}R29?e_XLWDEp;K(C59*r4m;jXn!=<{G@;ELOGP#jMA z72R*7vQL2|H)X={Mim?AVl(z_iN>WvmO$%IVq z+5(R>yegZOXj|y*A)$+QMP8m>CMa??dYB zIg4b{uU|BHLfeAw#shvY2PO0TVt1XnaGh>iX5t$8G6`~~0iX7Z`gOL2p!7>R6CfcP zWy3zU_U2O7Uu1GkK3_zVspr1|+x=9ww?RN_F0Cs<^-zCXW8Wu{3+e>uBFVkqt?46v9#{gje_r-=hVqkY0o?Ztv6J|WmsVa|l3X&x&cw+`Vqoob?uLobQ zFCs~3uHP4WP1W4L)|fRD61X-FZ}{rNse3Igh38(WeYV@IV>1Lc^p{5X%LslQI<|%u zx6VI-Gm;R1_OXaIIv^8bwZz7GB5Uu}_7XA*778#Bb_W`%ciHolnc7Hc|CA$y>$}0%lgI2fy{7 zP!KLm4osr9R7(Yax8yE8fN9*8`*I;xp?(r>)T5IgmRScdywipuO4T;Ik@M}#@+nu8 zFex$kyMzbiuhvQx#PibS*YhLl5|3UQUN`dF$?Z{m%_La2zRX@&2hcml*F1`Kh`V?^ z#p~6J$deSdC4jiW?a+w}3@}3=L+J58*E3Cu?XP1-{g*E2z+WH*4-AA- z6YF!nPF&vwr#O%GzL6C-cke}a+vi+WP->uJ$CWN4!+_8A13NwJZ>F7KKgz{%++PO3 z^~H9cPF?K?>)SbD%f~SIj?1*QsMfetTx#^uqr?SPvp1_Gbh5l7zX>hDXn=Emep)o! z*)Nz*t#hsv}|?G(*)HRJ^ysqPk7^9elIz=|G4ls)Aft0XNT?yz7ZSEsFnqh3y=e@omb}7YdESm%}}#tjqyD zBd&{+qhAji77=w#7|$d(>E*L(r@*C>wPY-&(Y1qKwphhr2$4-t70e_s(yStPVi-wq z7|~>-(6v#^ai2ems4`b-4r4BDSbeL|l%6EF%1rfPOKrR(0j&NdmV(s8(`GuI(BaiQ zSx@5=Vmp{Bh4YgTQh(~2-TY$)0W{!T;#P_IE zLT=6=-}3_fn`+6zL?J$H9gM2jLBV7A_W4R@Yy4cpYhD=@kYVh;LKSl`)all~*f&&; z*fCJoaF;5*=SZft;BTX`c)Y!x=%_0iSi|W$v%pT2xU{zFn|m;>EW1?~8FORfl=VO4 zl*x-D&nZ=CN|`qnJI#?UO%;$u?`x8lQNLiebfj0@N1i#l+dZAU?fge!k9wh$KXN?$ z{hA`Ec>cWqT3W}n_`*Yn34Sj+jJsuR4ADJt-=?Q0mbi}sz0PqLE})v7fFf6?V~xdR zmY@9$4wu7%2M_q4i3vDQ143_|r`q_Bz}h_z%Lr&^EdL4t1yZO1&Tdu(!^KYPxf~nt zk23P62i@%JC1ksmt~XTycns!2PO(Pi#KVEB1VtB~Q6Vo%Wk^Ql zpM5m8V?=)RR|fXM>2H`#e)f|G*#T?u+f|Y>X|{Gg>y|K1@N(rm&9;g)DUk7)n3W@SLZDtcKe!lMO>xjQe9Q>fl!^h z=L5B&@9{IUy4fJ7!qKMqz@5o@(zHo8Z==x#dj3%I?qO~q=c`<@@jVq$XXnvy_L`(e zzl}5mbK-*eTS{iWK~Ii$n|&KrSS6EFy_(J|rAm+Ykigs-I7)KsQ6nF^x`nTR`Kx#H z(#Y)W@wTfTZ>I)QGdzEGa%+P&B04nue;>`5NqsPntMaF)D|YI{W90yw%R}1E8u%n? z;8UjLv-+iXhn8TcZ#Nhsa>k5cbR3$ubf%1n)LyE>t}RSYh-C%4PV9iA?%-6zf_vj zQilTVA*x=Mk%#k1an+*z!80_Y=W}!zrRu(R{a@8RsZQNd7*Tn@W2(D@+05>yQbOMY zI!WXuWUr0oOZ)i3c>G06tYnndT^I)G!l{sdpe?{}1vtOP8IU@v`M&4IjSh>e%n0%+ z@BeXh?r}*T?Ek;vMny#+wQ{9_htkp#1;qn!BUovkDBH8P)pXgj+EYzao0bPqY+4@E zwtBV-muKnV zee|?z)ut+Tq+$_x>s0CQ*H%(UzS0}H_Nrb2&`?%r@EQXcy5kzGWV5~2Gm^nf&e*39 zcPV+Q9X{sW+Kp~mSK>k*g%cIulB1af+H?3jt6!=*-r5gl#M#zBOL-NTQTz$$C=}LXJ_3Rjl%Nr< zXw7vKnL2f-UgOi&y)p6K@=_jI_+jLJF?1z|@e8)!sfSjqs4HG@?K*i8Upan5LX@xf zOFHw(TkX2D)$2JND|fpoJj2U6;@S9tV)zd8U4W#%bJMP$?iL>RJCo*KRPr%vGCt?| zmR--URFod7IL!V1sGw_s@nzmClaQS8=HjN3zjV5WL>Zxf*?3;><9{M$KYDE710(UH z`?CHe_=)@r;p)Gi7uV~&nmeH@C1NdJ|D5HfsS7HE`i&<&3U6O2l;x^~4>c0tbn@rR zo7~>m|4-P(;`ch&)vQO-N|3g5!U|ta#b;*76`!NcON$wQ$y6Ti|VjTJJ36m_eB|Ipz8LpCq*$u!Auc zpDo%8myC?HLq?mfGpH34Cc>kwLk4rWN)=H=TTzef8+TBHINFI-h=51EL$=9~M?b>e zyzzctp$tsnD9KjIUhGC+fr-2jG0fOX3HKLExr0eG?=7k_(YE#tomRw+6?d1WgG_fg z&#zxUY}Y35d3w>Vp||oUL#SPq2;*)v+3eIDf$*LWQ^SZ_00-C|FJ-0^5T50;1gy8J z;`;(FO9QFaoX$Ypg-&?|*vbq#^c?1tsjew|9D$`0$8Q7d`u3Dq^y< zocZFAMG<^#+}~__HGgB1Era23dE{_+5#@u8eN-0?H-)V#JcV8oE>)baE5!SB{)2cf zuyt4301AG}2rj}Uce&C}{AuI}GGOe)y?rt_MinbzD8!Zf9?&nKMu3#DEo6gA-aQMS z!2*KE4hb^l49jKg?R<3eG+65Cx+w1z_~9ImgI}|g9#Ijg%T=%$i`D`98VZgH3czzF z931{t#7aNX*~j)HIz+Btg{?xofOG34Em1vW6oT#qjY`3+?eMMK!uA{LxqxeaVDK48 zbvH+%@e&;MV#)Q3Wa4c#j)7ab4EejRLs~765fHgt<)ym^fOTMYqpENWtX10)keAvc zqdas+Tv?~p<5$MF&SY$jgd0&jWi)yvRsiv-h|zP3ye`2ZA|BTSYIT6QjbZTb<%1hv zb~qSbiw0p#!v_hDe$lA`m!U&GCy0=-wp^41Gd)0OcfD$ymwuL(Z4`$HkWek5UFpc| z!C_eD8Bx-lCxtAhG^%ly8+4y3QYFSo6L5x-4C~psL@0(ZJ!U{2rbw%dSrhqOWOf=6 zo3&+9sZ<~(jD=nN&FBP~`$Hpxc#D1=kwZ!={~j2vGV>oF(?NODn~kV__A)9NbSfDo z2;k)!bO7|t{Aa-?otgrjU!;bDHQXx`T-~iYoYm=t9^vg*(pnkDP*JMNv3s9Lcy@xI zM3iWoX^ke$;xVw-W0YxqE1V>$%gV}$@X@LdO;%MwPljxubV8;H3yCFMdqI;7M}wX} znGgRKZt^N*V}Q6n(0j#o2eY-V*5j8>Po$Wht?nErXxFO&fsfB9XEU;cT{XyC7NB*_ z7W%;5s_>sj%><8v21azKY-{ZPlR=;481Jnd<1g^lr@^}~pM?L&U?d*;bo973NR4vt z%+RQBL!D8w)C+}?@62s=KHCo5Ip>b#$Q7x&9n4wTy-{^nr->Rn&_0@gWA%6{Pb`1UGDuO<4BqW zy3tMvX`l5r&n4-(#&vc?gE_1Oz9*7HvfoCh{6bA(_|De9$W_y&0tS#F4S2B0^f0`& zDJ?CCIGj8lmu2naQNx*~FiXG4+iSx&IG6>4y9j^@bj%&>DvsC!JfQ)l2F_(^822i?oi+M zq}j@eSe#5)|B}wC25dbWJEjt%C-*EE%kIe$gts)^JkwK(YT(Sj;R&K}ZgV?8Jz9I- z6g~>JYAmOjqUF1!fz!8IlTt7=>;9BsW073u)4UutCoMA~^QJ+X$w4dZ5w147vav4t zX`d*zQ=YqWk6iR>vW&h&zdbQ&3-(TMgIJWiQ<0k}Zi_4>!#D7=qcEI|_xmOUy zOeH3qf7E~38XXE9Ec@G>y_ZQinTj*6U?h)EJoO9etLY8V6Qlss#kGMA^ysJ*387^` zs`nJ;mK|`L-`c>*ZJS?bc&T$NJh#1Tm)Yg1+*V z%u%nS?OU3C@uB_|RMWa(Fs;@4d~ihAX7^Xs{LDE^k$fTR!qFwpcfI1Y8>z8*TW?&~ zybZc`5?wJrikbBDl!6Z<=8AB63(1mgYn=XTHj1~1{{^jl6j0AwaJEAm#hIK_t3{$A zR_cfml*<<;VVKlu^Q6A8x&`&!>)(uwj;LQBb-4r$0&>;QHqS85PJLo^g~sB(GxV-z z8w_T`oZ$mLsFVr&U|BY~;nM(2NU+ztP@p+n4>@^OS>Uea9wt!odh>NCsM1uTqjC@S1Ns1uE3NEO0 zOTTteZMBU(1R0-?2A)e02#78tl=&;mri8XX9>eVP8yr}0id-paCulWu*Nyd+i()54 zxx~N;!!1R{6TW7}0g>eW#bx{jc_(6ceYEK6rjw4&R$i{#J`aoX{x1FepAlZoKYsn< z82$6jCa$60jXMhL58jBh6`+;7_?H`zou$fsvSNw* z>^U9MOgw=jTGOc>4iiU0^Q!Q{vD&kZ|r-gw$h~FMFZhai}OJE=~QW;;YIW0+n7#_^k;DU}Hg#^Z# zB@Ol>B*L#JUz?-#=aBu&v(|OQks#TS`)LQk-EfK?5Kv8X8eJwx1^_f6!iC!A+ZH%c zkd`)rgd-iM0K(oXKQ*VatrDn7dVx(MO<}0@-HIFj>swMKH2=qk^{rTPA%jrLJu2d_ zGXi0*WjF(7b~IG>q4%n6`nED<@P!VuvFZ0EL1H_ci!#V*=(%OCZQG>G2iZU+V@#D} zLRo|4skh>8!ny=m??YJH)BrmdI*QJMIQ?5$Jsj>y_qsGd{<)bQYv^LFXVH{ z00Mx>qKppOe~efz<(m#*&?HiBe1X}Vo9xP58-#f+UP&m&A1cU6b+kD%C` zVYd9wx%~x3G`BKsGx%+7*ywkeje!Z&sllW&!1MjJbVYF4_GDRhZ#Axoxi7PS8p_;; z0ol~TMv5!woOL}wH*aulB=3R)1skpo7Z@p>!H(bsqP_ke|IY3WVqoh-@`Ve8*4$lO zOBLv$fJ`>_bQ+|3L7-IpXKc@hr7=zb=O@g!Dq6%3-pc3f#5S!QtdaLF#F*n;PKStY zS+O#-!8UBk{s#vU`WLg#fgG33JfHLkX?PS1URR3~6^V7zgw~at1+i}rLtg>dRsnrj zgbahlN|QqglOea}rY&yLc}3j5YkA83W1Izgaz-#JG;@{Q!?#3IOgV` z05I<0MZQQwDAGF%1w?q->)&d6N)*5&4A%E*NK zv6i@q%Cenl;5Q$gf7koI==^2;3{zL7mmJ=FPS3_eWqnCeFG{BcyC0h5(=Q6G)SsTD zmD?+nxfmB~Ba?r4Zq6Ggurm|@a#BuQ--M&#dD<2YQNO=z)=$v|VNYqq+9-XN(kM=-x$!g{CSeD$BTmR&l_`Ur< z;>Y8UR|Gg2FA|9D&mhfZXV^m4I7oC?+ay>ppGJrFYH1s#LeOE7JRAi5WoZ@}e1JcW zNKpJRp+UX10Xo_9`;q^_g>35RQ%|>f{}1`4l>)n?)y~#y$NBwtV~p3I(Hi_v$n#3I zt=H;d9k@B%M)bd?9AsC-CUw`uX9sQ8Jqov&Tx&3opM!n|97vG3%+`<$)4c|P5o>ppdxcfHVyoUC$Tp260C^ttk^ z#K#;G`0-S=ly`S)fC@goK)yU0C0st!z9zDNmo0o3eP$;b`*p!Xj9onO2)Qw9vY$>l z(~Z~EUHqOXHk7h!zcv2#_m(@`{ic7nr5wFqe+J8YtiO^#SU#?`FTf|Ky(<2=g2P!n zccQ2W%B|jpslEaI8gV7*KbVmHMt&bnK8=#Q)lE#dl=l6#6ZGbvBRd`eE`BTQU(c$w z)cbcl;PHET*RDc;W_u>$supcusK)$HKxn&b&Krl$cF~fA-a?9B12#bm4z93-qNyRU znsQenx5qNLVygl6`${`oFSM|9ZVfQ12Hpe)HWa197jb(5vGy|;3S6p_3s4;#nE;?0 zeh7q{+V!`v?ZWU@v!V(qZc9^EFTTn~a} z1q;~?sMHF}L6(`ZSZ{$&AYs7o;REpEoAico7}Q*-B+lSp=;4O`7_^aFi6SRdxy-7X zo>v-E1?n}A&95^Fky9C2Wk*w3$Ht7cjE?%*8b!o;)pjAQ%tF+z%(GhA%Zo#aV+yc) z!)WY#6z&@~^)aJ|4iXrRFUGNILXt@h7&TOl^JqlT3K3m>mMf64fjbImwLWOOlQm z-7Cz;F(~;g4q3>{uA_GW={7EBaG5PWz`DQ*!VHRYLDs_D9tB7h@iT;Tl|}R#x5;EO zTETD_`4HHQOTGZi0ZYg0hp@?JbSw*N+~u%txLUQr9o6TMTu3poI}1f>;(#i))_&xl z>|_kFFPWX0*!tK+D8=W!D|}}qU7nU=;*qZ;R@Ciih}4WBI#Bko*OMZ;dW}<)f8Mi@ zO)EudqsE}O<-4bM+q<46+b|ue#B@7byQv|&YnO=~=-Pzs-}`P6Ur41SbFyS;Y99xI zi~k2`Ix+7d2lKP>;AXl*GeI{b-}Oid9S6$UZr{oJjmO~qJDvInq|_#M=~TxauzQ~JChh}Jvv03wqzIYf4wxpRD9j* zqW#B9nGZZLgec5s?2Tw=0@(p=SB5>q!IIo-YcGroSXkmKbX_lH-L?z92?;(7%51Xz zh;W>y{+k>kyuh+n0e_8OP85(W{+JT4Zkd_^1Q^o+cMMv{f^ll4-!sh%LPl>arH$H; z)66omfX^E>8pG-JK$2OfG^azR!idTAFZ1h4+W%p)8(wmiqxlDsQnhH0=1)HcDM&Pw zpBsiKE@QvT_*8SIA{F*o`~7*flUPx3Qn>@Sy4?VX`YrZnP0dVSMA34@18XMgmC8#Z za?Q(08wZ-IUx5I*01o^o#}kL2i%l9_Dv3}2smt*cI0^&=)a2-5!NfE6-$w)hTM?ZZ ztCML3NhZsH)fcz8+aVS@Kib&ZRkQ4&%%dr?$$PAP05_xZZ=E8lX)u2Ebcl4~d!#SU zOj2eh7o;q%JqA9YO@Lo-o1BiO?AczoIPhe(~)(Bn)?gAroTHHJ#I8eqU5Nq2VkV4Vd=H{xi zSer44NA*COhIW$EfOBNyL24@+QOek>2|RvVV>0;lRf4{x(4WG=)G}L)v73|fRz+xQ zEfvZ+@=->z2=5hhQKUFA{G$J6*k( zq_2;{bT4s9-`R}q@VnxhUqy-(w8w#e&?q}FDdXAIC~Hkjgd&K{nqWDu=RnV9UNS9) zQ022g45*xaxfQ^sJ@C|!IhgK);YYx=b^B9#gialMR!cm zp>=>UT*0=H-hqoI8DJUs@WH}Hf<%s<=EC9bT$odkhK3^v(6pm`K+O+@jNwim+|+UL z2sy!`U{E`)ZrOT<8G#tP62xk`z{U63Y<>eXk43C90zi)@xThvcsdFglE*!LnzPxh; z+(O`^z;^&AI!HXt^V{fI2y?rqL1HsZ5h*okgKd7{=mLL-kEC+Xy9(pc1WJA(Y`i;T zaps{bD!McEIx}}3^2-)hpovBbaZ*CkgnXsciO28&<5EK-=^8^bPDG6RyLvqv^_BkU zVs+y`_m=hT@*?#ZcaJXTxcg@;2M5`U0|_|;#id~Dh)%CK2t$sMx#-G-1cRUqr;t$) zH--blTcLSc}j!zy=L~Hq-oVIyx3Lniu4hqgNy*E92;mgxo%?Y^=l@8|V5-gaLUQ)y;#y z{)>(5l?dj0zpYfsDIf?mtUyH<%fT<8Os;E=Z2#=QSZ39YNWjM78|)+1rO+Gt%;>YAN4;!b8o<{=jE+chJS5izpj` z0yLHJWhkYo*a|B50?0use9>L>?lK_qP+K-b-k4W2#NC7m`H$tQ`@`;IF9F9tYH_lM z>wU0_8%8)Nu%uc_hXb&j@a)CwGm2l_aP&K5p_it znv-YfWi_B(YN!w7@!WTW>4z2(xavsHM64u&XZsCyxK|?X2|z|1OoD5(mDq`!*#e%~ z(}7~Yi~GP|!0iI(Q1pOaJHU3`#(-2U3XdQ{WBK7K9F3KA4zTQizZn57Fuzd8i z_2yy!&PTJuGF*h`znFG^Cz`;$t8aqS+Jcy-*ELaFK@&j8+iF-cOmR?3fnA+o zkIMXoFWak0FpkW7-m_5hkIrhkxm(z3icQBH-eOP`A7=+;`z1QA?6YHhF*!K)|vC;`&CveRR~iSV4sD_c1o(`~CQFj*?a{5?>-76+*b1Sdcsq&8Bi z)RB2XmIbe%w&MnAtx0f=oRCjVrc&7qGK7wog7ZT0a1&qD*%>}H*z$!8+t$u|+%pdN zg7Z`Tn;@zQ!i1|Ee<1uQCghL(I3;0tR2d|7=h#4#-(Lx=>)?NlPT?$x>;-~|p#?dq z6L?W+Q(lphrn$%%qg?1JoxC+OXUrqSdP-(tzcM=hZjY{+yN@_I=KVx7*>qn%Znkq2 zn$xC3T+<9SofOtYA4W--6f z=YP!`3a2i&vmU(kvE3>@6Jtg-@~aL_gnjYq@_2ILv*NJcfx&@B^U@F(>7cl}473Ma~*U1wWgEve~H zo&Q>*@St;8zz=g>?|95Rwx7n#cgJT|;=XzWulaKH9Oj}hq(?yLAYG+;{;Ud7&&1k6 z*E{zEk9#fbw^W9Zx~SgnZ7du9GyR5HM{%8CM7pJ_;_O71GkWp!bD{++(^gGiaFcB@ zL7v2l#tnS19>5LqR+~qmhKeKM0|C@yMbe0yz_bM>o^*0SNUw^|| z_I;B#5wadHI$klyo3=?g-(zaMLX+UaP^7$p2ORO+HS*Xz@Qx*!PFU?l+S9b#_w3g0 z*xbpT$5;Nn9@q=g_kKH&+7>yVb?qmrSaIwc8a2C@oqSo@aXTDV>bp4(Afwa1AWM6( zVd9P8oKO0!mAJm_W<+e9y_$IQ@`;z1a(1I~P-=%yf|W!JmHyvjD+eFQ{dp6+mM{M4 zOZGxf?~CAu?IiDia=Z4YcYZUn%c}8jpJbu-0H*_lyw65=T$pC=0rrkc(P%twqSx7d z>>04iPQS7Dm$_AI``F2738aaq%R`dZQ10Qve`oj&%H{xs!POb4I^@3wWGv<$8DzriT995)h^P3=+QyRv=kqUy4 zil7W?o2oPlr%q(A3vc??vgHdDyya`Yu^l@b^9oEeax5%KJ&J>XpTeZ*E}YB47%2&N zxjcU^ECQ+zdS-VOSX;a5$uh+UZ+d0wZ8Q_q8xx{d>zF;mz@4||h+KF2*|8z{M(^QW zu~&(I@dx19e7L24K$jHP%&!al+m}Ssz9Nuwq!|#W0jpjG*xM8-{SFqZvVAJMqHyJ{l|0qN;FSH!$Q2o{e*kF?}o7gl` zE#V@CE@pCbY2X2Dc{>5jl*iNVi z$F>ld5vPILv^ek8l=!GSq73S>cZBWTf^-(FN-nOM7JweKF?dexS5hU%z1X1wOoBo| zI3VyEuAD_{sxf|7Rp4DxRC2m%ri5ID75H#M1u`Et1{)^9`Mob>*pf*+_DL7A-qpL3 z3jx(P9M>``^nzuW4cpar3MvBRo)e}khhyw2ECqWsT7eBl=N z6oTg;GIrzg^nRz<^n)(OAbXRrM2IMNuRn++zQdTbbB_o$i0a(y)q~G&md3!}l+rZs zJPQRnWy(26h;oI+4M(OA*kr0cASd9U`QKGH5-8%&Z5D;K^ITWuGWctRuSiKYRl1Dc zC)Tii5`PG>ed?Kr{-Wt9J0&A~FidB5*|Y1X@bZ0c9Z7eO3NL;>VM0wVKMqsnq=r_M zxO^z~I2jRg=b3jp*CeD*{_hs>C^0#w^X;3ocmG5o>i>`~+jl*O$ zh|0;LboYMr3i)21$71gxyX6n!z&lN&2h|KgE|4W5ZzoLJnQ(+wFmJ83Eq)b&dQ5ws zO=y2=ANMYh8NaH0{fbL7%co&G&r{==5K{>LzG@bd}jRcKxNBiUJ2{ck@Uf9Opt*4t83?L?{xBSNP&W|SZ`84n zJQ)Z#S|unYZzbx!%0#0AWeXO3OT?pUnz}#>&f8>cg5WH$Sw!~l)wQzW> z-TK_+>Ja>TB6wfD6SXrrRNtJ*dMaC-v*o;4TRT|GFn zh_M-dt&)^ItJB{z0~o7@FY6HWnA7f7dqqS08F#d0th`TgH#-SRN3T1f9w%QxOA7wd z^w%uey)j6n!h@@>P``$n!Ec)`O-) zZ8GPv`Vww4#U^63yqTup1dEXol?bxNQ@GfGh}5FB(pr@$)@LqOSct=PxxDZHJ!S$M zy#Zc<7XfIPBCPGaX}#AfU~4sXw=F<73u~^<%`?5^nHTWt`rQ&q|Cu*!-|s!OXeUQT#Zj0f)zMjA zi_@N|WoX0gB`=y1ZjC0OBidBbRsai2VF4B<0+b_QwD;QJ&fw7;)I8WQsGs!bJTKU@GP;NUy3d3zwf5Qc4ExusQUQ!_3Y zr+v`82fIwbDEo@OZJu!9qI-qa>heA=y{coyHcbQJ?Xw5K5aTH`+%;bq^l&Ms-D zMGRg@_KtQ8K%U?xCz+D`+hrj&T8d;2w<0%S5AxmI3F-l=-y>px&Gv`Jwdd3}^~80t zP2{TeP8+5;*0>T3yx_^&EmueMORJb=bp$qHg{Kv|FuhT!Hjg(>32S1^8{VqDYxW{d zTfi|rk|37Ka>SnRkzq5R>y&BX>#JoQwQ`ML?Gcb3BV^sFtM#;*mz@oRWZ2bdZMC0d zsD@rfHaZeWTn*r~Zu5zLTXpbsKG*)H6HeVkqk=b$aT5~2wN?Y5S7ik_Ir19DF)M=5R^v)i^YzDQUoCHe=U&6} zyyp+ojqtVRzk+~oC(d|9y6D)Y-^*zN6!V_%U`YIt_fbIjJKG7WM(1{WebM&iJ{H~x z&ffR`ju}Q-yIi)nIzyDxx!=miU!Te%GL`I*d@$V|)O@<}fiavqg@66w8}IQ=&^>FX z^#$fEE1E>wgSN{V`n0{XK?@WdG7H317TKzT(3HTokAGqeJE0UU#cj!FQ-bcNS%B$i z`DGU~6f8SR_}lf)+(32>W|>RP{s$TN2L}3(8C?E7&?=4ajELVtH(s*Oaa}PskPcQi zOfZe|%kQ5C>6L`+nDvYP%Qv`C7aDmk`GMH#)--!b-J5Nb+7PG`g!)I{+au3N59W01=c`57szVuU{<;wAgs%+tF7|aoY_3RFGgmA(=bGga&b6rdJ z&+{nf$02w(^cUP+x$FNsFqp^2-a`thN%gXcq3_T4Wv*&*%&)5Ei}=4AL$&A5Im?Op z$_ZWnQyPg!dwN{fA{#@wd|KOTeiX+pL_Y70d(@?n3rIrARFxa zVzijpc;%bNWKyQpi5rT);%*Gtvrjx&OV7FWt=*(NV5r>J(=2F7%ubraHSY17hNNY(UK&<5o%9 zEL41IYpaK!rT-?V>CWfdB7Gg9XPe24bp|Rh!Aj60PZm5@B^>0#LnioT_(tUUYxEp@ zuvzO^K;}1VAzkhRla`*8g3q(5(+Ii|_1i~Hz!Yy#5EC8CIgL%>c~*jXsN+ZKSByX|qFl3E zzhEemQOBv(4N^?Q5w4%cSvt}9|9PJxN*XD3pMNxbNruc0;#x9ZTn`EjC)bfyrfIk+ zVJ@0_uO=i`a^^_5UqaZCCk`zXM1xq*-p>Y8{7~wv)!s8q+~%p*!P2kB&pK5B>imqQ z3>qyo6IDtb6=uA)4SSpVN>PYLkHUz#Qg)B!fiPC+pdDnu`{#$=+d{kfp?%mNrzjf* z2Ini-pV%dyyb!W=ucB0TkpgNTZh7cmGBc((sMp57bsAFxV)f=(SGOKNIdL1-1%FKb zLwU+2l>By1|7u87{*Wj@u z@W@yP`WV0E;iU1$FTYV!Pm5*$=3YB~4~^!{uAq>YpLB%U3{aNqvA_WP=VIw@x7$b& zx*(P1E4lZOamx@nZ29$?Z-Ak48ZTm(zh~WVlC#JrhN*ha_aVbJy0Z)z7`oeD7Rsg;(D_Js^Kz%EOAf1c4uTftQM3r8=LVf{Pq; z-?$bcO&1|Sp_5ou5o}pg!;O5dRxO~m)l3IxUdY5Wxdc&>xj8>5nw$ zAUOpxxbw(7VW=BlPe<0}Z29cP{q7iwg@v(X)fos`fHo!*QS$DL@dc;bH_42YfAK6D z$v3(=!@LT=2pb-Cne`>Dq5<>MTh^UQnbd&zVH-ZQ%96+{(wS4xR#bIVGQO;RZ~J() zY3`;`7M4s!@M$?a6vL1R(9IM)_9=s9KhQk?M6J#;ED3CC12f0;a9?}q@6I_eF66L! z$(y6`s0#BiWs@%A20Qp2m6JcC*9up^%IioBOIUv)G9R5xg8~4SMY`SLMH!DmQ5TSql zp#x4C+IF1L3_!W6gqL=)xllA?cDI(73nRx9U&f;QDHj6 zfe%5WC=f~5$U)qa@)pxV3#!>>=P$WIL-cS;Bt#|5 zqer17gIIce=30Q@h_;3=s(vx=+3u}cZ=V!aMp(;6X&JVv0zoljNtL5FG7Actyhx4e znxdJvEn4eOD&{pdkzG;@JyOm8r~8>+Igb9Pw;>=s!@|yKyt!2ng53-~Cx?fDEh;?o z-q&YNXdX{`ivCG9^32g*YyUg8Bs5NbLy$MB-H&9tGo8k45kmROQQ!}I$~a0>Tg=*| zW2O1_FC)Y$#Se)sr5aRx_JZ|Bflww?^RDQP$!2Z4CEl}RsREpxNKboj7u?n~f!@5h zS~jLy$F5VZNnGx(zs#?j&K@Ibif?)wIeRQ#8itw>^a};LR9$J9o}GVwvM}_uY#uHN zCeO{&@|g@Y&w3DW-)(rC>>{#@DEmFB2}*VFvK_zeRCd|Hcs|pAd2-w^J(2jZu+Vm< zBBBM&AG^8IV+UoYUMpv^7Qag^bn52eiOYjxOCWb(JSqvtpfRt3rmx040ni|Qz+hK^4=5?@3qI*KS1 zC}FvDQ`x&?5+!J6sJ~G@HS=94;6wjF!JcfZmSJ`t#IQQ4)iuC;)h6;RR*(Xx4sLmy zPL<&S7vF%ldMsqZfv~Okx-lA%&&u4I(zUvPG`oDy)~EV*1Uc2kVgFs|L(?J$bUAZ_ z{G78|l%aUPYPyG}hy$8^KaMWD?eIY4gm>k zjWA%po1xdC?n_H$N`UE?#v2-Jp~YCMTzN7?zG%=0TTi>>q;;|fm28|aHKV&%~x z!t%QMeOTIHdaHHbe&gDez-I9K;;febs-HY&)xj#W%aB|4?Rx!zB7AMKJ3B6UAj%4< zl-t>61NP3DVD@aC*>fo}s~0*kZLHcN-Lrv7=)T+F*ik(6!ltE)CD%NWB-Rfro_gA8f816ABVELLV#gt)I$}k!RA}G|@L)m1RUkz|{v1Gj*{5F+?nP>IY<_ zWj5%xuMjfyeh8e2JpnO(mfwcfk6EMDVnM=i(OCns@}z0=?iaadORD2VY^;>VHC#jKJ&S{6@Uxs8k2!M)I<$(=UV6 zX3sCC)s@7l%NDvF?fQmHwrNdtiT6xRuMZVE?LR&ByAQ-+(HaEYd1m^5SZ8Uz) zQgd`faDmQU5KQLx%SPF4Ymgax`R-0kkoSB^h^!q`xs08i@ji#f)+~M&C>=$r=+ozp z16I(?ZWklftFvJHsQWJ!*D~**biY~Ghn831N}yeu#NF1Cf8B8)OrnJmuYoUCz3J(k zZ1AX^=Od~S3%yPxx>w&1)x;wGW;W5tSfA=@=*| z_9rSJ4ZHWbU12X95gdQ)WV8aJshzeyfT~B%0?ZGI?qK&*!66UOWwz4gdt#L`Hmyg7 z5kKq-fc-BJyi*V(l7OsMp)Wkz5|aQvRr}pk_h?V(%xN1Q?veyHteO`-3xqR8uxi~B z8Rs0Jl@Dm?lQuS1I|nH^xDzWcVF5T9(mPSmMIS;;6FLQhkpV%&UzV4zrqgxuh?e%) z7-*1zOlooE{cFq}ux>EG;TegP~9rv;LT;#4ppwj?vSwQ2J8M&N6C+=1O8MBYf{THW2FshXGpM7k$UPRQuzIn;4Dd!l z+B&01V4*$Yto)Rn_4gVR=`haZ|DHo~psCW4JJZLNOr%9BZDSKsGt4 z@r+t%#YDK1TJy7$r|L6j3gHu>9|miT)t#D=`d(RNc;qWYO%`ZMZTHqL0KzeXgLH4N zdJy{_O#{W!jN|%5NzI;Aqo*dTs3GN7X*&NEW$izX!a4SC)#2WjtOv8Q7|$ATy#F;Y zePLQr?9%T3b}}sxNVevg6BIIduQOgIgDnq!0N~rf3>_FDCY?f_cXgOU_Ft9 z+nLY-wcU}I`YDc>*y1I^jDVI#Q-=cNv9fdaoGKzS;s%Xy{SQRG230#jKCzqZOYo=) zz(NdQw-vK0l9NO`5ru~fC#8v#=MsvswuYVITsr^-BqGbs?L$tH8ccb6v!DoYSC+0Sdsd0c0DgxlJ^D&+c=10ZEfDO2xoh2pebJ7$t zo+5zm>;2V7*W6(UVY1wf(8Tq9<@dcYGPH`#61v~kX|A^v>YBCE?A+u>CqXj1U>(2+XJKN|XFqnS^HUwrg$e@h3i+K-d!$Mu}y8{&pay zPh%^cAM?dft-2+|r_%JLXT5VL8po-)a$>E`)@t3_V7+yjeBF436Ad?Ay_T@>8JO4a z(Ar_oX7AI6(AXr$C$q`G@j z6IJb$sgL&WU;r>I2=&8@l*m#& zDsazlnc-$Hpgk7w4XZQ!*2)IU3_@V^!btUu+)$lYN&*-1;{ul8Q;*WJZ|jpR@>sx z!5Tfk3T-fMXKdd-WsJYbnrL@;a-b2B(W_NktQmYHu84q0I%G>E zG)~-^rx#zunNPSr(NBFbb#JfYaGkCljLomV66WZaKuYbsfgGHd%=X9(748B38)X54 zwkmAn|Lf^mqnfzd^)M45Bq535?NgKpC6v~KO(wY)MeRo z47E0N-#?~YuYbT1JvzaDCGv7^8V_!xfYz`Swt4%%9+>96ihlIJ$=${Nhj{Vr@5OWM z`KXIw23~0W_{7OH{sf;BHKuzRo49Bbke>L`qaTAKLo=sL=fB1w6&uarZdNyn-12(x zsMVe(W&&nd3L}7pUl)ezfwr*-n%5tLPJt22Rv9>Anz6nQUV}DZH8B`g(gC>)^R}m) z0HBidl*avr=3xGU$6~Lx>RsSQBt1N*JA93Pe3C=lpr6hm4|+BK$DXs2-6fK7@XPrO z2vgepcRZWF zidR%vmE+%05vGR{NCz{`F`C51E;TNQL_zI>6Tcm4i95wvy@CT9$=>69DpTb@rJN#`U#`#Ec16|cq;ef8sxb0p4qw{^Vx~GLups4==}tYP z4`>q~`j7VBQ9zXNbv%a?qE1|Rsp zY+H1T1{KI=^+eYWgv7FlYDT+MHu9a|aLyV9p8Zt_1=HD-t^=kzyi&r=Fdp_$1aR~8 z8Ix6ov(y3)2Vk3#~>*Umk!xIOHwQA zT_Ox9`l$}!xLlWaPHgtwg4(l!gVw`#ZPdrwFV@p%4jf~z|u zyAm|0nRPn@5^@7Ht(m?Yn{k{f!M(AwEf-lmo2M} zpXgI0yb%lE*)gkq6BpCDrw*CQdMRrB9?MD`_=}g`6Mn?a_&nTS6&$B;^VEH4Hp|&U%o-EKOx~`nwzH8)2Bl}affI>!Z7X8Ny6OWL=w#g&QZ~Hw z^pV+K*+`n|DUKw)s6?D+V11C3#biCh|7812zv48xwxiCsnt^BDaNZjltr58IUFUvx&c~c=|Y>a@{Bw6>c5mxMrG1Q zArJr0N$q12wdn+terRfuB)9oC+dV(h_@uMJL3m)p@#_IYz0onq&mTuD%kMZc!O+Lb znQcP1fAnFy^1(OjV8F%;)v^KRM_69j&^@xv6cBvc>LVnc_DzLGQuo9ua<; zqbfs%I)gFQS)igk)P_LjnQc z{Wlwgs~uHcCsR!>L3F(&AFM-*rlV$371p#42NZY7muX-TZO$b53$kdFLHrHm!2eoD z;@nfFw(zC=ILhexR0Ct5xij%6Ca3*zQGin`CD=|i4KufE8*4Agq_ZrRUhcjwge2QSH*hEo-*wQ3u5cs=0% zIUC29!X_p`ob8SZW@d2FN`%9YST214&>oLDeg>v|N1@{sTeh^q%($rzMJM z{*iJbCanq*qqv}NjljwnY7M@;mpk(MOAj4lVZ#A=7p6ofIJ3wQM#bmu(jd&?oVWVR@9-cTjSF_iXFVM&sZ{)^}FyG`@V9b!Y5say3t|=VnO5Mf-Gtp$* zKtVaJ!lK@P0+|l_*)N&=I@d0b+?oo%LwkluyEk5NO(%IRD+Y!GbeXLZOHs~H6af7; z66yZLTIigWN&#q-blPUQF!T%WiM_jg(2&qkiJyDNzE}mN0WWa*i#6rM+vI>fAbF`HB}PJ z_?iG0S59-1dy;b;>xwg@AQ`o$L!Gr&2oL8d!Ela8w#Xh`3v4sv1i72M#S?FRC<2r7;IK>{MJJDi2{WOjF zf4Icc9(6l3nu>~NEh8B8H}{jVixqc>vZL~8?28usnxfPlrd#_3isM-))=oK_+Jyld zzAX$&4LhPuopG5;@DPr0JZMH%vtGuO$e%Kf3v*>R9s3vd%r1BwYZIo912a{oSgw@X zEuU5VMZ(e+ZDywpI7R%1<2M;8WvINfk)yKX1T>{?;8w2}YfU`l@Z}E2iz94=AEtm9 znPez_N}YQe=ucSFA{MyDW}1_I6KTi^LZ^}iETET$m>wm8rxy8*yjB%s+168xZvpgY zr<%m*&S0RHkX68JWo(PyCM(o6?+@xvOBt|5@oz~h@i=BY8dNiYHat&`b~|YW;bs=! zc|;H~<_d#F=b_aM z5-~B5N@?9uKMy)9zhI|TDpEMMpns!B~soqllHWz76 z$oc`--%@@%G-q5I@of73{>;`9(n^gkJW%=5wDQdJHhgxh>!~Tz@g!~GazkN^F*}@~ z{D_P3hSfJ#35*@g6!Q!BepQ_&TiG+-<9nky!Y4~s^e1!d%Jo*KFf;>3+S~TuHwyMv z=C-%*C?4{5XwkD16;L$Q4GSVc22~jJhTBeEkujqYt;S9vBpu|+B{dKMvdN9>v?iKD zDSCT&u>(4NaF-Jqo2zHO{T3+CJMY63W5wR2I|s;Tk>}LC zh%^=I6C=Ly;?zolU!9Ra!$Y(J2!kNZ9m7j??Lf@e>jALY0Rv!g>xbR02PZDJP%xwf z5pw_~OFg|5^Xupm3&`whet!;lZ8Kj&vD^N+BETO6 zhfdO7eeqn7Fp7xXbJcYl`-Z_nU07&$UrL-N1A1t#YsOu`{bFNwDk0Ztsi@z$B1Om%?13IHv zUP7saAhTGYw>i-R@WNKIRr0k~V3`}SF6Bay&aSL(T0?|rQW=B;W_1?$5xjezZXY;v z(%5@h(j8(-!|N`OzH3o(!93vsNh+n=wtWWhiGe0?C9~{ z;`zrB%1WmL@0FC*Mk2TnpZ)XqO%(BPYZ$V+`8@>JXZB@)g{<< z9r&*JD9`5cb#Cmd)lX|xtrn%0mOl#pMD1UmFM2m7|A&!ucy;rSvi9*83D%oIvstq~u1nF5JhAjV4|jh$ zB+;XB;-i0EYt8ub@|q?H;g5jM>|b(gN}Wuy@2kh|1$r)0IO(dxf?oRO$nHIhO{A|6 z?Kdr7_2FM_t2pE$zb)y-Z%qp~FMcIMt#zmw+#{>nwP4%q`(=JtvQ-IEDE(?~L#&RpPfDX2A|d*j*R+M8nA-7HHj%#Gb#H_Bk9Yeodyk!#R~SM+RAcX*A#80A z4#}667C;}oN@5WOm+EqUHvKW0@Y!b{6HPpEsj>2>z|4u2SV67p8_l!YP3~BF`S~B7 ziZZ_8_NlqnvS)w5uG^Od({I|A+NAs658Umr`vqW?ISNGXH50jlIn}2NTs{(p|2+FI z-O{>$#|ZMI-%TWdGS8g11xHz{?1vkCe-S*m5p;SVR6c7MIDP4CU4pn;@KH;CJ#PK# zU&s!dGLYgwPHk>m8IbnL$%dj~#}{iPmwvk~txdWz@y(`*KIelSmx3q760VXv>|ore zsT2G5Oye#sxs-M!f9f76zHwaR|34zjqwhPhl5G{FIq^Qic+m1Y>yX@~jn%*YbV!^( z2>3c~g66~_ zRY_&)x%3uEe8>;oDc=oUV}-KUh(5^NAM84Cb(!;_lC_ubAbak?`29^@Lj%&&rreEz zK2ycSk}By}0l(Ce_C7ZEFU;svnqMg;W=leNdjoOdubh#OnpklU%S)tp?|tQxDf6&@ z|6R(xb1`|&$PaV@R0{o>Xp8GnwE=dq@bs1K+pKdxAjVtnk9NZ|J4%}0n(kcQY-m5b z2u9S&)i>rk1ClOLjyX1o8dtgoiofwHon6(R_x>zc*;YWT{)=2`aHAjgUS%{~;8ZQ% zy>faB`J>yZF>i|PZ`vPh+2{1lKKL^cxPN5CCKijhOU`LOO+VBr!A~St6xfOD&Bp8= zO?VupekAVO#)HlQ<8gSvmJCv2YpsBS%R!5eGm{2>Yz$HpeccU36-PVUOI$?FM|Ov z`PyzH`bU>ZB$BGKGRc!?&srFDEs|&TwA`w*4|4=P_~_?#aT};5jR z>Yp_=#5QD44|}+~yDNMrkvbjGmX2)=S(?FBl+FP#Ssx9$E7s0%gyUVc^7G8tP;%Xj zd3iBLbRj7uQ;W(sETEa<}NJLLON6I6>Yk@)&o-Oh!c%4fYv1s;V9W}cPKa7mD4 zY;qrkkiuC%?c9>M^j@sK#P>E0(m>QQR3b8S8H@l_A=kwd$$+6Ddrb~SSmhRxVJMtv zGlFulW3--dd5HrmJ7^rDLVjGXj0UwpTqvTIpv1QSgM=33Fp!Jrd;k}B<5HDMY!gM-1=)$8O6uH8OZW(Qzgn`@J+!{WM`H5zA?Jr0LZM+AL%^dl zY||eY5+ZmpR00QJ1rQ$ckw(}dFbOZ3@2Us<1&g%GxK7iONB1s~OrX<~#r_NBk`8bF z^>4CcIKf zEdjQ#Q9|rEGX^)=({f9o+;KRMpT1-VfVP`&m2H=r5fkNQ{K~RK;YS2U6Lz&J>fMu} z^6d4Wf%Z`892QN2Y!;fT!&ts1LHnnC|d}v2+8_4u+~15J6Hrq-e!OPN2tL-dA&c#t#8u%>Fs?wEjSf^BiZ$0?$r2Dov9M-X9%j>7EIz@5LQAa9;Rg3*%C!5T_22(s7xCyYR_+y9;IhB|b~woB@{p8o~4G}FKU literal 0 HcmV?d00001 diff --git a/c++/src/algo/blast/unit_tests/api/delta_unit_test.cpp b/c++/src/algo/blast/unit_tests/api/delta_unit_test.cpp index 3490642f..967c2454 100644 --- a/c++/src/algo/blast/unit_tests/api/delta_unit_test.cpp +++ b/c++/src/algo/blast/unit_tests/api/delta_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: delta_unit_test.cpp 498724 2016-04-19 13:36:57Z ivanov $ +/* $Id: delta_unit_test.cpp 507726 2016-07-21 14:42:04Z grichenk $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -284,7 +284,7 @@ BOOST_AUTO_TEST_CASE(TestSingleQuery_CBS) BOOST_REQUIRE(pssm->HasQuery()); BOOST_REQUIRE(pssm->GetQuery().GetSeq().IsSetInst()); BOOST_REQUIRE_EQUAL(pssm->GetQuery().GetSeq().GetFirstId()->GetGi(), - GI_FROM(TIntId, 129295)); + GI_CONST(129295)); // check alignments from sequence search results @@ -292,7 +292,7 @@ BOOST_AUTO_TEST_CASE(TestSingleQuery_CBS) BOOST_REQUIRE_EQUAL( results[0].GetSeqAlign()->Get().front()->GetSeq_id(0).GetGi(), - GI_FROM(TIntId, 129295)); + GI_CONST(129295)); const int kNumExpectedMatchingSeqs = 8; CConstRef sas = results[0].GetSeqAlign(); @@ -545,7 +545,7 @@ BOOST_AUTO_TEST_CASE(TestSingleQuery_NoCBS) BOOST_REQUIRE(pssm->HasQuery()); BOOST_REQUIRE(pssm->GetQuery().GetSeq().IsSetInst()); BOOST_REQUIRE_EQUAL(pssm->GetQuery().GetSeq().GetFirstId()->GetGi(), - GI_FROM(TIntId, 129295)); + GI_CONST(129295)); // check alignments from sequence search results @@ -553,7 +553,7 @@ BOOST_AUTO_TEST_CASE(TestSingleQuery_NoCBS) BOOST_REQUIRE_EQUAL( results[0].GetSeqAlign()->Get().front()->GetSeq_id(0).GetGi(), - GI_FROM(TIntId, 129295)); + GI_CONST(129295)); const int kNumExpectedMatchingSeqs = 5; CConstRef sas = results[0].GetSeqAlign(); @@ -683,7 +683,7 @@ BOOST_AUTO_TEST_CASE(TestMultipleQueries) // verify query id in Seq_aligns BOOST_REQUIRE_EQUAL( results[0].GetSeqAlign()->Get().front()->GetSeq_id(0).GetGi(), - GI_FROM(TIntId, 129295)); + GI_CONST(129295)); BOOST_REQUIRE_EQUAL( results[1].GetSeqAlign()->Get().front()->GetSeq_id(0).GetPir().GetName(), @@ -693,7 +693,7 @@ BOOST_AUTO_TEST_CASE(TestMultipleQueries) // verify query id in PSSMs BOOST_REQUIRE_EQUAL( deltablast.GetPssm(0)->GetQuery().GetSeq().GetFirstId()->GetGi(), - GI_FROM(TIntId, 129295)); + GI_CONST(129295)); BOOST_REQUIRE_EQUAL( deltablast.GetPssm(1)->GetQuery().GetSeq().GetFirstId()->GetPir().GetName(), diff --git a/c++/src/algo/blast/unit_tests/api/hspfilter_besthit_unit_test.cpp b/c++/src/algo/blast/unit_tests/api/hspfilter_besthit_unit_test.cpp index 921361d0..2a842a15 100644 --- a/c++/src/algo/blast/unit_tests/api/hspfilter_besthit_unit_test.cpp +++ b/c++/src/algo/blast/unit_tests/api/hspfilter_besthit_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: hspfilter_besthit_unit_test.cpp 462040 2015-03-16 13:14:29Z vasilche $ +/* $Id: hspfilter_besthit_unit_test.cpp 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -87,7 +87,7 @@ BOOST_AUTO_TEST_CASE(HSPBestHitWriter) BOOST_REQUIRE(writer_info); BOOST_REQUIRE(writer_info->NewFnPtr); BOOST_REQUIRE(writer_info->params); - BlastHSPWriter* writer = BlastHSPWriterNew(&writer_info, &query_info); + BlastHSPWriter* writer = BlastHSPWriterNew(&writer_info, &query_info, NULL); BOOST_REQUIRE(writer_info == NULL); BOOST_REQUIRE(writer); // Following call also frees best_hit_params diff --git a/c++/src/algo/blast/unit_tests/api/hspfilter_culling_unit_test.cpp b/c++/src/algo/blast/unit_tests/api/hspfilter_culling_unit_test.cpp index 36e29034..28bae867 100644 --- a/c++/src/algo/blast/unit_tests/api/hspfilter_culling_unit_test.cpp +++ b/c++/src/algo/blast/unit_tests/api/hspfilter_culling_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: hspfilter_culling_unit_test.cpp 462040 2015-03-16 13:14:29Z vasilche $ +/* $Id: hspfilter_culling_unit_test.cpp 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -88,7 +88,7 @@ BOOST_AUTO_TEST_CASE(HSPCullingWriter) BOOST_REQUIRE(writer_info); BOOST_REQUIRE(writer_info->NewFnPtr); BOOST_REQUIRE(writer_info->params); - BlastHSPWriter* writer = BlastHSPWriterNew(&writer_info, &query_info); + BlastHSPWriter* writer = BlastHSPWriterNew(&writer_info, &query_info, NULL); BOOST_REQUIRE(writer_info == NULL); BOOST_REQUIRE(writer); // Following call also frees culling_params diff --git a/c++/src/algo/blast/unit_tests/api/hspstream_unit_test.cpp b/c++/src/algo/blast/unit_tests/api/hspstream_unit_test.cpp index a98b8529..0b6d80ac 100644 --- a/c++/src/algo/blast/unit_tests/api/hspstream_unit_test.cpp +++ b/c++/src/algo/blast/unit_tests/api/hspstream_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: hspstream_unit_test.cpp 462040 2015-03-16 13:14:29Z vasilche $ +/* $Id: hspstream_unit_test.cpp 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -84,7 +84,7 @@ void testHSPStream(EHSPStreamType stream_type) { BlastHSPWriterInfo * writer_info = BlastHSPCollectorInfoNew(col_params); - BlastHSPWriter* writer = BlastHSPWriterNew(&writer_info, NULL); + BlastHSPWriter* writer = BlastHSPWriterNew(&writer_info, NULL, NULL); BOOST_REQUIRE(writer_info == NULL); BlastHSPStream* hsp_stream = BlastHSPStreamNew(kProgram, ext_options, TRUE, @@ -197,7 +197,7 @@ BOOST_AUTO_TEST_CASE(testMultiSeqHSPCollector) { hit_options, ext_options->compositionBasedStats, scoring_options->gapped_calculation)); - BlastHSPWriter* writer = BlastHSPWriterNew(&writer_info, NULL); + BlastHSPWriter* writer = BlastHSPWriterNew(&writer_info, NULL, NULL); BOOST_REQUIRE(writer_info == NULL); BlastHSPStream* hsp_stream = BlastHSPStreamNew( diff --git a/c++/src/algo/blast/unit_tests/api/linkhsp_unit_test.cpp b/c++/src/algo/blast/unit_tests/api/linkhsp_unit_test.cpp index b321ea24..017c55d6 100644 --- a/c++/src/algo/blast/unit_tests/api/linkhsp_unit_test.cpp +++ b/c++/src/algo/blast/unit_tests/api/linkhsp_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: linkhsp_unit_test.cpp 462040 2015-03-16 13:14:29Z vasilche $ +/* $Id: linkhsp_unit_test.cpp 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -477,7 +477,7 @@ struct LinkHspTestFixture { LookupTableOptions* lookup_options = NULL; BlastSeqLoc* blast_seq_loc = BlastSeqLocNew(NULL, 0, m_QueryInfo->contexts[0].query_length-1); LookupTableOptionsNew(m_ProgramType, &lookup_options); - LookupTableWrapInit(query_blk, lookup_options, query_options, blast_seq_loc, m_ScoreBlk, &lookup_wrap, NULL, NULL); + LookupTableWrapInit(query_blk, lookup_options, query_options, blast_seq_loc, m_ScoreBlk, &lookup_wrap, NULL, NULL, NULL); query_options = BlastQuerySetUpOptionsFree(query_options); BOOST_REQUIRE(query_options == NULL); diff --git a/c++/src/algo/blast/unit_tests/api/magicblast_unit_test.cpp b/c++/src/algo/blast/unit_tests/api/magicblast_unit_test.cpp new file mode 100644 index 00000000..98964308 --- /dev/null +++ b/c++/src/algo/blast/unit_tests/api/magicblast_unit_test.cpp @@ -0,0 +1,447 @@ +/* $Id: magicblast_unit_test.cpp 517506 2016-10-25 17:22:36Z ivanov $ + * =========================================================================== + * + * PUBLIC DOMAIN NOTICE + * National Center for Biotechnology Information + * + * This software/database is a "United States Government Work" under the + * terms of the United States Copyright Act. It was written as part of + * the author's official duties as a United States Government employee and + * thus cannot be copyrighted. This software/database is freely available + * to the public for use. The National Library of Medicine and the U.S. + * Government have not placed any restriction on its use or reproduction. + * + * Although all reasonable efforts have been taken to ensure the accuracy + * and reliability of the software and data, the NLM and the U.S. + * Government do not and cannot warrant the performance or results that + * may be obtained by using this software or data. The NLM and the U.S. + * Government disclaim all warranties, express or implied, including + * warranties of performance, merchantability or fitness for any particular + * purpose. + * + * Please cite the author in any work or product based on this material. + * + * =========================================================================== + * + * Author: Greg Boratyn + * + * Test module for Magic-BLAST API + */ + +#include +#include + +// Serial library includes +#include +#include + +// Object includes +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +// BLAST includes +#include +#include +#include +#include + +using namespace std; +using namespace ncbi; +using namespace ncbi::objects; +using namespace ncbi::blast; + +struct CMagicBlastTestFixture { + + CRef m_OptHandle; + CRef m_Db; + + /// Contains a single Bioseq + CRef m_Queries; + + + CMagicBlastTestFixture() { + m_OptHandle.Reset(new CMagicBlastOptionsHandle); + m_Db.Reset(new CSearchDatabase("data/pombe", + CSearchDatabase::eBlastDbIsNucleotide)); + + m_Queries.Reset(new CBioseq_set); + } + + + ~CMagicBlastTestFixture() { + m_OptHandle.Reset(); + m_Db.Reset(); + m_Queries.Reset(); + } +}; + + +BOOST_FIXTURE_TEST_SUITE(magicblast, CMagicBlastTestFixture) + + +struct SExon +{ + unsigned int prod_start; + unsigned int prod_end; + unsigned int gen_start; + unsigned int gen_end; + + ENa_strand prod_strand; + ENa_strand gen_strand; + string acceptor; + string donor; +}; + +struct SMatch +{ + int score; + unsigned int prod_length; + vector exons; +}; + + +BOOST_AUTO_TEST_CASE(MappingNoPairs) +{ + ifstream istr("data/magicblast_queries.asn"); + BOOST_REQUIRE(istr); + istr >> MSerial_AsnText >> *m_Queries; + + CRef query_factory(new CObjMgrFree_QueryFactory(m_Queries)); + CRef db_adapter(new CLocalDbAdapter(*m_Db)); + CMagicBlast magicblast(query_factory, db_adapter, m_OptHandle); + CRef results = magicblast.Run(); + + const size_t kExpectedNumResults = 5; + BOOST_REQUIRE_EQUAL(results->Get().size(), kExpectedNumResults); + + SExon exon; + vector expected_hits(kExpectedNumResults); + + // expected HSPs + + int results_idx = 0; + // HSP #1 + expected_hits[results_idx].score = 49; + expected_hits[results_idx].prod_length = 49; + + exon.prod_start = 0; + exon.prod_end = 21; + exon.gen_start = 1827220; + exon.gen_end = 1827241; + exon.prod_strand = eNa_strand_minus; + exon.gen_strand = eNa_strand_plus; + exon.acceptor = ""; + exon.donor = "CT"; + expected_hits[results_idx].exons.push_back(exon); + + exon.prod_start = 22; + exon.prod_end = 48; + exon.gen_start = 1827292; + exon.gen_end = 1827318; + exon.prod_strand = eNa_strand_minus; + exon.gen_strand = eNa_strand_plus; + exon.acceptor = "AC"; + exon.donor = ""; + expected_hits[results_idx].exons.push_back(exon); + + // HSP #2 + results_idx++; + expected_hits[results_idx].score = 49; + expected_hits[results_idx].prod_length = 49; + + exon.prod_start = 0; + exon.prod_end = 28; + exon.gen_start = 181290; + exon.gen_end = 181318; + exon.prod_strand = eNa_strand_minus; + exon.gen_strand = eNa_strand_plus; + exon.acceptor = ""; + exon.donor = "CT"; + expected_hits[results_idx].exons.push_back(exon); + + exon.prod_start = 29; + exon.prod_end = 48; + exon.gen_start = 181367; + exon.gen_end = 181386; + exon.prod_strand = eNa_strand_minus; + exon.gen_strand = eNa_strand_plus; + exon.acceptor = "AC"; + exon.donor = ""; + expected_hits[results_idx].exons.push_back(exon); + + // HSP #3 + results_idx++; + expected_hits[results_idx].score = 49; + expected_hits[results_idx].prod_length = 49; + + exon.prod_start = 0; + exon.prod_end = 20; + exon.gen_start = 1033352; + exon.gen_end = 1033372; + exon.prod_strand = eNa_strand_minus; + exon.gen_strand = eNa_strand_plus; + exon.acceptor = ""; + exon.donor = "CT"; + expected_hits[results_idx].exons.push_back(exon); + + exon.prod_start = 21; + exon.prod_end = 48; + exon.gen_start = 1033432; + exon.gen_end = 1033459; + exon.prod_strand = eNa_strand_minus; + exon.gen_strand = eNa_strand_plus; + exon.acceptor = "AC"; + exon.donor = ""; + expected_hits[results_idx].exons.push_back(exon); + + // HSP #4 + results_idx++; + expected_hits[results_idx].score = 33; + expected_hits[results_idx].prod_length = 49; + + exon.prod_start = 0; + exon.prod_end = 32; + exon.gen_start = 1033340; + exon.gen_end = 1033372; + exon.prod_strand = eNa_strand_minus; + exon.gen_strand = eNa_strand_plus; + exon.acceptor = ""; + exon.donor = "CT"; + expected_hits[results_idx].exons.push_back(exon); + + // HSP #5 + results_idx++; + expected_hits[results_idx].score = 49; + expected_hits[results_idx].prod_length = 49; + + exon.prod_start = 0; + exon.prod_end = 23; + exon.gen_start = 89112; + exon.gen_end = 89135; + exon.prod_strand = eNa_strand_minus; + exon.gen_strand = eNa_strand_plus; + exon.acceptor = ""; + exon.donor = "CT"; + expected_hits[results_idx].exons.push_back(exon); + + exon.prod_start = 24; + exon.prod_end = 48; + exon.gen_start = 89420; + exon.gen_end = 89444; + exon.prod_strand = eNa_strand_minus; + exon.gen_strand = eNa_strand_plus; + exon.acceptor = "AC"; + exon.donor = ""; + expected_hits[results_idx].exons.push_back(exon); + + // compare computed HSPs with the expected ones + results_idx = 0; + for (auto it: results->Get()) { + + // we do not expect paired results + BOOST_REQUIRE(it->GetSegs().IsSpliced()); + + int score; + it->GetNamedScore("score", score); + BOOST_REQUIRE_EQUAL(score, expected_hits[results_idx].score); + + const CSpliced_seg& seg = it->GetSegs().GetSpliced(); + BOOST_REQUIRE_EQUAL(seg.GetProduct_length(), + expected_hits[results_idx].prod_length); + + BOOST_REQUIRE_EQUAL(seg.GetExons().size(), + expected_hits[results_idx].exons.size()); + + // compare exon data + auto expected_exon = expected_hits[results_idx].exons.begin(); + for (auto exon: seg.GetExons()) { + + // exon starts and stops + BOOST_REQUIRE_EQUAL(exon->GetProduct_start().GetNucpos(), + expected_exon->prod_start); + + BOOST_REQUIRE_EQUAL(exon->GetProduct_end().GetNucpos(), + expected_exon->prod_end); + + BOOST_REQUIRE_EQUAL(exon->GetGenomic_start(), + expected_exon->gen_start); + + BOOST_REQUIRE_EQUAL(exon->GetGenomic_end(), + expected_exon->gen_end); + + // strands + BOOST_REQUIRE_EQUAL(exon->GetProduct_strand(), + expected_exon->prod_strand); + + BOOST_REQUIRE_EQUAL(exon->GetGenomic_strand(), + expected_exon->gen_strand); + + // splice signals + if (!expected_exon->acceptor.empty()) { + BOOST_REQUIRE(exon->CanGetAcceptor_before_exon()); + BOOST_REQUIRE_EQUAL(exon->GetAcceptor_before_exon().GetBases(), + expected_exon->acceptor); + } + + if (!expected_exon->donor.empty()) { + BOOST_REQUIRE(exon->CanGetDonor_after_exon()); + BOOST_REQUIRE_EQUAL(exon->GetDonor_after_exon().GetBases(), + expected_exon->donor); + } + + ++expected_exon; + } + results_idx++; + } +} + + +BOOST_AUTO_TEST_CASE(MappingPaired) +{ + ifstream istr("data/magicblast_paired.asn"); + BOOST_REQUIRE(istr); + istr >> MSerial_AsnText >> *m_Queries; + + bool queries_paired = false; + auto q = m_Queries->GetSeq_set().begin(); + BOOST_REQUIRE(q != m_Queries->GetSeq_set().end()); + const CBioseq& bioseq = (*q)->GetSeq(); + BOOST_REQUIRE(bioseq.CanGetDescr()); + for (auto it: bioseq.GetDescr().Get()) { + if (it->IsUser()) { + const CUser_object& obj = it->GetUser(); + if (obj.GetType().IsStr() && obj.GetType().GetStr() == "Mapping") { + queries_paired = obj.HasField("has_pair"); + } + } + } + BOOST_REQUIRE(queries_paired); + + CRef query_factory(new CObjMgrFree_QueryFactory(m_Queries)); + CRef db_adapter(new CLocalDbAdapter(*m_Db)); + + m_OptHandle->SetPaired(true); + CMagicBlast magicblast(query_factory, db_adapter, m_OptHandle); + CRef results = magicblast.Run(); + + const size_t kExpectedNumResults = 1; + BOOST_REQUIRE_EQUAL(results->Get().size(), kExpectedNumResults); + + SExon exon; + vector expected_hits(2 * kExpectedNumResults); + + // expected HSPs + + int results_idx = 0; + // HSP #1 + expected_hits[results_idx].score = 68; + expected_hits[results_idx].prod_length = 75; + + exon.prod_start = 7; + exon.prod_end = 74; + exon.gen_start = 2443260; + exon.gen_end = 2443327; + exon.prod_strand = eNa_strand_plus; + exon.gen_strand = eNa_strand_plus; + exon.acceptor = "CT"; + exon.donor = ""; + expected_hits[results_idx].exons.push_back(exon); + + // HSP #2 + results_idx++; + expected_hits[results_idx].score = 71; + expected_hits[results_idx].prod_length = 75; + + exon.prod_start = 0; + exon.prod_end = 70; + exon.gen_start = 2443337; + exon.gen_end = 2443407; + exon.prod_strand = eNa_strand_minus; + exon.gen_strand = eNa_strand_plus; + exon.acceptor = ""; + exon.donor = "CA"; + expected_hits[results_idx].exons.push_back(exon); + + // compare computed HSPs with the expected ones + results_idx = 0; + for (auto seg: results->Get()) { + + // we do not expect paired results + BOOST_REQUIRE(seg->GetSegs().IsDisc()); + BOOST_REQUIRE_EQUAL(seg->GetSegs().GetDisc().Get().size(), 2u); + + for (auto it: seg->GetSegs().GetDisc().Get()) { + + BOOST_REQUIRE(it->GetSegs().IsSpliced()); + + int score; + it->GetNamedScore("score", score); + BOOST_REQUIRE_EQUAL(score, expected_hits[results_idx].score); + + + const CSpliced_seg& seg = it->GetSegs().GetSpliced(); + BOOST_REQUIRE_EQUAL(seg.GetProduct_length(), + expected_hits[results_idx].prod_length); + + BOOST_REQUIRE_EQUAL(seg.GetExons().size(), + expected_hits[results_idx].exons.size()); + + // compare exon data + auto expected_exon = expected_hits[results_idx].exons.begin(); + for (auto exon: seg.GetExons()) { + + // exon starts and stops + BOOST_REQUIRE_EQUAL(exon->GetProduct_start().GetNucpos(), + expected_exon->prod_start); + + BOOST_REQUIRE_EQUAL(exon->GetProduct_end().GetNucpos(), + expected_exon->prod_end); + + BOOST_REQUIRE_EQUAL(exon->GetGenomic_start(), + expected_exon->gen_start); + + BOOST_REQUIRE_EQUAL(exon->GetGenomic_end(), + expected_exon->gen_end); + + // strands + BOOST_REQUIRE_EQUAL(exon->GetProduct_strand(), + expected_exon->prod_strand); + + BOOST_REQUIRE_EQUAL(exon->GetGenomic_strand(), + expected_exon->gen_strand); + + // splice signals + if (!expected_exon->acceptor.empty()) { + BOOST_REQUIRE(exon->CanGetAcceptor_before_exon()); + BOOST_REQUIRE_EQUAL( + exon->GetAcceptor_before_exon().GetBases(), + expected_exon->acceptor); + } + + if (!expected_exon->donor.empty()) { + BOOST_REQUIRE(exon->CanGetDonor_after_exon()); + BOOST_REQUIRE_EQUAL(exon->GetDonor_after_exon().GetBases(), + expected_exon->donor); + } + + ++expected_exon; + } + results_idx++; + } + } +} + + +BOOST_AUTO_TEST_SUITE_END() + diff --git a/c++/src/algo/blast/unit_tests/api/magicblast_unit_test.ini b/c++/src/algo/blast/unit_tests/api/magicblast_unit_test.ini new file mode 100644 index 00000000..7bd19f9b --- /dev/null +++ b/c++/src/algo/blast/unit_tests/api/magicblast_unit_test.ini @@ -0,0 +1,3 @@ +; $Id: magicblast_unit_test.ini 517501 2016-10-25 17:21:06Z ivanov $ +[UNITTESTS_DISABLE] +GLOBAL = OS_Solaris | PLATFORM_Bits32 diff --git a/c++/src/algo/blast/unit_tests/api/ntlookup_unit_test.cpp b/c++/src/algo/blast/unit_tests/api/ntlookup_unit_test.cpp index f98033d7..fc4ea035 100644 --- a/c++/src/algo/blast/unit_tests/api/ntlookup_unit_test.cpp +++ b/c++/src/algo/blast/unit_tests/api/ntlookup_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: ntlookup_unit_test.cpp 462040 2015-03-16 13:14:29Z vasilche $ +/* $Id: ntlookup_unit_test.cpp 506102 2016-07-01 15:48:06Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -55,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -187,7 +188,7 @@ BOOST_AUTO_TEST_CASE(testStdLookupTable) { LookupTableWrap* lookup_wrap_ptr; BOOST_REQUIRE_EQUAL((int)LookupTableWrapInit(query_blk, lookup_options, query_options, lookup_segments, - 0, &lookup_wrap_ptr, NULL, NULL), 0); + 0, &lookup_wrap_ptr, NULL, NULL, NULL), 0); query_options = BlastQuerySetUpOptionsFree(query_options); BOOST_REQUIRE(query_options == NULL); BOOST_REQUIRE_EQUAL(eSmallNaLookupTable, @@ -221,8 +222,8 @@ BOOST_AUTO_TEST_CASE(testMegablastLookupTable) BlastQuerySetUpOptionsNew(&query_options); LookupTableWrap* lookup_wrap_ptr; BOOST_REQUIRE_EQUAL((int)LookupTableWrapInit(query_blk, - lookup_options, query_options, lookup_segments, - 0, &lookup_wrap_ptr, NULL, NULL), 0); + lookup_options, query_options, lookup_segments, + 0, &lookup_wrap_ptr, NULL, NULL, NULL), 0); query_options = BlastQuerySetUpOptionsFree(query_options); BOOST_REQUIRE(query_options == NULL); BOOST_REQUIRE_EQUAL((ELookupTableType)lookup_wrap_ptr->lut_type, @@ -265,8 +266,8 @@ BOOST_AUTO_TEST_CASE(testDiscontiguousMBLookupTableCodingWordSize11) { BlastQuerySetUpOptionsNew(&query_options); LookupTableWrap* lookup_wrap_ptr; BOOST_REQUIRE_EQUAL((int)LookupTableWrapInit(query_blk, - lookup_options, query_options, lookup_segments, - 0, &lookup_wrap_ptr, NULL, NULL), 0); + lookup_options, query_options, lookup_segments, + 0, &lookup_wrap_ptr, NULL, NULL, NULL), 0); query_options = BlastQuerySetUpOptionsFree(query_options); BOOST_REQUIRE(query_options == NULL); BOOST_REQUIRE_EQUAL(eMBLookupTable, (ELookupTableType)lookup_wrap_ptr->lut_type); @@ -311,8 +312,8 @@ BOOST_AUTO_TEST_CASE(testDiscontiguousMBLookupTableCodingWordSize12) { BlastQuerySetUpOptionsNew(&query_options); LookupTableWrap* lookup_wrap_ptr; BOOST_REQUIRE_EQUAL((int)LookupTableWrapInit(query_blk, - lookup_options, query_options, lookup_segments, - 0, &lookup_wrap_ptr, NULL, NULL), 0); + lookup_options, query_options, lookup_segments, + 0, &lookup_wrap_ptr, NULL, NULL, NULL), 0); query_options = BlastQuerySetUpOptionsFree(query_options); BOOST_REQUIRE(query_options == NULL); BOOST_REQUIRE_EQUAL(eMBLookupTable, (ELookupTableType)lookup_wrap_ptr->lut_type); @@ -357,8 +358,8 @@ BOOST_AUTO_TEST_CASE(testDiscontiguousMBLookupTableOptimalWordSize11) { BlastQuerySetUpOptionsNew(&query_options); LookupTableWrap* lookup_wrap_ptr; BOOST_REQUIRE_EQUAL((int)LookupTableWrapInit(query_blk, - lookup_options, query_options, lookup_segments, - 0, &lookup_wrap_ptr, NULL, NULL), 0); + lookup_options, query_options, lookup_segments, + 0, &lookup_wrap_ptr, NULL, NULL, NULL), 0); query_options = BlastQuerySetUpOptionsFree(query_options); BOOST_REQUIRE(query_options == NULL); BOOST_REQUIRE_EQUAL(eMBLookupTable, (ELookupTableType)lookup_wrap_ptr->lut_type); @@ -403,8 +404,8 @@ BOOST_AUTO_TEST_CASE(testDiscontiguousMBLookupTableOptimalWordSize12) { BlastQuerySetUpOptionsNew(&query_options); LookupTableWrap* lookup_wrap_ptr; BOOST_REQUIRE_EQUAL((int)LookupTableWrapInit(query_blk, - lookup_options, query_options, lookup_segments, - 0, &lookup_wrap_ptr, NULL, NULL), 0); + lookup_options, query_options, lookup_segments, + 0, &lookup_wrap_ptr, NULL, NULL, NULL), 0); query_options = BlastQuerySetUpOptionsFree(query_options); BOOST_REQUIRE(query_options == NULL); BOOST_REQUIRE_EQUAL(eMBLookupTable, (ELookupTableType)lookup_wrap_ptr->lut_type); @@ -449,8 +450,8 @@ BOOST_AUTO_TEST_CASE(testDiscontiguousMBLookupTableTwoTemplatesWordSize11) { BlastQuerySetUpOptionsNew(&query_options); LookupTableWrap* lookup_wrap_ptr; BOOST_REQUIRE_EQUAL((int)LookupTableWrapInit(query_blk, - lookup_options, query_options, lookup_segments, - 0, &lookup_wrap_ptr, NULL, NULL), 0); + lookup_options, query_options, lookup_segments, + 0, &lookup_wrap_ptr, NULL, NULL, NULL), 0); query_options = BlastQuerySetUpOptionsFree(query_options); BOOST_REQUIRE(query_options == NULL); BOOST_REQUIRE_EQUAL(eMBLookupTable, (ELookupTableType)lookup_wrap_ptr->lut_type); @@ -486,6 +487,160 @@ BOOST_AUTO_TEST_CASE(testDiscontiguousMBLookupTableTwoTemplatesWordSize11) { } +BOOST_AUTO_TEST_CASE(testHashLookupTableWordSize16) { + + SetUpQuery(LARGE_QUERY_GI); + LookupTableOptions* lookup_options; + LookupTableOptionsNew(eBlastTypeMapping, &lookup_options); + BLAST_FillLookupTableOptions(lookup_options, eBlastTypeMapping, + FALSE, 0, 0); + + QuerySetUpOptions* query_options = NULL; + BlastQuerySetUpOptionsNew(&query_options); + LookupTableWrap* lookup_wrap_ptr; + BOOST_REQUIRE_EQUAL((int)LookupTableWrapInit(query_blk, + lookup_options, query_options, lookup_segments, + 0, &lookup_wrap_ptr, NULL, NULL, NULL), 0); + query_options = BlastQuerySetUpOptionsFree(query_options); + BOOST_REQUIRE(query_options == NULL); + BOOST_REQUIRE_EQUAL(eNaHashLookupTable, + (ELookupTableType)lookup_wrap_ptr->lut_type); + + BlastNaHashLookupTable* lookup = + (BlastNaHashLookupTable*)lookup_wrap_ptr->lut; + BOOST_REQUIRE_EQUAL(16, (int)lookup->lut_word_length); + BOOST_REQUIRE_EQUAL(1, lookup->scan_step); + BOOST_REQUIRE_EQUAL(10, lookup->longest_chain); + BOOST_REQUIRE_EQUAL(16777216, lookup->backbone_size); + BOOST_REQUIRE_EQUAL(24, lookup->offsets_size); + BOOST_REQUIRE_EQUAL(11, lookup->pv_array_bts); + BOOST_REQUIRE_EQUAL(11, lookup->pv_array_bts); + BOOST_REQUIRE(lookup->hash_callback); + + Uint4 pv_array_size = 1u << (32 - 10); + int pv_array_hash = + EndianIndependentBufferHash((char*) lookup->pv, + pv_array_size * sizeof(PV_ARRAY_TYPE), + sizeof(PV_ARRAY_TYPE)); + BOOST_REQUIRE_EQUAL(-1839333193, pv_array_hash); + + TNaLookupHashFunction hash_func = + (TNaLookupHashFunction)lookup->hash_callback; + + // locate the first sequence word in the lookup table + // get the word in BLASTNA + Uint4 word = 0; + for (int i=0;i < 16;i++) { + BOOST_REQUIRE((query_blk->sequence[i] & 0xfc) == 0); + word = (word << 2) | query_blk->sequence[i]; + } + // hash the word + Uint4 hashed_word = hash_func((Uint1*)&word, lookup->mask); + // the word must be present in the lookup table ... + BOOST_REQUIRE(lookup->thick_backbone[hashed_word].num_words > 0); + BOOST_REQUIRE_EQUAL(word, lookup->thick_backbone[hashed_word].words[0]); + BOOST_REQUIRE(lookup->thick_backbone[hashed_word].num_offsets[0] < + NA_OFFSETS_PER_HASH); + // ... at position zero + BOOST_REQUIRE_EQUAL(0, lookup->thick_backbone[hashed_word].offsets[0]); + + lookup_wrap_ptr = LookupTableWrapFree(lookup_wrap_ptr); + BOOST_REQUIRE(lookup_wrap_ptr == NULL); + lookup_options = LookupTableOptionsFree(lookup_options); + BOOST_REQUIRE(lookup_options == NULL); +} + + +BOOST_AUTO_TEST_CASE(testHashLookupTableWordSize16WithDbFilter) { + + SetUpQuery(LARGE_QUERY_GI); + LookupTableOptions* lookup_options; + LookupTableOptionsNew(eBlastTypeMapping, &lookup_options); + BLAST_FillLookupTableOptions(lookup_options, eBlastTypeMapping, + FALSE, 0, 0); + lookup_options->db_filter = TRUE; + + CSearchDatabase db("data/pombe", CSearchDatabase::eBlastDbIsNucleotide); + CLocalDbAdapter db_adapter(db); + BlastSeqSrc* seqsrc = db_adapter.MakeSeqSrc(); + BOOST_REQUIRE(seqsrc); + + QuerySetUpOptions* query_options = NULL; + BlastQuerySetUpOptionsNew(&query_options); + + BOOST_REQUIRE(lookup_options->db_filter); + LookupTableWrap* lookup_wrap_ptr; + BOOST_REQUIRE(lookup_options->db_filter); + BOOST_REQUIRE_EQUAL((int)LookupTableWrapInit(query_blk, + lookup_options, query_options, lookup_segments, + 0, &lookup_wrap_ptr, NULL, NULL, seqsrc), 0); + query_options = BlastQuerySetUpOptionsFree(query_options); + BOOST_REQUIRE(query_options == NULL); + BOOST_REQUIRE_EQUAL(eNaHashLookupTable, + (ELookupTableType)lookup_wrap_ptr->lut_type); + + BlastNaHashLookupTable* lookup = + (BlastNaHashLookupTable*)lookup_wrap_ptr->lut; + BOOST_REQUIRE_EQUAL(16, (int)lookup->lut_word_length); + BOOST_REQUIRE_EQUAL(1, lookup->scan_step); + BOOST_REQUIRE_EQUAL(10, lookup->longest_chain); + BOOST_REQUIRE_EQUAL(16777216, lookup->backbone_size); + BOOST_REQUIRE_EQUAL(12, lookup->offsets_size); + BOOST_REQUIRE_EQUAL(11, lookup->pv_array_bts); + BOOST_REQUIRE_EQUAL(11, lookup->pv_array_bts); + BOOST_REQUIRE(lookup->hash_callback); + + Uint4 pv_array_size = 1u << (32 - 10); + int pv_array_hash = + EndianIndependentBufferHash((char*) lookup->pv, + pv_array_size * sizeof(PV_ARRAY_TYPE), + sizeof(PV_ARRAY_TYPE)); + BOOST_REQUIRE_EQUAL(2116636124, pv_array_hash); + + + TNaLookupHashFunction hash_func = + (TNaLookupHashFunction)lookup->hash_callback; + + // locate the first sequence word in the lookup table + Uint4 word = 0; + for (int i=0;i < 16;i++) { + BOOST_REQUIRE((query_blk->sequence[i] & 0xfc) == 0); + word = (word << 2) | query_blk->sequence[i]; + } + Uint4 hashed_word = hash_func((Uint1*)&word, lookup->mask); + // the word was filtered out and is not in the lookup table + BOOST_REQUIRE(lookup->thick_backbone[hashed_word].num_words == 0); + + lookup_wrap_ptr = LookupTableWrapFree(lookup_wrap_ptr); + BOOST_REQUIRE(lookup_wrap_ptr == NULL); + lookup_options = LookupTableOptionsFree(lookup_options); + BOOST_REQUIRE(lookup_options == NULL); +} + + +BOOST_AUTO_TEST_CASE(testHashLookupTableMissingSeqSrc) { + + SetUpQuery(LARGE_QUERY_GI); + LookupTableOptions* lookup_options; + LookupTableOptionsNew(eBlastTypeMapping, &lookup_options); + BLAST_FillLookupTableOptions(lookup_options, eBlastTypeMapping, + FALSE, 0, 0); + lookup_options->db_filter = TRUE; + + QuerySetUpOptions* query_options = NULL; + BlastQuerySetUpOptionsNew(&query_options); + + BOOST_REQUIRE(lookup_options->db_filter); + LookupTableWrap* lookup_wrap_ptr; + BOOST_REQUIRE(lookup_options->db_filter); + BOOST_REQUIRE((int)LookupTableWrapInit(query_blk, + lookup_options, query_options, lookup_segments, + 0, &lookup_wrap_ptr, NULL, NULL, NULL) != 0); + + lookup_options = LookupTableOptionsFree(lookup_options); + BOOST_REQUIRE(lookup_options == NULL); +} + BOOST_AUTO_TEST_CASE(testStdLookupTableDebruijn) { const int alphabet_size=4; // in alphabet there are A,C,G,T @@ -502,8 +657,8 @@ BOOST_AUTO_TEST_CASE(testStdLookupTableDebruijn) { BlastQuerySetUpOptionsNew(&query_options); LookupTableWrap* lookup_wrap_ptr; BOOST_REQUIRE_EQUAL((int)LookupTableWrapInit(query_blk, - lookup_options, query_options, lookup_segments, - 0, &lookup_wrap_ptr, NULL, NULL), 0); + lookup_options, query_options, lookup_segments, + 0, &lookup_wrap_ptr, NULL, NULL, NULL), 0); query_options = BlastQuerySetUpOptionsFree(query_options); BOOST_REQUIRE(query_options == NULL); BOOST_REQUIRE_EQUAL(eNaLookupTable, (ELookupTableType)lookup_wrap_ptr->lut_type); @@ -548,8 +703,8 @@ BOOST_AUTO_TEST_CASE(testMegablastLookupTableDebruijn) { BlastQuerySetUpOptionsNew(&query_options); LookupTableWrap* lookup_wrap_ptr; BOOST_REQUIRE_EQUAL((int)LookupTableWrapInit(query_blk, - lookup_options, query_options, lookup_segments, - 0, &lookup_wrap_ptr, NULL, NULL), 0); + lookup_options, query_options, lookup_segments, + 0, &lookup_wrap_ptr, NULL, NULL, NULL), 0); query_options = BlastQuerySetUpOptionsFree(query_options); BOOST_REQUIRE(query_options == NULL); BOOST_REQUIRE_EQUAL(eMBLookupTable, (ELookupTableType)lookup_wrap_ptr->lut_type); @@ -598,8 +753,8 @@ BOOST_AUTO_TEST_CASE(testStdTableSmallUnmaskedRegion) { BlastQuerySetUpOptionsNew(&query_options); LookupTableWrap* lookup_wrap_ptr; BOOST_REQUIRE_EQUAL((int)LookupTableWrapInit(query_blk, - lookup_options, query_options, segments, - 0, &lookup_wrap_ptr, NULL, NULL), 0); + lookup_options, query_options, segments, + 0, &lookup_wrap_ptr, NULL, NULL, NULL), 0); query_options = BlastQuerySetUpOptionsFree(query_options); BOOST_REQUIRE(query_options == NULL); BOOST_REQUIRE_EQUAL(eSmallNaLookupTable, @@ -652,8 +807,8 @@ BOOST_AUTO_TEST_CASE(testMegablastTableSmallUnmaskedRegion) { BlastQuerySetUpOptionsNew(&query_options); LookupTableWrap* lookup_wrap_ptr; BOOST_REQUIRE_EQUAL((int)LookupTableWrapInit(query_blk, - lookup_options, query_options, segments, 0, - &lookup_wrap_ptr, NULL, NULL), 0); + lookup_options, query_options, segments, 0, + &lookup_wrap_ptr, NULL, NULL, NULL), 0); query_options = BlastQuerySetUpOptionsFree(query_options); BOOST_REQUIRE(query_options == NULL); BOOST_REQUIRE_EQUAL((ELookupTableType)lookup_wrap_ptr->lut_type, eMBLookupTable); diff --git a/c++/src/algo/blast/unit_tests/api/ntlookup_unit_test.ini b/c++/src/algo/blast/unit_tests/api/ntlookup_unit_test.ini index 80f54cf6..dab8e62b 100644 --- a/c++/src/algo/blast/unit_tests/api/ntlookup_unit_test.ini +++ b/c++/src/algo/blast/unit_tests/api/ntlookup_unit_test.ini @@ -1,3 +1,5 @@ -; $Id: ntlookup_unit_test.ini 454210 2014-12-11 18:20:43Z camacho $ +; $Id: ntlookup_unit_test.ini 507273 2016-07-18 13:56:27Z boratyng $ [UNITTESTS_DISABLE] GLOBAL = OS_Solaris +testHashLookupTableWordSize16 = PLATFORM_Bits32 +testHashLookupTableWordSize16WithDbFilter = PLATFORM_Bits32 diff --git a/c++/src/algo/blast/unit_tests/api/ntscan_unit_test.cpp b/c++/src/algo/blast/unit_tests/api/ntscan_unit_test.cpp index 4c183d4d..8451a8f5 100644 --- a/c++/src/algo/blast/unit_tests/api/ntscan_unit_test.cpp +++ b/c++/src/algo/blast/unit_tests/api/ntscan_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: ntscan_unit_test.cpp 462040 2015-03-16 13:14:29Z vasilche $ +/* $Id: ntscan_unit_test.cpp 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -289,6 +289,7 @@ struct TestFixture { sbp, &lookup_wrap_ptr, NULL /* RPS Info */, + NULL, NULL); BOOST_REQUIRE_EQUAL(0, status); BlastChooseNaExtend(lookup_wrap_ptr); diff --git a/c++/src/algo/blast/unit_tests/api/phiblast_unit_test.cpp b/c++/src/algo/blast/unit_tests/api/phiblast_unit_test.cpp index f9bb4d92..c9fcb760 100644 --- a/c++/src/algo/blast/unit_tests/api/phiblast_unit_test.cpp +++ b/c++/src/algo/blast/unit_tests/api/phiblast_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: phiblast_unit_test.cpp 462040 2015-03-16 13:14:29Z vasilche $ +/* $Id: phiblast_unit_test.cpp 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -121,7 +121,7 @@ public: lookup_options->phi_pattern = strdup(pattern.c_str()); // Lookup segments and rps info arguments are irrelevant and passed as // NULL. - LookupTableWrapInit(NULL, lookup_options, NULL, NULL, m_ScoreBlk, &m_Lookup, NULL, NULL); + LookupTableWrapInit(NULL, lookup_options, NULL, NULL, m_ScoreBlk, &m_Lookup, NULL, NULL, NULL); } ~CPhiblastTestFixture() { diff --git a/c++/src/algo/blast/unit_tests/api/psiblast_iteration_unit_test.cpp b/c++/src/algo/blast/unit_tests/api/psiblast_iteration_unit_test.cpp index d6840866..948ec40e 100644 --- a/c++/src/algo/blast/unit_tests/api/psiblast_iteration_unit_test.cpp +++ b/c++/src/algo/blast/unit_tests/api/psiblast_iteration_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: psiblast_iteration_unit_test.cpp 401131 2013-05-28 18:34:25Z grichenk $ +/* $Id: psiblast_iteration_unit_test.cpp 507726 2016-07-21 14:42:04Z grichenk $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -58,7 +58,7 @@ BOOST_AUTO_TEST_CASE(TestAsLoopCounter) { itr.Advance(ids); } - BOOST_REQUIRE_EQUAL(gi, GI_FROM(unsigned int, kNumIterations)); + BOOST_REQUIRE_EQUAL(gi, GI_CONST(kNumIterations)); BOOST_REQUIRE_EQUAL(kNumIterations+1, itr.GetIterationNumber()); BOOST_REQUIRE_EQUAL(false, itr.HasMoreIterations()); BOOST_REQUIRE_EQUAL(false, itr.HasConverged()); @@ -70,8 +70,8 @@ BOOST_AUTO_TEST_CASE(TestConvergence) { BOOST_REQUIRE_EQUAL(false, itr.HasConverged()); BOOST_REQUIRE_EQUAL(1U, itr.GetIterationNumber()); CPsiBlastIterationState::TSeqIds ids, ids_plus_1; - ids.insert(CSeq_id_Handle::GetHandle(GI_FROM(TIntId, 555))); - ids_plus_1.insert(CSeq_id_Handle::GetHandle(GI_FROM(TIntId, 556))); + ids.insert(CSeq_id_Handle::GetHandle(GI_CONST(555))); + ids_plus_1.insert(CSeq_id_Handle::GetHandle(GI_CONST(556))); itr.Advance(ids); BOOST_REQUIRE_EQUAL(false, itr.HasConverged()); @@ -97,9 +97,9 @@ BOOST_AUTO_TEST_CASE(TestConvergence2) { BOOST_REQUIRE_EQUAL(false, itr.HasConverged()); BOOST_REQUIRE_EQUAL(1U, itr.GetIterationNumber()); CPsiBlastIterationState::TSeqIds ids_itr1, ids_itr2; - ids_itr1.insert(CSeq_id_Handle::GetHandle(GI_FROM(TIntId, 555))); - ids_itr1.insert(CSeq_id_Handle::GetHandle(GI_FROM(TIntId, 556))); - ids_itr2.insert(CSeq_id_Handle::GetHandle(GI_FROM(TIntId, 555))); + ids_itr1.insert(CSeq_id_Handle::GetHandle(GI_CONST(555))); + ids_itr1.insert(CSeq_id_Handle::GetHandle(GI_CONST(556))); + ids_itr2.insert(CSeq_id_Handle::GetHandle(GI_CONST(555))); itr.Advance(ids_itr1); BOOST_REQUIRE_EQUAL(false, itr.HasConverged()); @@ -117,8 +117,8 @@ BOOST_AUTO_TEST_CASE(TestModifyingConvergedIterationState) { BOOST_REQUIRE_EQUAL(false, itr.HasConverged()); CPsiBlastIterationState::TSeqIds ids; - ids.insert(CSeq_id_Handle::GetHandle(GI_FROM(TIntId, 555))); - ids.insert(CSeq_id_Handle::GetHandle(GI_FROM(TIntId, 555))); + ids.insert(CSeq_id_Handle::GetHandle(GI_CONST(555))); + ids.insert(CSeq_id_Handle::GetHandle(GI_CONST(555))); itr.Advance(ids); BOOST_REQUIRE_EQUAL(false, itr.HasConverged()); diff --git a/c++/src/algo/blast/unit_tests/api/psiblast_unit_test.cpp b/c++/src/algo/blast/unit_tests/api/psiblast_unit_test.cpp index 867c747a..3dfcb761 100644 --- a/c++/src/algo/blast/unit_tests/api/psiblast_unit_test.cpp +++ b/c++/src/algo/blast/unit_tests/api/psiblast_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: psiblast_unit_test.cpp 498724 2016-04-19 13:36:57Z ivanov $ +/* $Id: psiblast_unit_test.cpp 498248 2016-04-14 15:42:26Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/algo/blast/unit_tests/api/querydata_unit_test.cpp b/c++/src/algo/blast/unit_tests/api/querydata_unit_test.cpp index f82207ed..22149fde 100644 --- a/c++/src/algo/blast/unit_tests/api/querydata_unit_test.cpp +++ b/c++/src/algo/blast/unit_tests/api/querydata_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: querydata_unit_test.cpp 401131 2013-05-28 18:34:25Z grichenk $ +/* $Id: querydata_unit_test.cpp 507726 2016-07-21 14:42:04Z grichenk $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -567,9 +567,9 @@ BOOST_FIXTURE_TEST_SUITE(QueryData, CQueryDataTestFixture) BOOST_AUTO_TEST_CASE(ObjMgr_QueryFactory_LocalData_GetSumOfSequenceLengths) { vector gis; - gis.push_back(GI_FROM(TIntId, 26)); - gis.push_back(GI_FROM(TIntId, 555)); - gis.push_back(GI_FROM(TIntId, 556)); + gis.push_back(GI_CONST(26)); + gis.push_back(GI_CONST(555)); + gis.push_back(GI_CONST(556)); CRef bs(new CBioseq_set); ITERATE(vector, itr, gis) { CBioseq_Handle bh = CSimpleOM::GetBioseqHandle(*itr); @@ -599,31 +599,31 @@ BOOST_AUTO_TEST_CASE(ObjMgr_QueryFactory_LocalData_GetSumOfSequenceLengths) { BOOST_AUTO_TEST_CASE(ObjMgr_QueryFactory_LocalDataFromTSeqLocVector_Protein) { vector gis; - gis.push_back(GI_FROM(TIntId, 38092615)); - gis.push_back(GI_FROM(TIntId, 4506509)); + gis.push_back(GI_CONST(38092615)); + gis.push_back(GI_CONST(4506509)); s_ObjMgr_QueryFactory_LocalDataFromTSeqLocVector(gis); } BOOST_AUTO_TEST_CASE(ObjMgr_QueryFactory_LocalDataFromTSeqLocVector_Nucleotide) { vector gis; - gis.push_back(GI_FROM(TIntId, 555)); - gis.push_back(GI_FROM(TIntId, 556)); - gis.push_back(GI_FROM(TIntId, 26)); + gis.push_back(GI_CONST(555)); + gis.push_back(GI_CONST(556)); + gis.push_back(GI_CONST(26)); s_ObjMgr_QueryFactory_LocalDataFromTSeqLocVector(gis); } BOOST_AUTO_TEST_CASE(ObjMgr_QueryFactory_LocalDataFromBlastQueryVector_Protein) { vector gis; - gis.push_back(GI_FROM(TIntId, 38092615)); - gis.push_back(GI_FROM(TIntId, 4506509)); + gis.push_back(GI_CONST(38092615)); + gis.push_back(GI_CONST(4506509)); s_ObjMgr_QueryFactory_LocalDataFromBlastQueryVector(gis); } BOOST_AUTO_TEST_CASE(ObjMgr_QueryFactory_LocalDataFromBlastQueryVector_Nucleotide) { vector gis; - gis.push_back(GI_FROM(TIntId, 555)); - gis.push_back(GI_FROM(TIntId, 556)); - gis.push_back(GI_FROM(TIntId, 26)); + gis.push_back(GI_CONST(555)); + gis.push_back(GI_CONST(556)); + gis.push_back(GI_CONST(26)); s_ObjMgr_QueryFactory_LocalDataFromBlastQueryVector(gis); } @@ -634,7 +634,7 @@ BOOST_AUTO_TEST_CASE(ObjMgr_QueryFactory_RemoteData_SingleBioseqFromTSeqLocVecto auto_ptr sl(CTestObjMgr::Instance().CreateSSeqLoc(qid)); queries.push_back(*sl); CRef query_factory(new CObjMgr_QueryFactory(queries)); - CSequenceDataTester(query_factory, GI_FROM(int, kGi))(); + CSequenceDataTester(query_factory, GI_CONST(kGi))(); } BOOST_AUTO_TEST_CASE(ObjMgr_QueryFactory_RemoteData_SingleBioseqFromBlastQueryVector) { @@ -649,7 +649,7 @@ BOOST_AUTO_TEST_CASE(ObjMgr_QueryFactory_RemoteData_SingleBioseqFromBlastQueryVe queries->AddQuery(sq); CRef query_factory(new CObjMgr_QueryFactory(*queries)); - CSequenceDataTester(query_factory, GI_FROM(TIntId, kGi))(); + CSequenceDataTester(query_factory, GI_CONST(kGi))(); } BOOST_AUTO_TEST_CASE(ObjMgr_QueryFactory_EmptyTSeqLocVector) { @@ -665,28 +665,28 @@ BOOST_AUTO_TEST_CASE(ObjMgr_QueryFactory_EmptyBlastQueryVector) { // BOOST_AUTO_TEST_CASE(ObjMgrFree_QueryFactory_LocalDataFromBioseq_Protein) { - const TGi kGi = GI_FROM(TIntId, 129295); + const TGi kGi = GI_CONST(129295); s_ObjMgrFree_QueryFactory_LocalDataFromBioseq(kGi); } BOOST_AUTO_TEST_CASE(ObjMgrFree_QueryFactory_LocalDataFromBioseq_Nucleotide) { - const TGi kGi = GI_FROM(TIntId, 555); + const TGi kGi = GI_CONST(555); s_ObjMgrFree_QueryFactory_LocalDataFromBioseq(kGi); } BOOST_AUTO_TEST_CASE(ObjMgrFree_QueryFactory_LocalDataFromBioseq_set_Protein) { vector gis; - gis.push_back(GI_FROM(TIntId, 129295)); - gis.push_back(GI_FROM(TIntId, 87)); - gis.push_back(GI_FROM(TIntId, 1900)); + gis.push_back(GI_CONST(129295)); + gis.push_back(GI_CONST(87)); + gis.push_back(GI_CONST(1900)); s_ObjMgrFree_QueryFactory_LocalDataFromBioseq_set(gis); } BOOST_AUTO_TEST_CASE(ObjMgrFree_QueryFactory_LocalDataFromBioseq_set_Nucleotide) { vector gis; - gis.push_back(GI_FROM(TIntId, 26)); - gis.push_back(GI_FROM(TIntId, 555)); - gis.push_back(GI_FROM(TIntId, 556)); + gis.push_back(GI_CONST(26)); + gis.push_back(GI_CONST(555)); + gis.push_back(GI_CONST(556)); s_ObjMgrFree_QueryFactory_LocalDataFromBioseq_set(gis); } diff --git a/c++/src/algo/blast/unit_tests/api/queryinfo_unit_test.cpp b/c++/src/algo/blast/unit_tests/api/queryinfo_unit_test.cpp index 654fef27..c325f9c9 100644 --- a/c++/src/algo/blast/unit_tests/api/queryinfo_unit_test.cpp +++ b/c++/src/algo/blast/unit_tests/api/queryinfo_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: queryinfo_unit_test.cpp 345770 2011-11-30 13:58:31Z madden $ +/* $Id: queryinfo_unit_test.cpp 506956 2016-07-13 16:19:54Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -145,5 +145,77 @@ BOOST_AUTO_TEST_CASE(BlastnGetQueryIndex) { BOOST_REQUIRE_EQUAL(1, query_index); } +BOOST_AUTO_TEST_CASE(BlastnSearchContextInfo) +{ + CSeq_id id1("gi|3090"); + CSeq_id id2("gi|555"); + auto_ptr qsl1(CTestObjMgr::Instance().CreateSSeqLoc(id1)); + auto_ptr qsl2(CTestObjMgr::Instance().CreateSSeqLoc(id2)); + TSeqLocVector query_v; + query_v.push_back(*qsl1); + query_v.push_back(*qsl2); + CBlastQueryInfo query_info; + CRef opts(CBlastOptionsFactory::Create(eBlastn)); + + const CBlastOptions& kOpts = opts->GetOptions(); + EBlastProgramType prog = kOpts.GetProgramType(); + ENa_strand strand_opt = kOpts.GetStrandOption(); + + SetupQueryInfo(query_v, prog, strand_opt, &query_info); + + int length_1 = qsl1->scope->GetSequenceLength(id1); + int length_2 = qsl2->scope->GetSequenceLength(id2); + + // test min and max query length + BOOST_REQUIRE_EQUAL(query_info->min_length, min(length_1, length_2)); + BOOST_REQUIRE_EQUAL(query_info->max_length, max(length_1, length_2)); + + // test context for zero position in each sequence strand + BOOST_REQUIRE_EQUAL(0, BSearchContextInfo(0, query_info.Get())); + BOOST_REQUIRE_EQUAL(1, BSearchContextInfo(length_1 + 1, query_info.Get())); + BOOST_REQUIRE_EQUAL(2, BSearchContextInfo(2 * (length_1 + 1), + query_info.Get())); + + BOOST_REQUIRE_EQUAL(3, BSearchContextInfo(2 * (length_1 + 1) + length_2 + 1, + query_info.Get())); +} + +BOOST_AUTO_TEST_CASE(BlastnSearchContextInfoSingleStrand) +{ + CSeq_id id1("gi|555"); + CSeq_id id2("gi|3090"); + // only plus strand for the first sequence + auto_ptr qsl1(CTestObjMgr::Instance().CreateSSeqLoc(id1, + eNa_strand_plus)); + auto_ptr qsl2(CTestObjMgr::Instance().CreateSSeqLoc(id2)); + TSeqLocVector query_v; + query_v.push_back(*qsl1); + query_v.push_back(*qsl2); + CBlastQueryInfo query_info; + CRef opts(CBlastOptionsFactory::Create(eBlastn)); + + const CBlastOptions& kOpts = opts->GetOptions(); + EBlastProgramType prog = kOpts.GetProgramType(); + ENa_strand strand_opt = kOpts.GetStrandOption(); + + SetupQueryInfo(query_v, prog, strand_opt, &query_info); + + // pre condition: empty context in query info + BOOST_REQUIRE_EQUAL(query_info->contexts[1].query_length, 0); + + int length_1 = qsl1->scope->GetSequenceLength(id1); + int length_2 = qsl2->scope->GetSequenceLength(id2); + + // test min and max query length + BOOST_REQUIRE_EQUAL(query_info->min_length, 0u); + BOOST_REQUIRE_EQUAL(query_info->max_length, max(length_1, length_2)); + + // test context for zero position in each sequence strand + BOOST_REQUIRE_EQUAL(0, BSearchContextInfo(0, query_info.Get())); + BOOST_REQUIRE_EQUAL(2, BSearchContextInfo(length_1 + 1, query_info.Get())); + BOOST_REQUIRE_EQUAL(3, BSearchContextInfo(length_1 + length_2 + 2, + query_info.Get())); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/c++/src/algo/blast/unit_tests/api/redoalignment_unit_test.cpp b/c++/src/algo/blast/unit_tests/api/redoalignment_unit_test.cpp index 1c7c7503..995b5865 100644 --- a/c++/src/algo/blast/unit_tests/api/redoalignment_unit_test.cpp +++ b/c++/src/algo/blast/unit_tests/api/redoalignment_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: redoalignment_unit_test.cpp 498724 2016-04-19 13:36:57Z ivanov $ +/* $Id: redoalignment_unit_test.cpp 504861 2016-06-20 15:45:40Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -290,7 +290,7 @@ void CRedoAlignmentTestFixture:: hitsaving_opts, ext_options->compositionBasedStats, scoring_opts->gapped_calculation)); - BlastHSPWriter* writer = BlastHSPWriterNew(&writer_info, NULL); + BlastHSPWriter* writer = BlastHSPWriterNew(&writer_info, NULL, NULL); BOOST_REQUIRE(writer_info == NULL); BlastHSPStream* hsp_stream = BlastHSPStreamNew( diff --git a/c++/src/algo/blast/unit_tests/api/remote_blast_unit_test.cpp b/c++/src/algo/blast/unit_tests/api/remote_blast_unit_test.cpp index 94abdde3..286dbd59 100644 --- a/c++/src/algo/blast/unit_tests/api/remote_blast_unit_test.cpp +++ b/c++/src/algo/blast/unit_tests/api/remote_blast_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: remote_blast_unit_test.cpp 454692 2014-12-17 15:16:27Z camacho $ +/* $Id: remote_blast_unit_test.cpp 507726 2016-07-21 14:42:04Z grichenk $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -206,7 +206,7 @@ BOOST_AUTO_TEST_CASE(CheckRemoteRPSBlastOptionsHandle) { rmt_blaster.SetDatabase("cdd"); CRemoteBlast::TSeqLocList query_seqlocs; CRef sl(new CSeq_loc); - sl->SetWhole().SetGi(GI_FROM(TIntId, 129295)); + sl->SetWhole().SetGi(GI_CONST(129295)); query_seqlocs.push_back(sl); rmt_blaster.SetQueries(query_seqlocs); diff --git a/c++/src/algo/blast/unit_tests/api/rps_unit_test.cpp b/c++/src/algo/blast/unit_tests/api/rps_unit_test.cpp index f1a35adc..2568e343 100644 --- a/c++/src/algo/blast/unit_tests/api/rps_unit_test.cpp +++ b/c++/src/algo/blast/unit_tests/api/rps_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: rps_unit_test.cpp 498724 2016-04-19 13:36:57Z ivanov $ +/* $Id: rps_unit_test.cpp 505234 2016-06-23 13:16:57Z fongah2 $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -184,8 +185,11 @@ struct RpsTestFixture { } void NuclSearch(ENa_strand strand) { - CRef - opts(CBlastOptionsFactory::Create(eRPSTblastn)); + CRef opts(CBlastOptionsFactory::Create(eRPSTblastn)); + opts->SetFilterString("F"); + CRPSTBlastnOptionsHandle * + rpstblastn_opts(dynamic_cast (opts.GetPointer())); + rpstblastn_opts->SetCompositionBasedStats(false); opts->SetFilterString("F"); CSeq_id id("gi|19572546"); diff --git a/c++/src/algo/blast/unit_tests/api/split_query_unit_test.cpp b/c++/src/algo/blast/unit_tests/api/split_query_unit_test.cpp index e8b2cd94..e5b08502 100644 --- a/c++/src/algo/blast/unit_tests/api/split_query_unit_test.cpp +++ b/c++/src/algo/blast/unit_tests/api/split_query_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: split_query_unit_test.cpp 401131 2013-05-28 18:34:25Z grichenk $ +/* $Id: split_query_unit_test.cpp 497783 2016-04-11 12:27:40Z madden $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -913,7 +913,7 @@ return; // FIXME { retval.clear(); vector tokens; - NStr::Tokenize(input, ",", tokens); + NStr::Split(input, ",", tokens); retval.reserve(tokens.size()); ITERATE(vector, token, tokens) { retval.push_back(NStr::StringToInt(NStr::TruncateSpaces(*token))); diff --git a/c++/src/algo/blast/unit_tests/api/stat_unit_test.cpp b/c++/src/algo/blast/unit_tests/api/stat_unit_test.cpp index 3a555a65..122f4fb8 100644 --- a/c++/src/algo/blast/unit_tests/api/stat_unit_test.cpp +++ b/c++/src/algo/blast/unit_tests/api/stat_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: stat_unit_test.cpp 498724 2016-04-19 13:36:57Z ivanov $ +/* $Id: stat_unit_test.cpp 498248 2016-04-14 15:42:26Z boratyng $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/algo/blast/unit_tests/api/stat_unit_test.ini b/c++/src/algo/blast/unit_tests/api/stat_unit_test.ini new file mode 100644 index 00000000..883af81a --- /dev/null +++ b/c++/src/algo/blast/unit_tests/api/stat_unit_test.ini @@ -0,0 +1,3 @@ +; $Id: stat_unit_test.ini 504636 2016-06-16 19:14:01Z boratyng $ +[UNITTESTS_DISABLE] +GLOBAL = OS_Solaris diff --git a/c++/src/algo/blast/unit_tests/api/traceback_unit_test.cpp b/c++/src/algo/blast/unit_tests/api/traceback_unit_test.cpp index 89178181..025ece1a 100644 --- a/c++/src/algo/blast/unit_tests/api/traceback_unit_test.cpp +++ b/c++/src/algo/blast/unit_tests/api/traceback_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: traceback_unit_test.cpp 462040 2015-03-16 13:14:29Z vasilche $ +/* $Id: traceback_unit_test.cpp 516338 2016-10-12 17:32:04Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -125,7 +125,7 @@ public: opt.GetExtnOpts()->compositionBasedStats, opt.GetScoringOpts()->gapped_calculation)); - BlastHSPWriter* writer = BlastHSPWriterNew(&writer_info, NULL); + BlastHSPWriter* writer = BlastHSPWriterNew(&writer_info, NULL, NULL); BOOST_REQUIRE(writer_info == NULL); return BlastHSPStreamNew(opt.GetProgramType(), opt.GetExtnOpts(), FALSE, 1, writer); @@ -298,8 +298,8 @@ BOOST_AUTO_TEST_CASE(testBLASTNTraceBack) { const int score_final[k_num_hsps_end] = { 252, 226, 182, 54, 40, 26, 24}; const int context_final[k_num_hsps_end] = { 0, 0, 0, 0, 0, 1, 1}; const int subject_frame_final[k_num_hsps_end] = { 1, 1, 1, 1, 1, 1, 1}; - const int query_gapped_start_final[k_num_hsps_end] = { 6035, 6625, 5295, 7199, 5209, 7414, 3824}; - const int subject_gapped_start_final[k_num_hsps_end] = { 116, 244, 16, 386, 10, 69, 77}; + const int query_gapped_start_final[k_num_hsps_end] = { 6035, 6625, 5295, 7193, 5199, 7409, 3819}; + const int subject_gapped_start_final[k_num_hsps_end] = { 116, 244, 16, 380, 0, 64, 72}; const int num_ident_final[k_num_hsps_end] = { 135, 134, 91, 36, 20, 25, 12}; // One hsp is dropped when the function runs. @@ -795,7 +795,7 @@ BOOST_AUTO_TEST_CASE(testNoHSPEvalueCutoffBeforeLink) { hit_options, ext_options->compositionBasedStats, scoring_options->gapped_calculation)); - BlastHSPWriter* writer = BlastHSPWriterNew(&writer_info, NULL); + BlastHSPWriter* writer = BlastHSPWriterNew(&writer_info, NULL, NULL); BOOST_REQUIRE(writer_info == NULL); BlastHSPStream* hsp_stream = BlastHSPStreamNew( kProgramType, ext_options, FALSE, 1, writer); diff --git a/c++/src/algo/blast/unit_tests/api/tracebacksearch_unit_test.cpp b/c++/src/algo/blast/unit_tests/api/tracebacksearch_unit_test.cpp index 1434f34d..7dc6ed21 100644 --- a/c++/src/algo/blast/unit_tests/api/tracebacksearch_unit_test.cpp +++ b/c++/src/algo/blast/unit_tests/api/tracebacksearch_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: tracebacksearch_unit_test.cpp 457458 2015-01-23 12:27:33Z madden $ +/* $Id: tracebacksearch_unit_test.cpp 520431 2016-11-28 18:26:12Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -46,6 +46,7 @@ #include #include #include +#include // needed for objmgr dependent tests of query data interface @@ -93,7 +94,7 @@ public: opts->GetExtnOpts()->compositionBasedStats, opts->GetScoringOpts()->gapped_calculation)); - BlastHSPWriter* writer = BlastHSPWriterNew(&writer_info, NULL); + BlastHSPWriter* writer = BlastHSPWriterNew(&writer_info, NULL, NULL); BOOST_REQUIRE(writer_info == NULL); BlastHSPStream* hsp_stream = BlastHSPStreamNew( @@ -177,7 +178,7 @@ public: opts->GetExtnOpts()->compositionBasedStats, opts->GetScoringOpts()->gapped_calculation)); - BlastHSPWriter* writer = BlastHSPWriterNew(&writer_info, NULL); + BlastHSPWriter* writer = BlastHSPWriterNew(&writer_info, NULL, NULL); BOOST_REQUIRE(writer_info == NULL); BlastHSPStream* hsp_stream = BlastHSPStreamNew( @@ -218,67 +219,31 @@ public: return hsps; } - void x_FindUsedGis(const CDense_seg & dseg, set & used) - { - typedef vector< CRef< CScore > > TScoreList; - - if (dseg.CanGetScores()) { - const TScoreList & scores = dseg.GetScores(); - - ITERATE(TScoreList, sc, scores) { - const CScore & sc1 = **sc; - - if (sc1.CanGetId() && sc1.GetId().IsStr()) { - string id_name = sc1.GetId().GetStr(); - - if (id_name == "use_this_gi") { - BOOST_REQUIRE(sc1.CanGetValue()); - BOOST_REQUIRE(sc1.GetValue().IsInt()); - - used.insert(sc1.GetValue().GetInt()); - } - } - } - } - } - - typedef vector< CRef< CScore > > TScoreList; - - void x_FindUsedGis(const TScoreList & scores, set & used) - { - ITERATE(TScoreList, sc, scores) { - const CScore & sc1 = **sc; - - if (sc1.CanGetId() && sc1.GetId().IsStr()) { - string id_name = sc1.GetId().GetStr(); - - if (id_name == "use_this_gi") { - BOOST_REQUIRE(sc1.CanGetValue()); - BOOST_REQUIRE(sc1.GetValue().IsInt()); - - used.insert(sc1.GetValue().GetInt()); - } - } - } - } - - void x_FindUsedGis(const CSeq_align_set & aset, set & used) + void x_FindUsedGis(const CSeq_align_set & aset, set & used) { + used.clear(); ITERATE(CSeq_align_set::Tdata, align, aset.Get()) { - CSeq_align::C_Segs::E_Choice ch = (**align).GetSegs().Which(); - - if ((**align).CanGetScore()) { - x_FindUsedGis((**align).GetScore(), used); - } - - if (ch == CSeq_align::C_Segs::e_Disc) { - x_FindUsedGis((**align).GetSegs().GetDisc(), used); - } else if (ch == CSeq_align::C_Segs::e_Denseg) { -// x_FindUsedGis((**align).GetSegs().GetDenseg(), used); - } else { - BOOST_REQUIRE_EQUAL((int)ch, 0); - } - } + if((**align).CanGetExt() && (**align).GetExt().size() > 0) + { + CRef uObject = (**align).GetExt().front(); + if(uObject->IsSetType() && uObject->GetType().IsStr() && + uObject->GetType().GetStr() == "use_this_seqid" && uObject->IsSetData()) + { + const CUser_object::TData& fields = uObject->GetData(); + for(CUser_object::TData::const_iterator fit = fields.begin(); fit != fields.end(); ++fit) + { + const CUser_field& field = **fit; + if (field.IsSetLabel() && field.GetLabel().IsStr() && field.GetLabel().GetStr() == "SEQIDS") + { + const vector< CStringUTF8 >& giStrings = field.GetData().GetStrs(); + ITERATE(vector< CStringUTF8 >, str, giStrings) { + used.insert(*str); + } + } + } + } + } + } } CSearchResultSet x_Traceback(CSeqDBGiList * gi_list) @@ -340,7 +305,7 @@ BOOST_FIXTURE_TEST_SUITE(tracebacksearch, CTracebackSearchTestFixture) BOOST_AUTO_TEST_CASE(Traceback) { CSearchResultSet rset = x_Traceback(0); - set use_these; + set use_these; x_FindUsedGis(*rset[0].GetSeqAlign(), use_these); BOOST_REQUIRE(use_these.empty()); @@ -446,11 +411,11 @@ BOOST_AUTO_TEST_CASE(TracebackEntrez) { CSearchResultSet rset = x_Traceback(gi_list.GetPointerOrNull()); - set use_these; + set use_these; x_FindUsedGis(*rset[0].GetSeqAlign(), use_these); BOOST_REQUIRE_EQUAL((int)use_these.size(), 1); - BOOST_REQUIRE_EQUAL(*use_these.begin(), 158292535); + BOOST_REQUIRE(*(use_these.begin()) == "gi:158292535"); } BOOST_AUTO_TEST_SUITE_END() diff --git a/c++/src/algo/blast/unit_tests/api/version_reference_unit_test.cpp b/c++/src/algo/blast/unit_tests/api/version_reference_unit_test.cpp index 5f1bb6dd..f4f29d60 100644 --- a/c++/src/algo/blast/unit_tests/api/version_reference_unit_test.cpp +++ b/c++/src/algo/blast/unit_tests/api/version_reference_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: version_reference_unit_test.cpp 500531 2016-05-05 14:28:38Z ivanov $ +/* $Id: version_reference_unit_test.cpp 521263 2016-12-07 15:18:43Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -43,7 +43,7 @@ BOOST_AUTO_TEST_SUITE(version_reference) BOOST_AUTO_TEST_CASE(testVersion) { const int kMajor = 2; - const int kMinor = 4; + const int kMinor = 6; const int kPatch = 0; blast::CBlastVersion v; BOOST_REQUIRE_EQUAL(kMajor, v.GetMajor()); diff --git a/c++/src/algo/blast/unit_tests/blast_format/Makefile.blast_format_unit_test.app b/c++/src/algo/blast/unit_tests/blast_format/Makefile.blast_format_unit_test.app index 96ce71a5..4927ae82 100644 --- a/c++/src/algo/blast/unit_tests/blast_format/Makefile.blast_format_unit_test.app +++ b/c++/src/algo/blast/unit_tests/blast_format/Makefile.blast_format_unit_test.app @@ -1,4 +1,4 @@ -# $Id: Makefile.blast_format_unit_test.app 421234 2013-12-10 19:27:57Z camacho $ +# $Id: Makefile.blast_format_unit_test.app 500512 2016-05-05 13:14:49Z gouriano $ APP = blast_format_unit_test SRC = seqalignfilter_unit_test blastfmtutil_unit_test build_archive_unit_test vecscreen_run_unit_test @@ -7,7 +7,7 @@ CPPFLAGS = -DNCBI_MODULE=BLASTFORMAT $(ORIG_CPPFLAGS) $(BOOST_INCLUDE) CXXFLAGS = $(FAST_CXXFLAGS) LDFLAGS = $(FAST_LDFLAGS) -LIB_ = test_boost $(BLAST_FORMATTER_LIBS) ncbi_xloader_blastdb_rmt \ +LIB_ = test_boost $(BLAST_FORMATTER_LIBS) \ $(BLAST_LIBS) $(OBJMGR_LIBS) LIB = $(LIB_:%=%$(STATIC)) diff --git a/c++/src/algo/blast/unit_tests/blast_format/blastfmtutil_unit_test.cpp b/c++/src/algo/blast/unit_tests/blast_format/blastfmtutil_unit_test.cpp index 253e631e..b8df80b1 100644 --- a/c++/src/algo/blast/unit_tests/blast_format/blastfmtutil_unit_test.cpp +++ b/c++/src/algo/blast/unit_tests/blast_format/blastfmtutil_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: blastfmtutil_unit_test.cpp 456661 2015-01-14 15:22:43Z fongah2 $ +/* $Id: blastfmtutil_unit_test.cpp 507726 2016-07-21 14:42:04Z grichenk $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -175,7 +175,7 @@ BOOST_AUTO_TEST_CASE(GetAlnScoresAndGetScoreString) sum_n, num_ident, use_this_gi); BOOST_REQUIRE(score == 1296); BOOST_REQUIRE(sum_n == -1); - BOOST_REQUIRE(use_this_gi.front() == GI_FROM(TIntId, 18426812)); + BOOST_REQUIRE(use_this_gi.front() == GI_CONST(18426812)); BOOST_REQUIRE_CLOSE(evalue, 217774e-146, kMaxDoubleDiff); BOOST_REQUIRE_CLOSE(bits, 503.263, 0.0001); BOOST_REQUIRE(num_ident == 331); diff --git a/c++/src/algo/blast/unit_tests/blast_format/vecscreen_run_unit_test.cpp b/c++/src/algo/blast/unit_tests/blast_format/vecscreen_run_unit_test.cpp index c0c97bd1..89073967 100644 --- a/c++/src/algo/blast/unit_tests/blast_format/vecscreen_run_unit_test.cpp +++ b/c++/src/algo/blast/unit_tests/blast_format/vecscreen_run_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: vecscreen_run_unit_test.cpp 401131 2013-05-28 18:34:25Z grichenk $ +/* $Id: vecscreen_run_unit_test.cpp 507726 2016-07-21 14:42:04Z grichenk $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -69,7 +69,7 @@ BOOST_AUTO_TEST_CASE(VecscreenRunWithHits) CRef scope = ss.NewScope(); CRef query_loc(new CSeq_loc()); - query_loc->SetWhole().SetGi(GI_FROM(TIntId, 555)); + query_loc->SetWhole().SetGi(GI_CONST(555)); CVecscreenRun vs_run(query_loc, scope); @@ -94,7 +94,7 @@ BOOST_AUTO_TEST_CASE(VecscreenRunWithNoHits) CRef scope = ss.NewScope(); CRef query_loc(new CSeq_loc()); - query_loc->SetWhole().SetGi(GI_FROM(TIntId, 405832)); + query_loc->SetWhole().SetGi(GI_CONST(405832)); CVecscreenRun vs_run(query_loc, scope); @@ -113,7 +113,7 @@ BOOST_AUTO_TEST_CASE(VecscreenRunWithNoDataLoader) CRef scope(new CScope(*object_manager)); CRef query_loc(new CSeq_loc()); - query_loc->SetWhole().SetGi(GI_FROM(TIntId, 555)); + query_loc->SetWhole().SetGi(GI_CONST(555)); BOOST_REQUIRE_THROW(CVecscreenRun vs_run(query_loc, scope), blast::CBlastException); } diff --git a/c++/src/algo/blast/unit_tests/blastdb/Makefile.bdbloader_unit_test.app b/c++/src/algo/blast/unit_tests/blastdb/Makefile.bdbloader_unit_test.app index a6075410..ac8d4d5b 100644 --- a/c++/src/algo/blast/unit_tests/blastdb/Makefile.bdbloader_unit_test.app +++ b/c++/src/algo/blast/unit_tests/blastdb/Makefile.bdbloader_unit_test.app @@ -1,12 +1,11 @@ -# $Id: Makefile.bdbloader_unit_test.app 421234 2013-12-10 19:27:57Z camacho $ +# $Id: Makefile.bdbloader_unit_test.app 500512 2016-05-05 13:14:49Z gouriano $ APP = bdbloader_unit_test SRC = bdbloader_unit_test CPPFLAGS = -DNCBI_MODULE=BLASTDB $(ORIG_CPPFLAGS) $(BOOST_INCLUDE) -I../ -LIB_ = test_boost $(BLAST_INPUT_LIBS) ncbi_xloader_blastdb_rmt \ - $(BLAST_LIBS) $(OBJMGR_LIBS) +LIB_ = test_boost $(BLAST_INPUT_LIBS) $(BLAST_LIBS) $(OBJMGR_LIBS) LIB = $(LIB_:%=%$(STATIC)) LIBS = $(NETWORK_LIBS) $(CMPRS_LIBS) $(DL_LIBS) $(ORIG_LIBS) diff --git a/c++/src/algo/blast/unit_tests/seqdb_reader/Makefile.seqdb_unit_test.app b/c++/src/algo/blast/unit_tests/seqdb_reader/Makefile.seqdb_unit_test.app index 1cc778fc..89086b65 100644 --- a/c++/src/algo/blast/unit_tests/seqdb_reader/Makefile.seqdb_unit_test.app +++ b/c++/src/algo/blast/unit_tests/seqdb_reader/Makefile.seqdb_unit_test.app @@ -1,4 +1,4 @@ -# $Id: Makefile.seqdb_unit_test.app 421234 2013-12-10 19:27:57Z camacho $ +# $Id: Makefile.seqdb_unit_test.app 505858 2016-06-29 16:55:21Z elisovdn $ APP = seqdb_unit_test SRC = seqdb_unit_test diff --git a/c++/src/algo/blast/unit_tests/seqdb_reader/seqdb_unit_test.cpp b/c++/src/algo/blast/unit_tests/seqdb_reader/seqdb_unit_test.cpp index d98d5455..85317fbf 100644 --- a/c++/src/algo/blast/unit_tests/seqdb_reader/seqdb_unit_test.cpp +++ b/c++/src/algo/blast/unit_tests/seqdb_reader/seqdb_unit_test.cpp @@ -1,4 +1,4 @@ -/* $Id: seqdb_unit_test.cpp 488259 2015-12-29 14:32:15Z camacho $ +/* $Id: seqdb_unit_test.cpp 512373 2016-08-30 14:51:51Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -98,7 +98,10 @@ static void s_TestPartialAmbig(CSeqDB & db, TGi nt_gi) int oid(-1); bool success = db.GiToOid(nt_gi, oid); - BOOST_REQUIRE(success); + CNcbiOstrstream oss; + oss << "GI " << nt_gi << " was not found in nt"; + string msg = CNcbiOstrstreamToString(oss); + BOOST_REQUIRE_MESSAGE(success, msg); int length = db.GetSeqLength(oid); @@ -2152,7 +2155,7 @@ BOOST_AUTO_TEST_CASE(PartialSequences) s_TestPartialAmbig(nt, 57340989); s_TestPartialAmbig(nt, 24430781); - s_TestPartialAmbig(nt, 8885782); + s_TestPartialAmbig(nt, 1059791394); } BOOST_AUTO_TEST_CASE(GiListInOidRangeIteration) @@ -2501,7 +2504,7 @@ BOOST_AUTO_TEST_CASE(IntersectionGiList) // the other to verify that the code computing the intersection // correctly sorts its inputs. - TGi special = GI_FROM(int, 41); + TGi special = GI_CONST(41); // Add to start of a3 a3.push_back(special); @@ -2542,7 +2545,7 @@ BOOST_AUTO_TEST_CASE(IntersectionNegGiList) // the other to verify that the code computing the intersection // correctly sorts its inputs. - TGi special = GI_FROM(int, 41); + TGi special = GI_CONST(41); // Add to start of a3 a3.push_back(special); @@ -2557,7 +2560,7 @@ BOOST_AUTO_TEST_CASE(IntersectionNegGiList) // Add to end of a5 a5.push_back(special); - a5.push_back(GI_FROM(int, 1000)); + a5.push_back(GI_CONST(1000)); CSeqDBNegativeList gi3; gi3.SetGiList(a3); diff --git a/c++/src/algo/blast/unit_tests/seqdb_reader/seqdb_unit_test.ini b/c++/src/algo/blast/unit_tests/seqdb_reader/seqdb_unit_test.ini index b6341a56..b4ed4aab 100644 --- a/c++/src/algo/blast/unit_tests/seqdb_reader/seqdb_unit_test.ini +++ b/c++/src/algo/blast/unit_tests/seqdb_reader/seqdb_unit_test.ini @@ -1,4 +1,4 @@ -; $Id: seqdb_unit_test.ini 403238 2013-06-13 14:36:54Z camacho $ +; $Id: seqdb_unit_test.ini 520559 2016-11-29 19:17:28Z ivanov $ [UNITTESTS_DISABLE] ; TestOidNotFoundWithUserAliasFileAndGiList = true @@ -10,3 +10,11 @@ ; Temporarily disable due to wgs transition GlobalMemoryBound = true DeltaSequenceHash = true + +FilteredHeaders = OS_Windows && PLATFORM_Bits32 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; FIXME: this is a temporary workaround for SB-1826 +OidAndGiLists=true +NrAndSwissProt=true +NegativeListNr=true diff --git a/c++/src/app/Makefile.in b/c++/src/app/Makefile.in index 615e6e60..fb347bb3 100644 --- a/c++/src/app/Makefile.in +++ b/c++/src/app/Makefile.in @@ -1,4 +1,4 @@ -# $Id: Makefile.in 490144 2016-01-21 16:27:21Z bollin $ +# $Id: Makefile.in 507812 2016-07-21 17:53:16Z boratyng $ # Miscellaneous applications ################################# @@ -11,10 +11,10 @@ SUB_PROJ = asn2asn asn2fasta asn2flat asnval asn_cleanup \ bdb_env_keeper nw_aligner speedtest idmapper formatguess \ multireader read_blast_result splign hfilter \ annotwriter compart streamtest lds2_indexer \ - discrep_report discrepancy_report biosample_chk gap_stats table2asn \ - srcchk tableval ncbi_encrypt ssub_fork + discrepancy_report biosample_chk gap_stats table2asn \ + srcchk tableval ncbi_encrypt ssub_fork asn_cache magicblast -EXPENDABLE_SUB_PROJ = split_cache wig2table netcache rmblastn dblb tls +EXPENDABLE_SUB_PROJ = split_cache wig2table netcache rmblastn dblb tls idfetch REQUIRES = app diff --git a/c++/src/app/blast/Makefile.blastn.app b/c++/src/app/blast/Makefile.blastn.app index fd0e731c..2f1794fb 100644 --- a/c++/src/app/blast/Makefile.blastn.app +++ b/c++/src/app/blast/Makefile.blastn.app @@ -1,10 +1,11 @@ -# $Id: Makefile.blastn.app 474746 2015-07-31 13:51:46Z madden $ +# $Id: Makefile.blastn.app 504861 2016-06-20 15:45:40Z boratyng $ WATCHERS = camacho madden fongah2 APP = blastn SRC = blastn_app -LIB_ = $(BLAST_INPUT_LIBS) $(BLAST_LIBS) $(OBJMGR_LIBS) +LIB_ = xformat xcleanup valid gbseq mlacli mla medlars pubmed submit xregexp $(PCRE_LIB) \ + $(BLAST_INPUT_LIBS) $(BLAST_LIBS) $(OBJMGR_LIBS) LIB = blast_app_util $(LIB_:%=%$(STATIC)) # De-universalize Mac builds to work around a PPC toolchain limitation diff --git a/c++/src/app/blast/Makefile.in b/c++/src/app/blast/Makefile.in index 9038f9d3..62866b50 100644 --- a/c++/src/app/blast/Makefile.in +++ b/c++/src/app/blast/Makefile.in @@ -1,4 +1,4 @@ -# $Id: Makefile.in 371962 2012-08-14 09:45:56Z coulouri $ +# $Id: Makefile.in 507582 2016-07-20 14:22:33Z boratyng $ # Meta-makefile("APP" project) ################################# diff --git a/c++/src/app/blast/blast_app_util.cpp b/c++/src/app/blast/blast_app_util.cpp index f40fa93d..0b348992 100644 --- a/c++/src/app/blast/blast_app_util.cpp +++ b/c++/src/app/blast/blast_app_util.cpp @@ -1,4 +1,4 @@ -/* $Id: blast_app_util.cpp 500374 2016-05-04 13:30:40Z ivanov $ +/* $Id: blast_app_util.cpp 509280 2016-08-04 16:03:11Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -31,11 +31,6 @@ * Utility functions for BLAST command line applications */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_app_util.cpp 500374 2016-05-04 13:30:40Z ivanov $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include "blast_app_util.hpp" @@ -53,9 +48,6 @@ static char const rcsid[] = #include #include -#include -#include -#include #include #include // for CTypeInfo, needed by SerialClone #include @@ -645,22 +637,6 @@ SaveSearchStrategy(const CArgs& args, pssm, num_iters); } -struct CConstRefCSeqId_LessThan -{ - bool operator() (const CConstRef& a, const CConstRef& b) const { - if (a.Empty() && b.NotEmpty()) { - return true; - } else if (a.NotEmpty() && b.Empty()) { - return false; - } else if (a.Empty() && b.Empty()) { - return true; - } else { - _ASSERT(a.NotEmpty() && b.NotEmpty()); - return *a < *b; - } - } -}; - /// Extracts the subject sequence IDs and ranges from the BLAST results /// @note if this ever needs to be refactored for popular developer /// consumption, this function should operate on CSeq_align_set as opposed to @@ -722,70 +698,75 @@ s_IsUsingRemoteBlastDbDataLoader() return false; } -void BlastFormatter_PreFetchSequenceData(const blast::CSearchResultSet& - results, CRef scope) +static bool +s_IsPrefetchFormat(blast::CFormattingArgs::EOutputFormat format_type) +{ + if ((format_type == CFormattingArgs::eAsnText) || + (format_type == CFormattingArgs::eAsnBinary) || + (format_type == CFormattingArgs::eArchiveFormat)|| + (format_type == CFormattingArgs::eJsonSeqalign)) { + return false; + } + return true; +} + +static bool +s_PreFetchSeqs(const blast::CSearchResultSet& results, + blast::CFormattingArgs::EOutputFormat format_type) +{ + { + char * pre_fetch_limit_str = getenv("PRE_FETCH_SEQS_LIMIT"); + if (pre_fetch_limit_str) { + int pre_fetch_limit = NStr::StringToInt(pre_fetch_limit_str); + if(pre_fetch_limit == 0) { + return false; + } + if(pre_fetch_limit == INT_MAX){ + return true; + } + int num_of_seqs = 0; + for(unsigned int i=0; i < results.GetNumResults(); i++) { + if(results[i].HasAlignments()) { + num_of_seqs += results[i].GetSeqAlign()->Size(); + } + } + if(num_of_seqs > pre_fetch_limit) { + return false; + } + } + } + + return s_IsPrefetchFormat(format_type); +} + +void BlastFormatter_PreFetchSequenceData(const blast::CSearchResultSet& results, + CRef scope, + blast::CFormattingArgs::EOutputFormat format_type) { _ASSERT(scope.NotEmpty()); if (results.size() == 0) { return; } - // Only useful if we're dealing with then remote BLAST DB data loader - if (! s_IsUsingRemoteBlastDbDataLoader() ) { - return; + if(!s_PreFetchSeqs(results, format_type)){ + return; } - - CScope::TIds ids; - vector ranges; - s_ExtractSeqidsAndRanges(results, ids, ranges); - _TRACE("Prefetching " << ids.size() << " sequence lengths"); - try { - CScope::TBioseqHandles bhs = scope->GetBioseqHandles(ids); - - // Per Eugene Vasilchenko's suggestion, via email on 6/8/10: - // "With the current API you can make artificial delta sequence - // referencing several other sequences and use its CSeqMap to load them - // all in one call. There is no straightforward way to do this, sorry." - - // Create virtual delta sequence - CRef top_seq(new CBioseq); - CSeq_inst& inst = top_seq->SetInst(); - inst.SetRepr(CSeq_inst::eRepr_virtual); - inst.SetMol(CSeq_inst::eMol_not_set); - CDelta_ext& delta = inst.SetExt().SetDelta(); - int i = 0; - ITERATE(CScope::TBioseqHandles, it, bhs) { - CRef seq(new CDelta_seq); - CSeq_interval& interval = seq->SetLoc().SetInt(); - interval.SetId - (*SerialClone(*it->GetAccessSeq_id_Handle().GetSeqId())); - if (ranges[i].GetFrom() > ranges[i].GetToOpen()) { - TSeqPos length = it->GetBioseqLength(); - interval.SetFrom(length - ranges[i].GetTo()); - interval.SetTo(length - ranges[i].GetFrom()); - } else { - interval.SetFrom(ranges[i].GetFrom()); - interval.SetTo(ranges[i].GetTo()); - } - i++; - delta.Set().push_back(seq); - } - - // Add it to the scope - CBioseq_Handle top_bh = scope->AddBioseq(*top_seq); - - // prepare selector. SetLinkUsedTSE() is necessary for batch loading - SSeqMapSelector sel(CSeqMap::fFindAnyLeaf, kInvalidSeqPos); - sel.SetLinkUsedTSE(top_bh.GetTSE_Handle()); + CScope::TIds ids; + vector ranges; + s_ExtractSeqidsAndRanges(results, ids, ranges); + _TRACE("Prefetching " << ids.size() << " sequence lengths"); + LoadSequencesToScope(ids, ranges, scope); + } catch (CException& e) { + if(s_IsUsingRemoteBlastDbDataLoader()) { + NCBI_THROW(CBlastSystemException, eNetworkError, + "Error fetching sequence data from BLAST databases at NCBI, " + "please try again later"); + } + else { + NCBI_RETHROW_SAME(e, "Error pre-fetching sequence data "); + } + } - // and get all sequence data in batch mode - _TRACE("Prefetching " << ids.size() << " sequences"); - top_bh.GetSeqMap().CanResolveRange(&*scope, sel); - } catch (const CException&) { - NCBI_THROW(CBlastSystemException, eNetworkError, - "Error fetching sequence data from BLAST databases at NCBI, " - "please try again later"); - } } /// Auxiliary function to extract the ancillary data from the PSSM. diff --git a/c++/src/app/blast/blast_app_util.hpp b/c++/src/app/blast/blast_app_util.hpp index 6abed4fd..59c6881d 100644 --- a/c++/src/app/blast/blast_app_util.hpp +++ b/c++/src/app/blast/blast_app_util.hpp @@ -1,4 +1,4 @@ -/* $Id: blast_app_util.hpp 495291 2016-03-16 14:52:25Z ivanov $ +/* $Id: blast_app_util.hpp 509280 2016-08-04 16:03:11Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -265,15 +265,15 @@ SaveSearchStrategy(const CArgs& args, = CRef(), unsigned int num_iters = 0); -/// This method needs to be invoked for optimizing the retrieval of -/// sequence data from the remote BLAST database data loader (exercised -/// when there are no locally available BLAST databases) +/// This method optimize the retrieval of sequence data to scope /// @param results BLAST results [in] /// @param scope CScope object from which the sequence data will be fetched /// [in] +/// @param format_type Blast output fomat type void BlastFormatter_PreFetchSequenceData(const blast::CSearchResultSet& - results, CRef scope); + results, CRef scope, + blast::CFormattingArgs::EOutputFormat format_type); /// Auxiliary function to extract the ancillary data from the PSSM. /// Used in PSI-BLAST and DELTA-BLAST diff --git a/c++/src/app/blast/blast_formatter.cpp b/c++/src/app/blast/blast_formatter.cpp index 5eeaaa08..2d093722 100644 --- a/c++/src/app/blast/blast_formatter.cpp +++ b/c++/src/app/blast/blast_formatter.cpp @@ -1,4 +1,4 @@ -/* $Id: blast_formatter.cpp 495294 2016-03-16 14:53:17Z ivanov $ +/* $Id: blast_formatter.cpp 509280 2016-08-04 16:03:11Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -31,11 +31,6 @@ * Stand-alone command line formatter for BLAST. */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blast_formatter.cpp 495294 2016-03-16 14:53:17Z ivanov $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include @@ -353,7 +348,8 @@ int CBlastFormatterApp::PrintFormattedOutput(void) } else { while (1) { - BlastFormatter_PreFetchSequenceData(*results, scope); + BlastFormatter_PreFetchSequenceData(*results, scope, + fmt_args.GetFormattedOutputChoice()); ITERATE(CSearchResultSet, result, *results) { if(isPsiBlast) { @@ -471,6 +467,6 @@ int CBlastFormatterApp::Run(void) #ifndef SKIP_DOXYGEN_PROCESSING int main(int argc, const char* argv[] /*, const char* envp[]*/) { - return CBlastFormatterApp().AppMain(argc, argv, 0, eDS_Default, ""); + return CBlastFormatterApp().AppMain(argc, argv); } #endif /* SKIP_DOXYGEN_PROCESSING */ diff --git a/c++/src/app/blast/blastn_app.cpp b/c++/src/app/blast/blastn_app.cpp index 78ed4199..08d4fd63 100644 --- a/c++/src/app/blast/blastn_app.cpp +++ b/c++/src/app/blast/blastn_app.cpp @@ -1,4 +1,4 @@ -/* $Id: blastn_app.cpp 495294 2016-03-16 14:53:17Z ivanov $ +/* $Id: blastn_app.cpp 509280 2016-08-04 16:03:11Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -31,11 +31,6 @@ * BLASTN command line application */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blastn_app.cpp 495294 2016-03-16 14:53:17Z ivanov $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include @@ -213,7 +208,8 @@ int CBlastnApp::Run(void) formatter.WriteArchive(*queries, *opts_hndl, *results, 0, bah.GetMessages()); bah.ResetMessages(); } else { - BlastFormatter_PreFetchSequenceData(*results, scope); + BlastFormatter_PreFetchSequenceData(*results, scope, + fmt_args->GetFormattedOutputChoice()); ITERATE(CSearchResultSet, result, *results) { formatter.PrintOneResultSet(**result, query_batch); } diff --git a/c++/src/app/blast/blastp_app.cpp b/c++/src/app/blast/blastp_app.cpp index 5369ac3f..6251d9a7 100644 --- a/c++/src/app/blast/blastp_app.cpp +++ b/c++/src/app/blast/blastp_app.cpp @@ -1,4 +1,4 @@ -/* $Id: blastp_app.cpp 495295 2016-03-16 14:53:41Z ivanov $ +/* $Id: blastp_app.cpp 509280 2016-08-04 16:03:11Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -31,11 +31,6 @@ * BLASTP command line application */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blastp_app.cpp 495295 2016-03-16 14:53:41Z ivanov $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include @@ -192,7 +187,8 @@ int CBlastpApp::Run(void) formatter.WriteArchive(*queries, *opts_hndl, *results, 0, bah.GetMessages()); bah.ResetMessages(); } else { - BlastFormatter_PreFetchSequenceData(*results, scope); + BlastFormatter_PreFetchSequenceData(*results, scope, + fmt_args->GetFormattedOutputChoice()); ITERATE(CSearchResultSet, result, *results) { formatter.PrintOneResultSet(**result, query_batch); } diff --git a/c++/src/app/blast/blastx_app.cpp b/c++/src/app/blast/blastx_app.cpp index b2151641..2e9fcca4 100644 --- a/c++/src/app/blast/blastx_app.cpp +++ b/c++/src/app/blast/blastx_app.cpp @@ -1,4 +1,4 @@ -/* $Id: blastx_app.cpp 495295 2016-03-16 14:53:41Z ivanov $ +/* $Id: blastx_app.cpp 509280 2016-08-04 16:03:11Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -31,11 +31,6 @@ * BLASTX command line application */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blastx_app.cpp 495295 2016-03-16 14:53:41Z ivanov $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include @@ -190,7 +185,8 @@ int CBlastxApp::Run(void) formatter.WriteArchive(*queries, *opts_hndl, *results, 0, bah.GetMessages()); bah.ResetMessages(); } else { - BlastFormatter_PreFetchSequenceData(*results, scope); + BlastFormatter_PreFetchSequenceData(*results, scope, + fmt_args->GetFormattedOutputChoice()); ITERATE(CSearchResultSet, result, *results) { formatter.PrintOneResultSet(**result, query_batch); } diff --git a/c++/src/app/blast/deltablast_app.cpp b/c++/src/app/blast/deltablast_app.cpp index c6f6d843..1162ea42 100644 --- a/c++/src/app/blast/deltablast_app.cpp +++ b/c++/src/app/blast/deltablast_app.cpp @@ -1,4 +1,4 @@ -/* $Id: deltablast_app.cpp 495295 2016-03-16 14:53:41Z ivanov $ +/* $Id: deltablast_app.cpp 509280 2016-08-04 16:03:11Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -31,11 +31,6 @@ * DELTA-BLAST command line application */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: deltablast_app.cpp 495295 2016-03-16 14:53:41Z ivanov $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include @@ -357,9 +352,11 @@ int CDeltaBlastApp::Run(void) formatter.WriteArchive(*queries, *opts_hndl, *results, 0, m_bah.GetMessages()); m_bah.ResetMessages(); } else { - BlastFormatter_PreFetchSequenceData(*results, scope); + BlastFormatter_PreFetchSequenceData(*results, scope, + fmt_args->GetFormattedOutputChoice()); if (m_CmdLineArgs->GetShowDomainHits()) { - BlastFormatter_PreFetchSequenceData(*results, scope); + BlastFormatter_PreFetchSequenceData(*domain_results, scope, + fmt_args->GetFormattedOutputChoice()); } ITERATE(blast::CSearchResultSet, result, *results) { if (m_CmdLineArgs->GetShowDomainHits()) { @@ -477,7 +474,8 @@ CDeltaBlastApp::DoPsiBlastIterations(CRef opts_hndl, CRef query_factory(new CObjMgr_QueryFactory(*query)); - BlastFormatter_PreFetchSequenceData(*results, scope); + BlastFormatter_PreFetchSequenceData(*results, scope, + m_CmdLineArgs->GetFormattingArgs()->GetFormattedOutputChoice()); if (CFormattingArgs::eArchiveFormat == m_CmdLineArgs->GetFormattingArgs()->GetFormattedOutputChoice()) { formatter.WriteArchive(*query_factory, *opts_hndl, *results, @@ -524,7 +522,8 @@ CDeltaBlastApp::DoPsiBlastIterations(CRef opts_hndl, psiblast->SetNumberOfThreads(m_CmdLineArgs->GetNumThreads()); results = psiblast->Run(); - BlastFormatter_PreFetchSequenceData(*results, scope); + BlastFormatter_PreFetchSequenceData(*results, scope, + m_CmdLineArgs->GetFormattingArgs()->GetFormattedOutputChoice()); if (CFormattingArgs::eArchiveFormat == m_CmdLineArgs->GetFormattingArgs()->GetFormattedOutputChoice()) { formatter.WriteArchive(*pssm, *opts_hndl, *results, @@ -586,7 +585,7 @@ CDeltaBlastApp::ComputePssmForNextPsiBlastIteration(const CBioseq& bioseq, #ifndef SKIP_DOXYGEN_PROCESSING int main(int argc, const char* argv[] /*, const char* envp[]*/) { - return CDeltaBlastApp().AppMain(argc, argv, 0, eDS_Default, ""); + return CDeltaBlastApp().AppMain(argc, argv); } #endif /* SKIP_DOXYGEN_PROCESSING */ diff --git a/c++/src/app/blast/psiblast_app.cpp b/c++/src/app/blast/psiblast_app.cpp index 0b33701a..c4dde7d6 100644 --- a/c++/src/app/blast/psiblast_app.cpp +++ b/c++/src/app/blast/psiblast_app.cpp @@ -1,4 +1,4 @@ -/* $Id: psiblast_app.cpp 495295 2016-03-16 14:53:41Z ivanov $ +/* $Id: psiblast_app.cpp 509280 2016-08-04 16:03:11Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -31,11 +31,6 @@ * PSI-BLAST command line application */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: psiblast_app.cpp 495295 2016-03-16 14:53:41Z ivanov $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include @@ -249,13 +244,15 @@ CPsiBlastApp::x_RunLocalPsiBlastIterations(CRef query, CLocalBlast lcl_blast(query_factory, CRef(phi_opts), db_adapter); lcl_blast.SetNumberOfThreads(m_CmdLineArgs->GetNumThreads()); results = lcl_blast.Run(); - BlastFormatter_PreFetchSequenceData(*results, scope); + BlastFormatter_PreFetchSequenceData(*results, scope, + m_CmdLineArgs->GetFormattingArgs()->GetFormattedOutputChoice()); formatter.PrintPhiResult(*results, query, itr.GetIterationNumber(), itr.GetPreviouslyFoundSeqIds()); } else { results = psiblast->Run(); - BlastFormatter_PreFetchSequenceData(*results, scope); + BlastFormatter_PreFetchSequenceData(*results, scope, + m_CmdLineArgs->GetFormattingArgs()->GetFormattedOutputChoice()); if(CFormattingArgs::eArchiveFormat == m_CmdLineArgs->GetFormattingArgs()->GetFormattedOutputChoice()) { @@ -360,7 +357,8 @@ CPsiBlastApp::DoIterations(CRef opts_hndl, } else { - BlastFormatter_PreFetchSequenceData(*results, scope); + BlastFormatter_PreFetchSequenceData(*results, scope, + m_CmdLineArgs->GetFormattingArgs()->GetFormattedOutputChoice()); ITERATE(CSearchResultSet, result, *results) { formatter.PrintOneResultSet(**result, query); } @@ -566,6 +564,6 @@ int CPsiBlastApp::Run(void) #ifndef SKIP_DOXYGEN_PROCESSING int main(int argc, const char* argv[] /*, const char* envp[]*/) { - return CPsiBlastApp().AppMain(argc, argv, 0, eDS_Default, ""); + return CPsiBlastApp().AppMain(argc, argv); } #endif /* SKIP_DOXYGEN_PROCESSING */ diff --git a/c++/src/app/blast/rpsblast_app.cpp b/c++/src/app/blast/rpsblast_app.cpp index 37e5ca7c..b2f7a5cd 100644 --- a/c++/src/app/blast/rpsblast_app.cpp +++ b/c++/src/app/blast/rpsblast_app.cpp @@ -1,4 +1,4 @@ -/* $Id: rpsblast_app.cpp 495295 2016-03-16 14:53:41Z ivanov $ +/* $Id: rpsblast_app.cpp 509280 2016-08-04 16:03:11Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -31,11 +31,6 @@ * RPSBLAST command line application */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: rpsblast_app.cpp 495295 2016-03-16 14:53:41Z ivanov $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include @@ -196,7 +191,8 @@ int CRPSBlastApp::Run(void) formatter.WriteArchive(*queries, *opts_hndl, *results, 0, bah.GetMessages()); bah.ResetMessages(); } else { - BlastFormatter_PreFetchSequenceData(*results, scope); + BlastFormatter_PreFetchSequenceData(*results, scope, + fmt_args->GetFormattedOutputChoice()); ITERATE(CSearchResultSet, result, *results) { formatter.PrintOneResultSet(**result, query_batch); } @@ -220,7 +216,7 @@ int CRPSBlastApp::Run(void) #ifndef SKIP_DOXYGEN_PROCESSING int main(int argc, const char* argv[] /*, const char* envp[]*/) { - int status = CRPSBlastApp().AppMain(argc, argv, 0, eDS_Default, ""); + int status = CRPSBlastApp().AppMain(argc, argv); return status; } diff --git a/c++/src/app/blast/rpstblastn_app.cpp b/c++/src/app/blast/rpstblastn_app.cpp index f30ad758..1586abd3 100644 --- a/c++/src/app/blast/rpstblastn_app.cpp +++ b/c++/src/app/blast/rpstblastn_app.cpp @@ -1,4 +1,4 @@ -/* $Id: rpstblastn_app.cpp 495295 2016-03-16 14:53:41Z ivanov $ +/* $Id: rpstblastn_app.cpp 509280 2016-08-04 16:03:11Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -31,11 +31,6 @@ * RPS TBLASTN command line application */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: rpstblastn_app.cpp 495295 2016-03-16 14:53:41Z ivanov $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include @@ -193,7 +188,8 @@ int CRPSTBlastnApp::Run(void) formatter.WriteArchive(*queries, *opts_hndl, *results, 0, bah.GetMessages()); bah.ResetMessages(); } else { - BlastFormatter_PreFetchSequenceData(*results, scope); + BlastFormatter_PreFetchSequenceData(*results, scope, + fmt_args->GetFormattedOutputChoice()); ITERATE(CSearchResultSet, result, *results) { formatter.PrintOneResultSet(**result, query_batch); } @@ -217,6 +213,6 @@ int CRPSTBlastnApp::Run(void) #ifndef SKIP_DOXYGEN_PROCESSING int main(int argc, const char* argv[] /*, const char* envp[]*/) { - return CRPSTBlastnApp().AppMain(argc, argv, 0, eDS_Default, ""); + return CRPSTBlastnApp().AppMain(argc, argv); } #endif /* SKIP_DOXYGEN_PROCESSING */ diff --git a/c++/src/app/blast/seedtop_app.cpp b/c++/src/app/blast/seedtop_app.cpp index 0eb12c4d..17ad3295 100644 --- a/c++/src/app/blast/seedtop_app.cpp +++ b/c++/src/app/blast/seedtop_app.cpp @@ -1,4 +1,4 @@ -/* $Id: seedtop_app.cpp 473030 2015-07-15 19:29:59Z camacho $ +/* $Id: seedtop_app.cpp 500404 2016-05-04 14:59:01Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -31,11 +31,6 @@ * SEEDTOP command line application */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: seedtop_app.cpp 473030 2015-07-15 19:29:59Z camacho $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include @@ -241,6 +236,6 @@ int CSeedTopApp::Run(void) #ifndef SKIP_DOXYGEN_PROCESSING int main(int argc, const char* argv[] /*, const char* envp[]*/) { - return CSeedTopApp().AppMain(argc, argv, 0, eDS_Default, ""); + return CSeedTopApp().AppMain(argc, argv); } #endif /* SKIP_DOXYGEN_PROCESSING */ diff --git a/c++/src/app/blast/tblastn_app.cpp b/c++/src/app/blast/tblastn_app.cpp index 38e85a5b..d163d190 100644 --- a/c++/src/app/blast/tblastn_app.cpp +++ b/c++/src/app/blast/tblastn_app.cpp @@ -1,4 +1,4 @@ -/* $Id: tblastn_app.cpp 495295 2016-03-16 14:53:41Z ivanov $ +/* $Id: tblastn_app.cpp 509280 2016-08-04 16:03:11Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -31,11 +31,6 @@ * TBLASTN command line application */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: tblastn_app.cpp 495295 2016-03-16 14:53:41Z ivanov $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include @@ -211,7 +206,8 @@ int CTblastnApp::Run(void) formatter.WriteArchive(*query_factory, *opts_hndl, *results, 0, bah.GetMessages()); bah.ResetMessages(); } else { - BlastFormatter_PreFetchSequenceData(*results, scope); + BlastFormatter_PreFetchSequenceData(*results, scope, + fmt_args->GetFormattedOutputChoice()); ITERATE(CSearchResultSet, result, *results) { formatter.PrintOneResultSet(**result, query); } @@ -246,7 +242,8 @@ int CTblastnApp::Run(void) formatter.WriteArchive(*query_factory, *opts_hndl, *results, 0, bah.GetMessages()); bah.ResetMessages(); } else { - BlastFormatter_PreFetchSequenceData(*results, scope); + BlastFormatter_PreFetchSequenceData(*results, scope, + fmt_args->GetFormattedOutputChoice()); ITERATE(CSearchResultSet, result, *results) { formatter.PrintOneResultSet(**result, query); } diff --git a/c++/src/app/blast/tblastx_app.cpp b/c++/src/app/blast/tblastx_app.cpp index 808f133b..91af1530 100644 --- a/c++/src/app/blast/tblastx_app.cpp +++ b/c++/src/app/blast/tblastx_app.cpp @@ -1,4 +1,4 @@ -/* $Id: tblastx_app.cpp 495295 2016-03-16 14:53:41Z ivanov $ +/* $Id: tblastx_app.cpp 509280 2016-08-04 16:03:11Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -31,11 +31,6 @@ * TBLASTX command line application */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: tblastx_app.cpp 495295 2016-03-16 14:53:41Z ivanov $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include @@ -190,7 +185,8 @@ int CTblastxApp::Run(void) formatter.WriteArchive(*queries, *opts_hndl, *results, 0, bah.GetMessages()); bah.ResetMessages(); } else { - BlastFormatter_PreFetchSequenceData(*results, scope); + BlastFormatter_PreFetchSequenceData(*results, scope, + fmt_args->GetFormattedOutputChoice()); ITERATE(CSearchResultSet, result, *results) { formatter.PrintOneResultSet(**result, query_batch); } diff --git a/c++/src/app/blast/update_blastdb.pl b/c++/src/app/blast/update_blastdb.pl index 4aba43a5..76a046e4 100755 --- a/c++/src/app/blast/update_blastdb.pl +++ b/c++/src/app/blast/update_blastdb.pl @@ -1,5 +1,5 @@ #!/usr/bin/perl -# $Id: update_blastdb.pl 446062 2014-09-10 21:38:05Z camacho $ +# $Id: update_blastdb.pl 504861 2016-06-20 15:45:40Z boratyng $ # =========================================================================== # # PUBLIC DOMAIN NOTICE @@ -82,7 +82,7 @@ $|++; # Connect and download files my $ftp = &connect_to_ftp() unless ($opt_show_version); if ($opt_show_version) { - my $revision = '$Revision: 446062 $'; + my $revision = '$Revision: 504861 $'; $revision =~ s/\$Revision: | \$//g; print "$0 version $revision\n"; } elsif ($opt_showall) { diff --git a/c++/src/app/blastdb/Makefile.convert2blastmask.app b/c++/src/app/blastdb/Makefile.convert2blastmask.app index 611960cc..ff732815 100644 --- a/c++/src/app/blastdb/Makefile.convert2blastmask.app +++ b/c++/src/app/blastdb/Makefile.convert2blastmask.app @@ -5,7 +5,7 @@ REQUIRES = objects APP = convert2blastmask SRC = convert2blastmask -LIB = seqmasks_io $(BLAST_LIBS) $(OBJMGR_LIBS:%=%$(STATIC)) +LIB = $(BLAST_LIBS) $(OBJMGR_LIBS) CFLAGS = $(FAST_CFLAGS) CXXFLAGS = $(FAST_CXXFLAGS) diff --git a/c++/src/app/blastdb/Makefile.makeblastdb.app b/c++/src/app/blastdb/Makefile.makeblastdb.app index c9ab8bbd..405031ad 100644 --- a/c++/src/app/blastdb/Makefile.makeblastdb.app +++ b/c++/src/app/blastdb/Makefile.makeblastdb.app @@ -2,7 +2,7 @@ WATCHERS = camacho fongah2 APP = makeblastdb SRC = makeblastdb masked_range_set -LIB_ = $(BLAST_INPUT_LIBS) writedb $(BLAST_LIBS) $(OBJMGR_LIBS) +LIB_ = writedb $(BLAST_INPUT_LIBS) $(BLAST_LIBS) $(OBJMGR_LIBS) LIB = $(LIB_:%=%$(STATIC)) CFLAGS = $(FAST_CFLAGS) diff --git a/c++/src/app/blastdb/Makefile.makeprofiledb.app b/c++/src/app/blastdb/Makefile.makeprofiledb.app index 476ca1bd..88c72924 100644 --- a/c++/src/app/blastdb/Makefile.makeprofiledb.app +++ b/c++/src/app/blastdb/Makefile.makeprofiledb.app @@ -2,7 +2,7 @@ WATCHERS = fongah2 APP = makeprofiledb SRC = makeprofiledb -LIB_ = $(BLAST_INPUT_LIBS) writedb $(BLAST_LIBS) $(OBJMGR_LIBS) +LIB_ = writedb $(BLAST_INPUT_LIBS) $(BLAST_LIBS) $(OBJMGR_LIBS) LIB = $(LIB_:%=%$(STATIC)) CFLAGS = $(FAST_CFLAGS) diff --git a/c++/src/app/blastdb/blastdb_aliastool.cpp b/c++/src/app/blastdb/blastdb_aliastool.cpp index 304ab2ac..5827a7bc 100644 --- a/c++/src/app/blastdb/blastdb_aliastool.cpp +++ b/c++/src/app/blastdb/blastdb_aliastool.cpp @@ -1,4 +1,4 @@ -/* $Id: blastdb_aliastool.cpp 488259 2015-12-29 14:32:15Z camacho $ +/* $Id: blastdb_aliastool.cpp 519975 2016-11-21 18:09:00Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -31,11 +31,6 @@ * Command line tool to create BLAST database aliases and associated files. */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blastdb_aliastool.cpp 488259 2015-12-29 14:32:15Z camacho $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include @@ -108,9 +103,9 @@ const char * const CBlastDBAliasApp::DOCUMENTATION = "\n\n" " binary format. This can be provided as an argument to the -gilist option\n" " of the BLAST search command line binaries or to the -gilist option of\n" " this program to create an alias file for a BLAST database (see below).\n\n" -"2) Alias file creation (restricting with GI List):\n" -" Creates an alias for a BLAST database and a GI list which restricts this\n" -" database. This is useful if one often searches a subset of a database\n" +"2) Alias file creation (restricting with GI List or Sequence ID List):\n" +" Creates an alias for a BLAST database and a GI or ID list which restricts\n" +" this database. This is useful if one often searches a subset of a database\n" " (e.g., based on organism or a curated list). The alias file makes the\n" " search appear as if one were searching a regular BLAST database rather\n" " than the subset of one.\n\n" @@ -135,7 +130,8 @@ void CBlastDBAliasApp::Init() dflt += " with the .bgl extension"; const char* exclusions[] = { kArgDb.c_str(), kArgDbType.c_str(), kArgDbTitle.c_str(), - kArgGiList.c_str(), kArgOutput.c_str(), "dblist", "num_volumes", "vdblist" }; + kArgGiList.c_str(), kArgSeqIdList.c_str(), kArgOutput.c_str(), + "dblist", "num_volumes", "vdblist" }; arg_desc->SetCurrentGroup("GI file conversion options"); arg_desc->AddOptionalKey("gi_file_in", "input_file", "Text file to convert, should contain one GI per line", @@ -158,7 +154,6 @@ void CBlastDBAliasApp::Init() arg_desc->SetCurrentGroup("Alias file creation options"); arg_desc->AddOptionalKey(kArgDb, "dbname", "BLAST database name", CArgDescriptions::eString); - arg_desc->SetDependency(kArgDb, CArgDescriptions::eRequires, kArgGiList); arg_desc->SetDependency(kArgDb, CArgDescriptions::eRequires, kOutput); arg_desc->AddDefaultKey(kArgDbType, "molecule_type", @@ -181,6 +176,16 @@ void CBlastDBAliasApp::Init() "to binary", CArgDescriptions::eInputFile); arg_desc->SetDependency(kArgGiList, CArgDescriptions::eRequires, kOutput); + + arg_desc->AddOptionalKey(kArgSeqIdList, "input_file", + "Text sequence id or accession file to restrict " + "the BLAST database provided in -db argument", + CArgDescriptions::eInputFile); + + arg_desc->SetDependency(kArgSeqIdList, CArgDescriptions::eRequires, kOutput); + arg_desc->SetDependency(kArgSeqIdList, CArgDescriptions::eExcludes, + kArgGiList); + #ifdef NCBI_TI arg_desc->AddFlag("process_as_tis", "Process all numeric ID lists as TIs instead of GIs", true); @@ -226,6 +231,7 @@ void CBlastDBAliasApp::Init() CArgDescriptions::eInteger); arg_desc->SetDependency("num_volumes", CArgDescriptions::eExcludes, kArgDb); arg_desc->SetDependency("num_volumes", CArgDescriptions::eExcludes, kArgGiList); + arg_desc->SetDependency("num_volumes", CArgDescriptions::eExcludes, kArgSeqIdList); arg_desc->SetDependency("num_volumes", CArgDescriptions::eRequires, kOutput); arg_desc->SetDependency("num_volumes", CArgDescriptions::eRequires, kArgDbType); arg_desc->SetDependency("num_volumes", CArgDescriptions::eRequires, kArgDbTitle); @@ -284,12 +290,25 @@ CBlastDBAliasApp::CreateAliasFile() const if (args.Exist("process_as_tis") && args["process_as_tis"]) { isTiList = true; } + + if (args[kArgDb].HasValue() && !args[kArgGiList].HasValue() && + !args[kArgSeqIdList].HasValue()) { + + NCBI_THROW(CInputException, eInvalidInput, "Either gilist or " + "seqid_list must be specified if database name is used"); + } + if (args[kArgDbTitle].HasValue()) { title = args[kArgDbTitle].AsString(); } else if (args[kArgDb].HasValue()) { - _ASSERT(args[kArgGiList].HasValue()); - title = args[kArgDb].AsString() + " limited by " + - args[kArgGiList].AsString(); + _ASSERT(args[kArgGiList].HasValue() || args[kArgSeqIdList].HasValue()); + title = args[kArgDb].AsString() + " limited by "; + if (args[kArgGiList]) { + title += args[kArgGiList].AsString(); + } + else { + title += args[kArgSeqIdList].AsString(); + } } const CWriteDB::ESeqType seq_type = args[kArgDbType].AsString() == "prot" @@ -316,6 +335,14 @@ CBlastDBAliasApp::CreateAliasFile() const } } + string seqid_list = args[kArgSeqIdList] ? args[kArgSeqIdList].AsString() : + kEmptyStr; + if ( !seqid_list.empty() ) { + if ( !CFile(seqid_list).Exists() ) { + NCBI_THROW(CSeqDBException, eFileErr, seqid_list + " not found"); + } + } + const EAliasFileFilterType alias_type = (isTiList ? eTiList : eGiList); if (args["dblist"].HasValue() || args["dblist_file"].HasValue()) { vector dbs2aggregate = x_GetDbsToAggregate("dblist", "dblist_file"); @@ -326,11 +353,16 @@ CBlastDBAliasApp::CreateAliasFile() const static_cast(args["num_volumes"].AsInteger()); CWriteDB_CreateAliasFile(args[kOutput].AsString(), num_vols, seq_type, title); - } else if (args[kArgDb].HasValue()){ + } else if (args[kArgDb].HasValue() && args[kArgGiList]){ CWriteDB_CreateAliasFile(args[kOutput].AsString(), args[kArgDb].AsString(), seq_type, gilist, title, alias_type); + } else { + CWriteDB_CreateAliasFile(args[kOutput].AsString(), + args[kArgDb].AsString(), + seq_type, seqid_list, + title, eSeqIdList); } if (args["vdblist"].HasValue() || args["vdblist_file"].HasValue()) { @@ -425,6 +457,6 @@ int CBlastDBAliasApp::Run(void) #ifndef SKIP_DOXYGEN_PROCESSING int main(int argc, const char* argv[] /*, const char* envp[]*/) { - return CBlastDBAliasApp().AppMain(argc, argv, 0, eDS_Default, ""); + return CBlastDBAliasApp().AppMain(argc, argv); } #endif /* SKIP_DOXYGEN_PROCESSING */ diff --git a/c++/src/app/blastdb/blastdbcheck.cpp b/c++/src/app/blastdb/blastdbcheck.cpp index dd369920..802b7c25 100644 --- a/c++/src/app/blastdb/blastdbcheck.cpp +++ b/c++/src/app/blastdb/blastdbcheck.cpp @@ -1,4 +1,4 @@ -/* $Id: blastdbcheck.cpp 473030 2015-07-15 19:29:59Z camacho $ +/* $Id: blastdbcheck.cpp 492284 2016-02-16 16:55:37Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -1515,6 +1515,6 @@ void CBlastDbCheckApplication::Exit(void) int main(int argc, const char* argv[]) { // Execute main application function - return CBlastDbCheckApplication().AppMain(argc, argv, 0, eDS_Default, ""); + return CBlastDbCheckApplication().AppMain(argc, argv); #endif /* SKIP_DOXYGEN_PROCESSING */ } diff --git a/c++/src/app/blastdb/blastdbcmd.cpp b/c++/src/app/blastdb/blastdbcmd.cpp index 814e97a6..282c0eef 100644 --- a/c++/src/app/blastdb/blastdbcmd.cpp +++ b/c++/src/app/blastdb/blastdbcmd.cpp @@ -1,4 +1,4 @@ -/* $Id: blastdbcmd.cpp 489108 2016-01-08 15:13:21Z fongah2 $ +/* $Id: blastdbcmd.cpp 518486 2016-11-03 16:05:31Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -32,18 +32,13 @@ * successor to fastacmd from the C toolkit */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: blastdbcmd.cpp 489108 2016-01-08 15:13:21Z fongah2 $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include #include #include #include -#include +#include #include #include @@ -77,22 +72,22 @@ private: CRef m_BlastDb; /// Is the database protein bool m_DbIsProtein; - /// Sequence range, non-empty if provided as command line argument - TSeqRange m_SeqRange; - /// Strand to retrieve - ENa_strand m_Strand; /// output is FASTA bool m_FASTA; /// output is ASN.1 defline - bool m_Asn1DeflineOutput; + bool m_Asn1Bioseq; /// should we find duplicate entries? bool m_GetDuplicates; /// should we output target sequence only? bool m_TargetOnly; + CBlastDB_FormatterConfig m_Config; + /// Initializes the application's data members void x_InitApplicationData(); + string x_InitSearchRequest(); + /// Prints the BLAST database information (e.g.: handles -info command line /// option) void x_PrintBlastDatabaseInformation(); @@ -101,159 +96,192 @@ private: /// @return 0 on success; 1 if some sequences were not retrieved int x_ProcessSearchRequest(); - /// Vector of sequence identifiers in a BLAST database - typedef vector< CRef > TQueries; - - /// Extract the queries for the BLAST database from the command line - /// options - /// @param queries queries to retrieve [in|out] + /// Process batch entry with range, strand and filter id + /// @param args program input args + /// @param seq_fmt sequence formatter object /// @return 0 on sucess; 1 if some queries were not processed - int x_GetQueries(TQueries& queries) const; - - /// Add a query ID for processing - /// @param retval the return value where the queries will be added [in|out] - /// @param entry the user's query [in] - /// @return 0 on sucess; 1 if some seqid is not translated - int x_AddSeqId(CBlastDBCmdApp::TQueries& retval, const string& entry) const; + int x_ProcessBatchEntry(CBlastDB_Formatter & seq_fmt); - /// Add an OID for processing - /// @param retval the return value where the queries will be added [in|out] - /// @param entry the user's query [in] - void x_AddOid(CBlastDBCmdApp::TQueries& retval, const int oid, bool check=false) const; - - /// Process batch entry with range, strand and filter id + /// Process entry with range, strand and filter id /// @param args program input args /// @param seq_fmt sequence formatter object /// @return 0 on sucess; 1 if some queries were not processed - int x_ProcessBatchEntry(const CArgs& args, CSeqFormatter & seq_fmt); -}; + int x_ProcessEntry(CBlastDB_Formatter & fmt); -int -CBlastDBCmdApp::x_AddSeqId(CBlastDBCmdApp::TQueries& retval, - const string& entry) const -{ - // Process get dups - if (m_GetDuplicates) { - vector oids; - m_BlastDb->AccessionToOids(entry, oids); - ITERATE(vector, oid, oids) { - x_AddOid(retval, *oid, true); - } - return 0; - } + int x_ProcessSearchType(CBlastDB_Formatter & fmt); - // FASTA / target_only just need one id - if (m_TargetOnly) { - retval.push_back(CRef(new CBlastDBSeqId(entry))); - return 0; - } + bool x_GetOids(const string & acc, vector & oids); - // Default: find oid first and add all pertinent - vector oids; - m_BlastDb->AccessionToOids(entry, oids); - if (!oids.empty()) { - x_AddOid(retval, oids[0], true); - return 0; - } + int x_ModifyConfigForBatchEntry(const vector & tmp); + + bool x_UseLongSeqIds(); +}; - ERR_POST(Error << entry << ": OID not found"); - return 1; +bool +CBlastDBCmdApp::x_GetOids(const string & acc, vector & oids) +{ + Int8 num_id = NStr::StringToNumeric(acc, NStr::fConvErr_NoThrow); + if(!errno) { + int gi_oid = -1; + m_BlastDb->GiToOidwFilterCheck(num_id, gi_oid); + if(gi_oid < 0) { + m_BlastDb->AccessionToOids(acc, oids); + } + else { + oids.push_back(gi_oid); + } + + } + else { + m_BlastDb->AccessionToOids(acc, oids); + } + if(oids.empty()) { + ERR_POST(Error << "Entry not found: " << acc); + return false; + } + return true; } -void -CBlastDBCmdApp::x_AddOid(CBlastDBCmdApp::TQueries& retval, - const int oid, - bool check) const +int +CBlastDBCmdApp::x_ProcessEntry(CBlastDB_Formatter & fmt) { - // check to see if this oid has been excluded - if (check) { - list< CRef > filtered_ids = m_BlastDb->GetSeqIDs(oid); - if (filtered_ids.empty()) { - return; - } - } + unsigned int err_found = 0; + const CArgs& args = GetArgs(); + _ASSERT(m_BlastDb.NotEmpty()); - // FASTA output just need one id - if (m_FASTA || m_Asn1DeflineOutput) { - CRef blastdb_seqid(new CBlastDBSeqId()); - blastdb_seqid->SetOID(oid); - retval.push_back(blastdb_seqid); - return; + if (args["pig"].HasValue()) { + CSeqDB::TOID oid; + m_BlastDb->PigToOid(args["pig"].AsInteger(),oid); + fmt.Write(oid, m_Config); + } else if (args["entry"].HasValue()) { + static const string kDelim(","); + const string& entry = args["entry"].AsString(); + + vector queries; + if (entry.find(kDelim[0]) != string::npos) { + NStr::Split(entry, kDelim, queries, NStr::fSplit_NoMergeDelims); + } else { + queries.resize(1); + queries[0] = entry; + } + for(unsigned int i=0; i < queries.size(); i++) { + vector oids; + if(x_GetOids(queries[i], oids)) { + if (m_GetDuplicates) { + for(unsigned int j=0; j < oids.size(); j++) { + fmt.Write(oids[j], m_Config); + } + } + else { + if(m_TargetOnly) { + fmt.Write(oids[0], m_Config, queries[i]); + } + else { + fmt.Write(oids[0], m_Config); + } + } + } + else { + err_found ++; + } + } + if(err_found == queries.size()) { + NCBI_THROW(CInputException, eInvalidInput, + "Entry or entries not found in BLAST database"); + } } + return (err_found) ? 1:0; +} - // Not a NR database, add oid instead - vector gis; - m_BlastDb->GetGis(oid, gis); - if (gis.empty()) { - list< CRef > ids = m_BlastDb->GetSeqIDs(oid); - ITERATE(list< CRef > , id, ids) { - CRef blastdb_seqid(new CBlastDBSeqId((*id)->AsFastaString())); - retval.push_back(blastdb_seqid); +bool s_IsMaskAlgoIdValid(CSeqDB & blastdb, int id) +{ + if (id >= 0) { + vector algo_id(1, id); + vector invalid_algo_ids = blastdb.ValidateMaskAlgorithms(algo_id); + if ( !invalid_algo_ids.empty()) { + ERR_POST(Error << "Invalid filtering algorithm ID: " << NStr::IntToString(id)); + return false; + } } - return; - } + return true; +} - // Default: add all possible ids - ITERATE(vector, gi, gis) { - retval.push_back(CRef - (new CBlastDBSeqId(NStr::IntToString(GI_TO(TIntId, *gi))))); +int CBlastDBCmdApp::x_ModifyConfigForBatchEntry(const vector & tmp) +{ + int status = 0; + if (!m_DbIsProtein) { + m_Config.m_Strand = eNa_strand_plus; + } + m_Config.m_SeqRange = TSeqRange::GetEmpty(); + m_Config.m_FiltAlgoId = -1; + for(unsigned int i=1; i < tmp.size(); i++) { + if(tmp[i].find('-')!= string::npos) + { + try { + m_Config.m_SeqRange = ParseSequenceRangeOpenEnd(tmp[i]); + } catch (...) { + } + } + else if (!m_DbIsProtein && NStr::EqualNocase(tmp[i].c_str(), "minus")) { + m_Config.m_Strand = eNa_strand_minus; + } + else { + m_Config.m_FiltAlgoId = NStr::StringToNonNegativeInt(tmp[i]); + if(!s_IsMaskAlgoIdValid(*m_BlastDb, m_Config.m_FiltAlgoId)){ + status = 1; + } + } } + return status; } int -CBlastDBCmdApp::x_GetQueries(CBlastDBCmdApp::TQueries& retval) const +CBlastDBCmdApp::x_ProcessBatchEntry(CBlastDB_Formatter & fmt) { - int err_found = 0; - int err_here; - const CArgs& args = GetArgs(); - - retval.clear(); - - _ASSERT(m_BlastDb.NotEmpty()); - - if (args["pig"].HasValue()) { - retval.reserve(1); - retval.push_back(CRef - (new CBlastDBSeqId(args["pig"].AsInteger()))); + int err_found = 0; + const CArgs& args = GetArgs(); + CNcbiIstream& input = args["entry_batch"].AsInputFile(); - } else if (args["entry"].HasValue()) { + while (input) { + string line; + NcbiGetlineEOL(input, line); + if ( !line.empty() ) { + vector tmp; + NStr::Split(line, " \t", tmp, NStr::fSplit_MergeDelims); + if(tmp.empty()) { + continue; + } + if(x_ModifyConfigForBatchEntry(tmp)) { + err_found ++; + ERR_POST (Error << "Skipped " << tmp[0]); + continue; + } + vector oids; + if(!x_GetOids(tmp[0], oids)) { + err_found ++; + ERR_POST (Error << "Skipped " << tmp[0]); + continue; + } - static const string kDelim(","); - const string& entry = args["entry"].AsString(); - - if (entry.find(kDelim[0]) != string::npos) { - vector tokens; - NStr::Split(entry, kDelim, tokens, NStr::fSplit_NoMergeDelims); - ITERATE(vector, itr, tokens) { - err_found += (err_here = x_AddSeqId(retval, *itr)); - if (err_here) { - ERR_POST(Error << *itr << ": OID not found"); - } - } - } else if (entry == "all") { - for (int i = 0; m_BlastDb->CheckOrFindOID(i); i++) { - x_AddOid(retval, i); - } - } else { - err_found += (err_here = x_AddSeqId(retval, entry)); - if (err_here) { - ERR_POST(Error << entry << ": OID not found"); - } + if (m_GetDuplicates) { + for(unsigned int j=0; j < oids.size(); j++) { + fmt.Write(oids[j], m_Config); + } + } + else { + if(m_TargetOnly) { + fmt.Write(oids[0], m_Config, tmp[0]); + } + else { + fmt.Write(oids[0], m_Config); + } + } } - - } else { - NCBI_THROW(CInputException, eInvalidInput, - "Must specify query type: one of 'entry', 'entry_batch', or 'pig'"); } - - if (retval.empty()) { - NCBI_THROW(CInputException, eInvalidInput, - "Entry or entries not found in BLAST database"); - } - return (err_found) ? 1 : 0; } + void CBlastDBCmdApp::x_InitApplicationData() { @@ -261,28 +289,7 @@ CBlastDBCmdApp::x_InitApplicationData() CSeqDB::ESeqType seqtype = ParseMoleculeTypeString(args[kArgDbType].AsString()); m_BlastDb.Reset(new CSeqDBExpert(args[kArgDb].AsString(), seqtype)); - m_DbIsProtein = static_cast(m_BlastDb->GetSequenceType() == CSeqDB::eProtein); - - m_SeqRange = TSeqRange::GetEmpty(); - if (args["range"].HasValue()) { - m_SeqRange = ParseSequenceRangeOpenEnd(args["range"].AsString()); - } - - m_Strand = eNa_strand_unknown; - if (args["strand"].HasValue() && !m_DbIsProtein) { - if (args["strand"].AsString() == "plus") { - m_Strand = eNa_strand_plus; - } else if (args["strand"].AsString() == "minus") { - m_Strand = eNa_strand_minus; - } else { - abort(); // both strands not supported - } - } - - m_GetDuplicates = args["get_dups"]; - - m_TargetOnly = args["target_only"]; } void @@ -293,7 +300,7 @@ CBlastDBCmdApp::x_PrintBlastDatabaseInformation() const string kLetters = m_DbIsProtein ? "residues" : "bases"; const CArgs& args = GetArgs(); - CNcbiOstream& out = args["out"].AsOutputFile(); + CNcbiOstream& out = args[kArgOutput].AsOutputFile(); // Print basic database information out << "Database: " << m_BlastDb->GetTitle() << endl @@ -324,168 +331,159 @@ CBlastDBCmdApp::x_PrintBlastDatabaseInformation() } } -int -CBlastDBCmdApp::x_ProcessSearchRequest() +string +CBlastDBCmdApp::x_InitSearchRequest() { - const CArgs& args = GetArgs(); - CNcbiOstream& out = args["out"].AsOutputFile(); - - CSeqFormatterConfig conf; - conf.m_LineWidth = args["line_length"].AsInteger(); - conf.m_SeqRange = m_SeqRange; - conf.m_Strand = m_Strand; - conf.m_TargetOnly = m_TargetOnly; - conf.m_UseCtrlA = args["ctrl_a"]; - if (args["mask_sequence_with"].HasValue()) { - conf.m_FiltAlgoId = -1; - conf.m_FiltAlgoId = NStr::StringToInt(args["mask_sequence_with"].AsString(), NStr::fConvErr_NoThrow); - if(errno) - conf.m_FiltAlgoId = m_BlastDb->GetMaskAlgorithmId(args["mask_sequence_with"].AsString()); - } + const CArgs& args = GetArgs(); + m_GetDuplicates = args["get_dups"]; + m_TargetOnly = args["target_only"]; - string outfmt; + string outfmt = kEmptyStr; if (args["outfmt"].HasValue()) { - outfmt = args["outfmt"].AsString(); + outfmt = args["outfmt"].AsString(); m_FASTA = false; - m_Asn1DeflineOutput = false; + m_Asn1Bioseq = false; + + if ((outfmt.find("%f") != string::npos && + (outfmt.find("%b") != string::npos || outfmt.find("%d") != string::npos)) || + (outfmt.find("%b") != string::npos && outfmt.find("%d") != string::npos)) { + NCBI_THROW(CInputException, eInvalidInput, + "The %f, %b, %d output format options cannot be specified together."); + } - if (outfmt.find("%f") != string::npos && - outfmt.find("%d") != string::npos) { - NCBI_THROW(CInputException, eInvalidInput, - "The %d and %f output format options cannot be specified together."); + if (outfmt.find("%b") != string::npos) { + outfmt = "%b"; + m_Asn1Bioseq = true; } // If "%f" is found within outfmt, discard everything else if (outfmt.find("%f") != string::npos) { - outfmt = "%f"; - m_FASTA = true; + outfmt = "%f"; + m_FASTA = true; } - // If "%d" is found within outfmt, discard everything else + if (outfmt.find("%d") != string::npos) { - outfmt = "%d"; - m_Asn1DeflineOutput = true; + outfmt = "%d"; } + if (outfmt.find("%m") != string::npos) { - int algo_id = 0; - size_t i = outfmt.find("%m") + 2; - bool found = false; - while (i < outfmt.size() - && outfmt[i] >= '0' && outfmt[i] <= '9') { - algo_id = algo_id * 10 + (outfmt[i] - '0'); - outfmt.erase(i, 1); - found = true; + int algo_id = 0; + size_t i = outfmt.find("%m") + 2; + bool found = false; + while (i < outfmt.size() && outfmt[i] >= '0' && outfmt[i] <= '9') { + algo_id = algo_id * 10 + (outfmt[i] - '0'); + outfmt.erase(i, 1); + found = true; } if (!found) { - NCBI_THROW(CInputException, eInvalidInput, - "The option '-outfmt %m' is not followed by a masking algo ID."); + NCBI_THROW(CInputException, eInvalidInput, + "The option '-outfmt %m' is not followed by a masking algo ID."); } - conf.m_FmtAlgoId = algo_id; - } - } - - bool errors_found = false; - CSeqFormatter seq_fmt(outfmt, *m_BlastDb, out, conf); - - /* Special case: full db dump when no range and mask data is specified */ - if (m_FASTA && - args["entry"].HasValue() && args["entry"].AsString() == "all" && - ! args["mask_sequence_with"].HasValue() && - ! args["range"].HasValue()) { - - try { - seq_fmt.DumpAll(*m_BlastDb, conf); - } catch (const CException& e) { - ERR_POST(Error << e.GetMsg()); - errors_found = true; - } catch (...) { - ERR_POST(Error << "Failed to retrieve requested item"); - errors_found = true; + m_Config.m_FmtAlgoId = algo_id; + if(!s_IsMaskAlgoIdValid(*m_BlastDb, m_Config.m_FmtAlgoId)) { + NCBI_THROW(CInvalidDataException, eInvalidInput, + "Invalid filtering algorithm ID for outfmt %m."); + } } - return errors_found ? 1 : 0; } - if (args["entry_batch"].HasValue()) { - return x_ProcessBatchEntry(args, seq_fmt); + if (args["strand"].HasValue() && !m_DbIsProtein) { + if (args["strand"].AsString() == "plus") { + m_Config.m_Strand = eNa_strand_plus; + } else if (args["strand"].AsString() == "minus") { + m_Config.m_Strand = eNa_strand_minus; + } else { + NCBI_THROW(CInputException, eInvalidInput, + "Both strands is not supported"); + } } - - TQueries queries; - errors_found = (x_GetQueries(queries) > 0 ? true : false); - _ASSERT( !queries.empty() ); - - NON_CONST_ITERATE(TQueries, itr, queries) { - try { - seq_fmt.Write(**itr); - } catch (const CException& e) { - ERR_POST(Error << e.GetMsg()); - errors_found = true; - } catch (...) { - ERR_POST(Error << "Failed to retrieve requested item"); - errors_found = true; + m_Config.m_UseCtrlA = args["ctrl_a"]; + if (args["mask_sequence_with"].HasValue()) { + m_Config.m_FiltAlgoId = -1; + m_Config.m_FiltAlgoId = NStr::StringToInt(args["mask_sequence_with"].AsString(), NStr::fConvErr_NoThrow); + if(errno) { + m_Config.m_FiltAlgoId = m_BlastDb->GetMaskAlgorithmId(args["mask_sequence_with"].AsString()); } + if(!s_IsMaskAlgoIdValid(*m_BlastDb, m_Config.m_FiltAlgoId)){ + NCBI_THROW(CInvalidDataException, eInvalidInput, + "Invalid filtering algorithm ID for mask_sequence_with."); + } } - return errors_found ? 1 : 0; + if (args["range"].HasValue()) { + m_Config.m_SeqRange = ParseSequenceRangeOpenEnd(args["range"].AsString()); + } + return outfmt; } -int CBlastDBCmdApp::x_ProcessBatchEntry(const CArgs& args, CSeqFormatter & seq_fmt) +int +CBlastDBCmdApp::x_ProcessSearchType(CBlastDB_Formatter & fmt) { - CNcbiIstream& input = args["entry_batch"].AsInputFile(); - bool err_found = false; - while (input) { - string line; - NcbiGetlineEOL(input, line); - if ( !line.empty() ) { - vector tmp; - NStr::Split(line, " \t", tmp, NStr::fSplit_MergeDelims); - if(tmp.empty()) - continue; + const CArgs& args = GetArgs(); + if (args["entry"].HasValue() && args["entry"].AsString() == "all") { + fmt.DumpAll(m_Config); + } + else if (args["entry_batch"].HasValue()) { + return x_ProcessBatchEntry(fmt); + } + else if (args["entry"].HasValue() || args["pig"].HasValue()) { + return x_ProcessEntry(fmt); + } + else { + NCBI_THROW(CInputException, eInvalidInput, + "Must specify query type: one of 'entry', 'entry_batch', or 'pig'"); + } + return 0; +} - TQueries queries; - if(x_AddSeqId(queries, tmp[0]) > 0 ) - err_found = true; - - if(queries.empty()) - continue; - - TSeqRange seq_range(TSeqRange::GetEmpty()); - ENa_strand seq_strand = eNa_strand_plus; - int seq_algo_id = -1; - - for(unsigned int i=1; i < tmp.size(); i++) { - - if(tmp[i].find('-')!= string::npos) - { - try { - seq_range = ParseSequenceRangeOpenEnd(tmp[i]); - } catch (...) { - seq_range = TSeqRange::GetEmpty(); - } - } - else if (!m_DbIsProtein && NStr::EqualNocase(tmp[i].c_str(), "minus")) { - seq_strand = eNa_strand_minus; - } - else { - seq_algo_id = NStr::StringToNonNegativeInt(tmp[i]); - } - } +bool CBlastDBCmdApp::x_UseLongSeqIds() +{ + const CArgs& args = GetArgs(); + if (args["long_seqids"].AsBoolean()) { + return true; + } + CNcbiApplication* app = CNcbiApplication::Instance(); + if (app) { + const CNcbiRegistry& registry = app->GetConfig(); + if (registry.Get("BLAST", "LONG_SEQID") == "1") { + return true; + } + } + return false; +} - seq_fmt.SetConfig(seq_range, seq_strand, seq_algo_id); - NON_CONST_ITERATE(TQueries, itr, queries) { - try { - seq_fmt.Write(**itr); - } catch (const CException& e) { - ERR_POST(Error << e.GetMsg() << ": " << **itr); - err_found = true; - } catch (...) { - ERR_POST(Error << "Failed to retrieve requested item: " - << **itr); - err_found = true; - } - } - } +int +CBlastDBCmdApp::x_ProcessSearchRequest() +{ + int err_found = 0; + try { + const CArgs& args = GetArgs(); + CNcbiOstream& out = args[kArgOutput].AsOutputFile(); + string outfmt = x_InitSearchRequest(); + /* Special case: full db dump when no range and mask data is specified */ + if (m_FASTA) { + CBlastDB_FastaFormatter fasta_fmt(*m_BlastDb, out, args["line_length"].AsInteger(), x_UseLongSeqIds()); + err_found = x_ProcessSearchType(fasta_fmt); + } + else if (m_Asn1Bioseq) { + CBlastDB_BioseqFormatter bioseq_fmt(*m_BlastDb, out); + err_found = x_ProcessSearchType(bioseq_fmt); + } + else { + CBlastDB_SeqFormatter seq_fmt(outfmt, *m_BlastDb, out); + err_found = x_ProcessSearchType(seq_fmt); + } + } + catch (const CException& e) { + ERR_POST(Error << e.GetMsg()); + err_found = 1; + } catch (...) { + ERR_POST(Error << "Failed to retrieve requested item"); + err_found = 1; } - return err_found ? 1:0; + return err_found; } + void CBlastDBCmdApp::Init() { HideStdArgs(fHideConffile | fHideFullVersion | fHideXmlHelp | fHideDryRun); @@ -620,7 +618,7 @@ void CBlastDBCmdApp::Init() arg_desc->SetCurrentGroup("Output configuration options for FASTA format"); arg_desc->AddDefaultKey("line_length", "number", "Line length for output", CArgDescriptions::eInteger, - NStr::IntToString(CSeqFormatterConfig().m_LineWidth)); + NStr::IntToString(80)); arg_desc->SetConstraint("line_length", new CArgAllowValuesGreaterThanOrEqual(1)); @@ -679,6 +677,8 @@ void CBlastDBCmdApp::Init() arg_desc->AddFlag("exact_length", "Get exact length for db info", true); arg_desc->SetDependency("exact_length", CArgDescriptions::eRequires, "info"); + arg_desc->AddFlag("long_seqids", "Use long seq id for fasta deflines", true); + arg_desc->SetDependency("long_seqids", CArgDescriptions::eExcludes, "info"); SetupArgDescriptions(arg_desc.release()); } @@ -692,7 +692,6 @@ int CBlastDBCmdApp::Run(void) SetDiagPostLevel(eDiag_Warning); SetDiagPostPrefix("blastdbcmd"); - try { CNcbiOstream& out = args["out"].AsOutputFile(); if (args["show_blastdb_search_path"]) { @@ -717,11 +716,11 @@ int CBlastDBCmdApp::Run(void) } x_InitApplicationData(); - if (args["info"]) { x_PrintBlastDatabaseInformation(); } else { - status = x_ProcessSearchRequest(); + x_InitSearchRequest(); + status = x_ProcessSearchRequest(); } } CATCH_ALL(status) @@ -732,6 +731,6 @@ int CBlastDBCmdApp::Run(void) #ifndef SKIP_DOXYGEN_PROCESSING int main(int argc, const char* argv[] /*, const char* envp[]*/) { - return CBlastDBCmdApp().AppMain(argc, argv, 0, eDS_Default, ""); + return CBlastDBCmdApp().AppMain(argc, argv); } #endif /* SKIP_DOXYGEN_PROCESSING */ diff --git a/c++/src/app/blastdb/blastdbcp.cpp b/c++/src/app/blastdb/blastdbcp.cpp index fed381d0..bf09b926 100644 --- a/c++/src/app/blastdb/blastdbcp.cpp +++ b/c++/src/app/blastdb/blastdbcp.cpp @@ -1,4 +1,4 @@ -/* $Id: blastdbcp.cpp 485504 2015-11-23 14:41:02Z rackerst $ +/* $Id: blastdbcp.cpp 492284 2016-02-16 16:55:37Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -470,5 +470,5 @@ void BlastdbCopyApplication::Exit(void) int main(int argc, const char* argv[]) { // Execute main application function - return BlastdbCopyApplication().AppMain(argc, argv, 0, eDS_Default, ""); + return BlastdbCopyApplication().AppMain(argc, argv); } diff --git a/c++/src/app/blastdb/convert2blastmask.cpp b/c++/src/app/blastdb/convert2blastmask.cpp index cdf2340e..954ff686 100644 --- a/c++/src/app/blastdb/convert2blastmask.cpp +++ b/c++/src/app/blastdb/convert2blastmask.cpp @@ -1,4 +1,4 @@ -/* # $Id: convert2blastmask.cpp 473030 2015-07-15 19:29:59Z camacho $ +/* # $Id: convert2blastmask.cpp 492284 2016-02-16 16:55:37Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -230,7 +230,7 @@ void CConvert2BlastMaskApplication::Exit(void) int main(int argc, const char* argv[]) { // Execute main application function - return CConvert2BlastMaskApplication().AppMain(argc, argv, 0, eDS_Default, ""); + return CConvert2BlastMaskApplication().AppMain(argc, argv); } #endif /* SKIP_DOXYGEN_PROCESSING */ diff --git a/c++/src/app/blastdb/makeblastdb.cpp b/c++/src/app/blastdb/makeblastdb.cpp index a856a229..3cac9dba 100644 --- a/c++/src/app/blastdb/makeblastdb.cpp +++ b/c++/src/app/blastdb/makeblastdb.cpp @@ -1,4 +1,4 @@ -/* $Id: makeblastdb.cpp 488259 2015-12-29 14:32:15Z camacho $ +/* $Id: makeblastdb.cpp 516397 2016-10-13 12:26:46Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -32,11 +32,6 @@ * formatdb from the C toolkit */ -#ifndef SKIP_DOXYGEN_PROCESSING -static char const rcsid[] = - "$Id: makeblastdb.cpp 488259 2015-12-29 14:32:15Z camacho $"; -#endif /* SKIP_DOXYGEN_PROCESSING */ - #include #include #include @@ -816,7 +811,7 @@ void CMakeBlastDBApp::x_ProcessMaskData() vector gi_mask_names; if (! files.HasValue()) return; - NStr::Tokenize(NStr::TruncateSpaces(files.AsString()), ",", file_list, + NStr::Split(NStr::TruncateSpaces(files.AsString()), ",", file_list, NStr::eNoMergeDelims); if (! file_list.size()) { NCBI_THROW(CInvalidDataException, eInvalidInput, @@ -841,7 +836,7 @@ void CMakeBlastDBApp::x_ProcessMaskData() } if (descs.HasValue()) { - NStr::Tokenize(NStr::TruncateSpaces(descs.AsString()), ",", desc_list, + NStr::Split(NStr::TruncateSpaces(descs.AsString()), ",", desc_list, NStr::eNoMergeDelims); if (file_list.size() != desc_list.size()) { NCBI_THROW(CInvalidDataException, eInvalidInput, @@ -854,7 +849,7 @@ void CMakeBlastDBApp::x_ProcessMaskData() } if (gi_names.HasValue()) { - NStr::Tokenize(NStr::TruncateSpaces(gi_names.AsString()), ",", gi_mask_names, + NStr::Split(NStr::TruncateSpaces(gi_names.AsString()), ",", gi_mask_names, NStr::eNoMergeDelims); if (file_list.size() != gi_mask_names.size()) { NCBI_THROW(CInvalidDataException, eInvalidInput, @@ -1089,12 +1084,20 @@ void CMakeBlastDBApp::x_BuildDatabase() indexing |= (hash_index ? CWriteDB::eAddHash : 0); indexing |= (parse_seqids ? CWriteDB::eFullIndex : 0); + bool long_seqids = false; + CNcbiApplication* app = CNcbiApplication::Instance(); + if (app) { + const CNcbiRegistry& registry = app->GetConfig(); + long_seqids = (registry.Get("BLAST", "LONG_SEQID") == "1"); + } + m_DB.Reset(new CBuildDatabase(dbname, title, is_protein, indexing, use_gi_mask, - m_LogFile)); + m_LogFile, + long_seqids)); #if _BLAST_DEBUG if (args["verbose"]) { @@ -1163,6 +1166,6 @@ int CMakeBlastDBApp::Run(void) #ifndef SKIP_DOXYGEN_PROCESSING int main(int argc, const char* argv[] /*, const char* envp[]*/) { - return CMakeBlastDBApp().AppMain(argc, argv, 0, eDS_Default, ""); + return CMakeBlastDBApp().AppMain(argc, argv); } #endif /* SKIP_DOXYGEN_PROCESSING */ diff --git a/c++/src/app/blastdb/makeprofiledb.cpp b/c++/src/app/blastdb/makeprofiledb.cpp index efe8480e..9635f864 100644 --- a/c++/src/app/blastdb/makeprofiledb.cpp +++ b/c++/src/app/blastdb/makeprofiledb.cpp @@ -1,4 +1,4 @@ -/* $Id: makeprofiledb.cpp 489108 2016-01-08 15:13:21Z fongah2 $ +/* $Id: makeprofiledb.cpp 492284 2016-02-16 16:55:37Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -1710,7 +1710,7 @@ int CMakeProfileDBApp::Run(void) #ifndef SKIP_DOXYGEN_PROCESSING int main(int argc, const char* argv[] /*, const char* envp[]*/) { - return CMakeProfileDBApp().AppMain(argc, argv, 0, eDS_Default, ""); + return CMakeProfileDBApp().AppMain(argc, argv); } diff --git a/c++/src/app/dustmasker/Makefile.dustmasker.app b/c++/src/app/dustmasker/Makefile.dustmasker.app index c2c4892b..a85b0df8 100644 --- a/c++/src/app/dustmasker/Makefile.dustmasker.app +++ b/c++/src/app/dustmasker/Makefile.dustmasker.app @@ -1,4 +1,4 @@ -# $Id: Makefile.dustmasker.app 398472 2013-05-06 19:02:03Z kornbluh $ +# $Id: Makefile.dustmasker.app 500573 2016-05-05 16:42:41Z gouriano $ REQUIRES = objects algo @@ -8,7 +8,7 @@ APP = dustmasker SRC = main dust_mask_app LIB = xalgodustmask seqmasks_io $(OBJREAD_LIBS) xobjutil \ - $(OBJREAD_LIBS) seqdb blastdb $(OBJMGR_LIBS:%=%$(STATIC)) + seqdb blastdb $(OBJMGR_LIBS:%=%$(STATIC)) LIBS = $(CMPRS_LIBS) $(NETWORK_LIBS) $(DL_LIBS) $(ORIG_LIBS) diff --git a/c++/src/app/dustmasker/main.cpp b/c++/src/app/dustmasker/main.cpp index d5ea7582..fae1708c 100644 --- a/c++/src/app/dustmasker/main.cpp +++ b/c++/src/app/dustmasker/main.cpp @@ -1,4 +1,4 @@ -/* $Id: main.cpp 473030 2015-07-15 19:29:59Z camacho $ +/* $Id: main.cpp 492284 2016-02-16 16:55:37Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -38,5 +38,5 @@ USING_NCBI_SCOPE; int main( int argc, char * argv[] ) { - return CDustMaskApplication().AppMain(argc, argv, 0, eDS_Default, ""); + return CDustMaskApplication().AppMain(argc, argv); } diff --git a/c++/src/app/segmasker/Makefile.segmasker.app b/c++/src/app/segmasker/Makefile.segmasker.app index 9fb7ee7d..48561b76 100644 --- a/c++/src/app/segmasker/Makefile.segmasker.app +++ b/c++/src/app/segmasker/Makefile.segmasker.app @@ -1,4 +1,4 @@ -# $Id: Makefile.segmasker.app 208957 2010-10-21 19:23:10Z camacho $ +# $Id: Makefile.segmasker.app 500573 2016-05-05 16:42:41Z gouriano $ REQUIRES = objects algo @@ -7,7 +7,7 @@ ASN_DEP = seq APP = segmasker SRC = segmasker -LIB_ = xobjsimple seqmasks_io xalgosegmask $(BLAST_LIBS) $(OBJMGR_LIBS) +LIB_ = xobjsimple xalgosegmask $(BLAST_LIBS) $(OBJMGR_LIBS) LIB = $(LIB_:%=%$(STATIC)) LIBS = $(CMPRS_LIBS) $(NETWORK_LIBS) $(DL_LIBS) $(ORIG_LIBS) diff --git a/c++/src/app/segmasker/segmasker.cpp b/c++/src/app/segmasker/segmasker.cpp index 51cb1838..8d1af222 100644 --- a/c++/src/app/segmasker/segmasker.cpp +++ b/c++/src/app/segmasker/segmasker.cpp @@ -1,4 +1,4 @@ -/* $Id: segmasker.cpp 473030 2015-07-15 19:29:59Z camacho $ +/* $Id: segmasker.cpp 492284 2016-02-16 16:55:37Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -269,7 +269,7 @@ void SegMaskerApplication::Exit(void) int main(int argc, const char* argv[]) { // Execute main application function - return SegMaskerApplication().AppMain(argc, argv, 0, eDS_Default, ""); + return SegMaskerApplication().AppMain(argc, argv); } #endif /* SKIP_DOXYGEN_PROCESSING */ diff --git a/c++/src/app/winmasker/Makefile.winmasker.app b/c++/src/app/winmasker/Makefile.winmasker.app index b780f7a2..eb68d9de 100644 --- a/c++/src/app/winmasker/Makefile.winmasker.app +++ b/c++/src/app/winmasker/Makefile.winmasker.app @@ -1,4 +1,4 @@ -# $Id: Makefile.winmasker.app 398558 2013-05-07 11:21:36Z kornbluh $ +# $Id: Makefile.winmasker.app 500573 2016-05-05 16:42:41Z gouriano $ WATCHERS = morgulis camacho mozese2 @@ -9,8 +9,8 @@ ASN_DEP = seq APP = windowmasker SRC = main win_mask_app win_mask_sdust_masker -LIB = xalgowinmask xalgodustmask blast composition_adjustment seqdb blastdb \ - seqmasks_io tables $(OBJREAD_LIBS) xobjutil \ +LIB = xalgowinmask xalgodustmask blast composition_adjustment \ + seqmasks_io seqdb blastdb tables $(OBJREAD_LIBS) xobjutil \ $(OBJMGR_LIBS:%=%$(STATIC)) LIBS = $(CMPRS_LIBS) $(NETWORK_LIBS) $(DL_LIBS) $(ORIG_LIBS) diff --git a/c++/src/app/winmasker/main.cpp b/c++/src/app/winmasker/main.cpp index 0ddf8ba3..c062f2d6 100644 --- a/c++/src/app/winmasker/main.cpp +++ b/c++/src/app/winmasker/main.cpp @@ -1,4 +1,4 @@ -/* $Id: main.cpp 473030 2015-07-15 19:29:59Z camacho $ +/* $Id: main.cpp 492284 2016-02-16 16:55:37Z camacho $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -38,5 +38,5 @@ USING_NCBI_SCOPE; int main( int argc, char * argv[] ) { - return CWinMaskApplication().AppMain(argc, argv, 0, eDS_Default, ""); + return CWinMaskApplication().AppMain(argc, argv); } diff --git a/c++/src/build-system/Makefile.app.in b/c++/src/build-system/Makefile.app.in index 7555933c..27768b04 100644 --- a/c++/src/build-system/Makefile.app.in +++ b/c++/src/build-system/Makefile.app.in @@ -1,6 +1,6 @@ # -*- makefile-gmake -*- ################################# -# $Id: Makefile.app.in 492296 2016-02-16 17:41:47Z ivanov $ +# $Id: Makefile.app.in 492189 2016-02-12 20:50:52Z ucko $ # Author: Denis Vakatov (vakatov@ncbi.nlm.nih.gov) ################################# # This can be used to build/install/clean diff --git a/c++/src/build-system/Makefile.meta_l b/c++/src/build-system/Makefile.meta_l index d16157db..db20437e 100644 --- a/c++/src/build-system/Makefile.meta_l +++ b/c++/src/build-system/Makefile.meta_l @@ -1,5 +1,5 @@ # -*- makefile-gmake -*- -# $Id: Makefile.meta_l 487127 2015-12-15 17:04:00Z ivanov $ +# $Id: Makefile.meta_l 507305 2016-07-18 16:19:28Z ucko $ ### Rules for building within a single directory @@ -81,6 +81,7 @@ endif # 1: proj_name, 2: lock_map?, 3: command, 4: target, 5: ext, 6: cleanup, # 7: error_status, 8: is_expendable? define make_one_leaf_proj +NCBICXX_TESTING_REQS=1 $(3) -q requirements REQUIRES= && \ $(if $(8),NCBI_BUT_EXPENDABLE=$(but_exp);,) \ if NCBICXX_TESTING_REQS=1 $(3) -q requirements; then \ if $(3) -q depend >/dev/null 2>&1 && $(3) -q $(4) >/dev/null 2>&1; then \ @@ -207,6 +208,7 @@ endif # 1: proj_name define add_one_check @i=$(1) ; \ +NCBICXX_TESTING_REQS=1 $(MAKE_APP) -q requirements REQUIRES= && \ if NCBICXX_TESTING_REQS=1 $(MAKE_APP) -q requirements >/dev/null 2>&1; then \ $(check_add) $(abs_srcdir) $(1) $(signature) $(subdir) || exit 5 ; \ else \ diff --git a/c++/src/build-system/Makefile.mk.in b/c++/src/build-system/Makefile.mk.in index 755b876c..e05b5c39 100644 --- a/c++/src/build-system/Makefile.mk.in +++ b/c++/src/build-system/Makefile.mk.in @@ -1,5 +1,5 @@ ################################# -# $Id: Makefile.mk.in 493416 2016-02-26 18:48:41Z ivanov $ +# $Id: Makefile.mk.in 512372 2016-08-30 14:51:36Z ivanov $ # Author: Denis Vakatov (vakatov@ncbi.nlm.nih.gov) ################################# # @@ -152,7 +152,8 @@ CXXCPP = $(CONF_CXXCPP) AR = $(CONF_AR) RANLIB = $(CONF_RANLIB) LINK = $(CONF_LINK) -C_LINK = $(CONF_C_LINK) # Linker for pure-C programs +# Linker for pure-C programs +C_LINK = $(CONF_C_LINK) STRIP = $(CONF_STRIP) CFLAGS = $(CONF_CFLAGS) @@ -164,7 +165,8 @@ LDFLAGS = $(CONF_LDFLAGS) APP_LDFLAGS = $(CONF_APP_LDFLAGS) DLL_LDFLAGS = $(CONF_DLL_LDFLAGS) LIBS = $(CONF_LIBS) -C_LIBS = $(CONF_C_LIBS) # Libraries for pure-C programs +# Libraries for pure-C programs +C_LIBS = $(CONF_C_LIBS) PRE_LIBS = # To add directory /foo to the list to search at runtime, you can add @@ -516,11 +518,20 @@ NCBILS_LIB = $(NCBILS2_LIB) # NCBI SRA/VDB Toolkit VDB_INCLUDE = @VDB_INCLUDE@ -VDB_LIB = @VDB_LIB@ VDB_LIBS = @VDB_LIBS@ VDB_STATIC_LIBS = @VDB_STATIC_LIBS@ VDB_REQ = @VDB_REQ@ VDB_POST_LINK = @VDB_POST_LINK@ +bamread = @bamread@ +sraread = @sraread@ +ncbi_id2proc_snp = @ncbi_id2proc_snp@ +ncbi_id2proc_wgs = @ncbi_id2proc_wgs@ +ncbi_xloader_bam = @ncbi_xloader_bam@ +ncbi_xloader_csra = @ncbi_xloader_csra@ +ncbi_xloader_snp = @ncbi_xloader_snp@ +ncbi_xloader_sra = @ncbi_xloader_sra@ +ncbi_xloader_vdbgraph = @ncbi_xloader_vdbgraph@ +ncbi_xloader_wgs = @ncbi_xloader_wgs@ # SP: headers, libraries SP_INCLUDE = @SP_INCLUDE@ @@ -652,6 +663,14 @@ MONGODB_STATIC_LIBS = @MONGODB_STATIC_LIBS@ GMOCK_INCLUDE = @GMOCK_INCLUDE@ GMOCK_LIBS = @GMOCK_LIBS@ +# LAPACK +LAPACK_INCLUDE = @LAPACK_INCLUDE@ +LAPACK_LIBS = @LAPACK_LIBS@ + +# LMDB +LMDB_INCLUDE = @LMDB_INCLUDE@ +LMDB_LIBS = @LMDB_LIBS@ + # Compress COMPRESS_LDEP = $(CMPRS_LIB) COMPRESS_LIBS = xcompress $(COMPRESS_LDEP) @@ -669,7 +688,7 @@ GENBANK_READER_LIBS = ncbi_xreader $(GENBANK_READER_LDEP) # In-house-only PubSeqOS loader (not always built) ncbi_xreader_pubseqos = @ncbi_xreader_pubseqos@ ncbi_xreader_pubseqos2 = @ncbi_xreader_pubseqos2@ -GENBANK_READER_PUBSEQOS_LDEP = $(XCONNEXT) xconnect $(DBAPI_DRIVER) $(GENBANK_READER_LIBS) +GENBANK_READER_PUBSEQOS_LDEP = $(DBAPI_DRIVER) $(GENBANK_READER_LIBS) # @UNLESS_PUBSEQOS@ GENBANK_READER_PUBSEQOS_LDEP = xconnect $(GENBANK_READER_LIBS) GENBANK_READER_PUBSEQOS_LIBS = $(ncbi_xreader_pubseqos) $(GENBANK_READER_PUBSEQOS_LDEP) @@ -712,3 +731,15 @@ XFORMAT_LIBS = xformat xcleanup gbseq submit mlacli mla medlars pubmed valid tax # object editing library OBJEDIT_LIBS = xobjedit $(OBJREAD_LIBS) taxon3 + +# standard data loader configuration, plus supporting libraries +DATA_LOADERS_UTIL_LIB = data_loaders_util \ + ncbi_xloader_asn_cache asn_cache bdb \ + ncbi_xloader_lds2 lds2 $(OBJREAD_LIBS) sqlitewrapp \ + ncbi_xloader_blastdb seqdb blastdb \ + $(ncbi_xreader_pubseqos2) ncbi_xdbapi_ftds $(FTDS_LIB) \ + $(ncbi_xloader_wgs) $(ncbi_xloader_csra) \ + $(SRAREAD_LIBS) + +DATA_LOADERS_UTIL_LIBS = $(BERKELEYDB_LIBS) $(SQLITE3_LIBS) $(FTDS_LIBS) \ + $(VDB_LIBS) diff --git a/c++/src/build-system/Makefile.rules.in b/c++/src/build-system/Makefile.rules.in index 37814f32..3d5a2798 100644 --- a/c++/src/build-system/Makefile.rules.in +++ b/c++/src/build-system/Makefile.rules.in @@ -1,5 +1,5 @@ ################################# -# $Id: Makefile.rules.in 493416 2016-02-26 18:48:41Z ivanov $ +# $Id: Makefile.rules.in 497672 2016-04-08 18:34:20Z ucko $ # Author: Denis Vakatov (vakatov@ncbi.nlm.nih.gov), # Aaron Ucko (ucko@ncbi.nlm.nih.gov) ################################# @@ -113,7 +113,7 @@ clean-common: -$(RMDIR) ii_files -$(RMDIR) ti_files -$(RM) .make.state - -$(RM) $(SOURCES:=.d) + -$(RM) $(SOURCES:=.d) $(SOURCES:=.gcda) $(SOURCES:=.gcno) -$(RM) ir.out ifeq "$(APP)" "" -$(RM) $(status_dir)/.$(LIB).disabled diff --git a/c++/src/build-system/NEWS b/c++/src/build-system/NEWS index d867b999..ab2c7219 100644 --- a/c++/src/build-system/NEWS +++ b/c++/src/build-system/NEWS @@ -19,3 +19,5 @@ installations. 2015-06-01: additional @VDB_*@ variables @VDB_REQ@ and @VDB_POST_LINK@. 2015-12-17: new variables for FreeTDS 0.95. + +2016-06-20: variables for libraries dependent on SRA/VDB. diff --git a/c++/src/build-system/aclocal.m4 b/c++/src/build-system/aclocal.m4 index 58ac6e4d..ddf1fced 100644 --- a/c++/src/build-system/aclocal.m4 +++ b/c++/src/build-system/aclocal.m4 @@ -268,17 +268,16 @@ AC_DEFUN(_NCBI_CHECK_PYTHON, [AC_PATH_PROG($1, python$2, [], [${PYTHON_PATH+$PYTHON_PATH/bin:}$PATH:/usr/local/python-$2/bin]) if test -x "[$]$1"; then - $1_VERSION=`[$]$1 -c 'from distutils import sysconfig; print(sysconfig.get_config_var("VERSION"))' 2>/dev/null` + pyconf="$real_srcdir/scripts/common/impl/python-config.py" + $1_VERSION=`DYLD_BIND_AT_LAUNCH=1 "[$]$1" "$pyconf" --version 2>&AS_MESSAGE_LOG_FD` else $1_VERSION= [ncbi_cv_lib_]m4_tolower($1)=no fi if test -n "[$]$1_VERSION"; then - $1_INCLUDE=`[$]$1 -c 'from distutils import sysconfig; f=sysconfig.get_python_inc; print("-I%s -I%s" % (f(), f(True)))'` - $1_LIBPATH=`[$]$1 -c 'from distutils import sysconfig; print(" ".join(sysconfig.get_config_vars("LIBDIR", "LIBPL")))'` - $1_DEPS=`[$]$1 -c 'from distutils import sysconfig; print(" ".join(sysconfig.get_config_vars("LIBS", "SYSLIBS")))'` - $1_LDVERSION=`[$]$1 -c 'from distutils import sysconfig; print(sysconfig.get_config_var("LDVERSION") or sysconfig.get_config_var("VERSION"))' 2>/dev/null` - NCBI_RPATHIFY($1_LIBS, [$]$1_LIBPATH, [ ]-lpython[$]$1_LDVERSION [$]$1_DEPS) + $1_INCLUDE=`"[$]$1" "$pyconf" --include` + $1_LIBPATH=`"[$]$1" "$pyconf" --libpath` + NCBI_RPATHIFY($1_LIBS, [$]$1_LIBPATH, [ ]`"[$]$1" "$pyconf" --libs`) CPPFLAGS="[$]$1_INCLUDE $orig_CPPFLAGS" LIBS="[$]$1_LIBS $orig_LIBS" AC_CACHE_CHECK([for usable Python [$]$1_VERSION libraries], @@ -296,6 +295,7 @@ AC_DEFUN(_NCBI_CHECK_PYTHON, [[ncbi_cv_lib_]m4_tolower($1)=yes], [[ncbi_cv_lib_]m4_tolower($1)=no])]) else + $1= [ncbi_cv_lib_]m4_tolower($1)=no fi if test "[$ncbi_cv_lib_]m4_tolower($1)" = "no"; then @@ -314,7 +314,7 @@ AC_DEFUN(NCBI_LOCAL_FTDS, if test $try_local = yes -a -f "${real_srcdir}/src/$d/Makefile.in" ; then test "$ftds_ver" = $1 && FTDS_PATH="<$d>" FTDS$1[_CTLIB_LIB]="ct_ftds$1${STATIC} tds_ftds$1${STATIC}" - FTDS$1[_CTLIB_LIBS]='$(ICONV_LIBS) $(KRB5_LIBS)' + FTDS$1[_CTLIB_LIBS]='$(ICONV_LIBS) $(KRB5_LIBS) $(NETWORK_LIBS)' FTDS$1[_CTLIB_INCLUDE]="-I\$(includedir)/$d -I\$(includedir0)/$d" freetds=freetds elif test -d "$FTDS_PATH" ; then diff --git a/c++/src/build-system/config.h.in b/c++/src/build-system/config.h.in index 422f58ea..ff0e35b8 100644 --- a/c++/src/build-system/config.h.in +++ b/c++/src/build-system/config.h.in @@ -3,6 +3,9 @@ /* Define to 1 if necessary to get FIONBIO (e.g., on Solaris) */ #undef BSD_COMP +/* Define to 1 if you have the header file. */ +#undef HAVE_ACCELERATE_ACCELERATE_H + /* Define to 1 if you have the `alarm' function. */ #undef HAVE_ALARM @@ -65,6 +68,12 @@ /* Define to 1 if the `Boost.Thread' library is available. */ #undef HAVE_BOOST_THREAD +/* Define to 1 if you have the header file. */ +#undef HAVE_CLAPACK_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_COMMON_NCBI_BUILD_VER_H + /* Define to 1 if the preprocessor supports GNU-style variadic macros. */ #undef HAVE_CPP_GNU_VARARGS @@ -203,6 +212,12 @@ /* Define to 1 if you have `ios(_base)::register_callback'. */ #undef HAVE_IOS_REGISTER_CALLBACK +/* Define to 1 if you have the header file. */ +#undef HAVE_LAPACKE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LAPACKE_LAPACKE_H + /* Define to 1 if you have the `lchown' function. */ #undef HAVE_LCHOWN @@ -290,6 +305,12 @@ the standard libraries. */ #undef HAVE_LIBKSTAT +/* Define to 1 if liblapack is available. */ +#undef HAVE_LIBLAPACK + +/* Define to 1 if liblmdb is available. */ +#undef HAVE_LIBLMDB + /* Define to 1 if liblzo2 is available. */ #undef HAVE_LIBLZO @@ -415,6 +436,9 @@ /* Define to 1 if the real version of ncbi_crypt support is available. */ #undef HAVE_NCBI_CRYPT +/* Define to 1 if you have NCBI's SRA/VDB SDK/Toolkit. */ +#undef HAVE_NCBI_VDB + /* Define to 1 if you have the header file. */ #undef HAVE_NETDB_H @@ -484,6 +508,9 @@ /* Define to 1 if Python 2.7 libraries are available. */ #undef HAVE_PYTHON27 +/* Define to 1 if Python 3 libraries are available. */ +#undef HAVE_PYTHON3 + /* Define to 1 if you have the `readpassphrase' function. */ #undef HAVE_READPASSPHRASE @@ -709,6 +736,9 @@ /* Define to 1 if Zorba is available. */ #undef HAVE_ZORBA +/* Define to 1 if the system has the type `__CLPK_integer'. */ +#undef HAVE___CLPK_INTEGER + /* Full GNU-style system type */ #undef HOST @@ -870,9 +900,6 @@ variables, or leave undefined if it doesn't. */ #undef NCBI_TLS_VAR -/* Define to 1 if building universal (multi-architecture) binaries. */ -#undef NCBI_UNIVERSAL_BUILD - /* Define to 1 if building plugins as bundles, as Mac OS X traditionally required. */ #undef NCBI_USE_BUNDLES diff --git a/c++/src/build-system/configure b/c++/src/build-system/configure index 5749672e..b5294eae 100755 --- a/c++/src/build-system/configure +++ b/c++/src/build-system/configure @@ -829,6 +829,10 @@ MONGODB_INCLUDE MONGODB_LIBS GMOCK_INCLUDE GMOCK_LIBS +LAPACK_INCLUDE +LAPACK_LIBS +LMDB_INCLUDE +LMDB_LIBS signature build_root top_srcdir @@ -1004,9 +1008,18 @@ LIBSSSUTILS LIBSSSDB sssutils VDB_INCLUDE -VDB_LIB VDB_LIBS VDB_STATIC_LIBS +bamread +sraread +ncbi_id2proc_snp +ncbi_id2proc_wgs +ncbi_xloader_bam +ncbi_xloader_csra +ncbi_xloader_snp +ncbi_xloader_sra +ncbi_xloader_vdbgraph +ncbi_xloader_wgs VDB_REQ VDB_POST_LINK SP_INCLUDE @@ -1076,6 +1089,9 @@ compiler_version COMPILER OSTYPE NCBI_PLATFORM_BITS +NCBI_TEAMCITY_BUILD_NUMBER +NCBI_SUBVERSION_REVISION +NCBI_SC_VERSION LIBOBJS LTLIBOBJS' ac_subst_files='' @@ -1591,21 +1607,21 @@ esac #### Check the passed arguments against the list of available ones x_with_list="\ debug max-debug symbols optimization profiling tcheck dll static static-exe \ -plugin-auto-load bundles bin-release mt 64 universal exe runpath hard-runpath \ +plugin-auto-load bundles bin-release mt 64 exe runpath hard-runpath \ lfs limited-linker openmp \ autodep suffix hostspec version execopy bincopy lib-rebuilds lib-rebuilds=ask \ deactivation makefile-auto-update projects flat-makefile configure-dialog \ check ncbi-public strip pch caution ccache distcc \ ncbi-c wxwidgets wxwidgets-ucs fastcgi sss sssdb sssutils included-sss \ -geo included-geo vdb downloaded-vdb \ -z bz2 lzo pcre gmp gcrypt nettle gnutls openssl krb5 \ +geo included-geo vdb downloaded-vdb static-vdb \ +z bz2 lzo pcre gmp gcrypt nettle gnutls static-gnutls openssl krb5 \ sybase sybase-local sybase-new ftds mysql \ orbacus freetype ftgl opengl mesa glut glew glew-mx \ bdb python perl jni sqlite3 icu boost boost-tag \ sp expat sablot libxml libxslt libexslt xerces xalan zorba \ oechem sge muparser hdf5 \ gif jpeg tiff png xpm \ -magic curl mimetic gsoap avro cereal sasl2 mongodb gmock 3psw \ +magic curl mimetic gsoap avro cereal sasl2 mongodb gmock lapack lmdb 3psw \ local-lbsm ncbi-crypt connext \ serial objects dbapi app ctools gui algo internal gbench" @@ -1675,7 +1691,7 @@ for x_arg in "$@" ; do | --with-jpeg=* | --with-png=* | --with-tiff=* | --with-xpm=* \ | --with-magic=* | --with-curl=* | --with-mimetic=* | --with-gsoap=* \ | --with-avro=* | --with-cereal=* | --with-sasl2* | --with-mongodb=* \ - | --with-gmock=* ) + | --with-gmock=* | --with-lapack=* | --with-lmdb=* ) # Confirm that the specified directory exists and is readable. dir=`echo $x_arg | sed -e 's/^[^=]*=//'` case "$x_arg" in @@ -1699,7 +1715,7 @@ for x_arg in "$@" ; do | --silent | --cache-file=* | -C | --config-cache | -n | --no-create \ | --no-recursion | --prefix=* | --exec-prefix=* | --bindir=* \ | --libdir=* | --includedir=* | --build=* | --host=* | --target=* \ - | --with-universal=* | --with-runpath=* | --with-relative-runpath=* \ + | --with-runpath=* | --with-relative-runpath=* \ | --with-experimental=* | --with-extra-action=* | --with-build-root=* \ | --with-fake-root=* | --with-build-root-sfx=* | --with-check=* \ | --with-check-tools=* | --with-ftds=[0-9]* | --with-fastcgi=[0-9]* \ @@ -1820,8 +1836,6 @@ Optional Packages: --without-mt support only single-threaded operation --with-openmp enable OpenMP extensions for all projects --with-64 compile to 64-bit code - --with-universal build universal binaries on Mac OS X - --with-universal=CPUs build universal binaries targeting the given CPUs --without-exe do not build executables --with-runpath=PATH specify the usual runtime path to DLLs --with-relative-runpath=P specify an executable-relative DLL search path @@ -1866,6 +1880,7 @@ Optional Packages: --with-vdb=DIR use NCBI SRA/VDB Toolkit installation in DIR --without-vdb do not use the NCBI SRA/VDB Toolkit --with-downloaded-vdb download and build SRA/VDB from GitHub + --with-static-vdb always link statically against SRA/VDB --with-z=DIR use zlib installation in DIR --without-z use internal copy of zlib --with-bz2=DIR use bzlib installation in DIR @@ -1882,6 +1897,7 @@ Optional Packages: --without-nettle do not use Nettle --with-gnutls=DIR use GNUTLS installation in DIR --without-gnutls do not use GNUTLS + --with-static-gnutls link GNUTLS statically if possible --with-openssl=DIR use OpenSSL installation in DIR --without-openssl do not use OpenSSL --with-krb5=DIR use Kerberos 5 installation in DIR @@ -1986,6 +2002,10 @@ Optional Packages: --without-mongodb do not use MongoDB --with-gmock=DIR use Google Mock installation in DIR --without-gmock do not use Google Mock + --with-lapack=DIR use LAPACK installation in DIR + --without-lapack do not use LAPACK + --with-lmdb=DIR use LMDB installation in DIR + --without-lmdb do not use LMDB --with-3psw=std:netopt favor standard (system) builds of the above pkgs. --without-3psw do not use any of the above packages --without-local-lbsm turn off support for IPC with locally running LBSMD @@ -2245,6 +2265,12 @@ case "$with_3psw" in else with_boost=no fi + if test "${with_lmdb-no}" != "no"; then + { echo "$as_me: error: incompatible options: --with-lmdb but --without-3psw" >&2 + { (exit 1); exit 1; }; } + else + with_lmdb=no + fi if test "${with_sybase-no}" != "no"; then { echo "$as_me: error: incompatible options: --with-sybase but --without-3psw" >&2 { (exit 1); exit 1; }; } @@ -2521,6 +2547,12 @@ case "$with_3psw" in else with_gmock=no fi + if test "${with_lapack-no}" != "no"; then + { echo "$as_me: error: incompatible options: --with-lapack but --without-3psw" >&2 + { (exit 1); exit 1; }; } + else + with_lapack=no + fi $as_unset NCBI || test "${NCBI+set}" != set || { NCBI=; export NCBI; } ;; @@ -2999,18 +3031,6 @@ if test "${with_64+set}" = set; then fi -# Check whether --with-universal was given. -if test "${with_universal+set}" = set; then - withval=$with_universal; -fi - - -# Check whether --with-universal2 was given. -if test "${with_universal2+set}" = set; then - withval=$with_universal2; -fi - - # Check whether --with-exe was given. if test "${with_exe+set}" = set; then withval=$with_exe; @@ -3278,6 +3298,12 @@ if test "${with_downloaded_vdb+set}" = set; then fi +# Check whether --with-static-vdb was given. +if test "${with_static_vdb+set}" = set; then + withval=$with_static_vdb; +fi + + ## Third-party and system packages # Check whether --with-z was given. @@ -3376,6 +3402,12 @@ if test "${with_gnutls2+set}" = set; then fi +# Check whether --with-static-gnutls was given. +if test "${with_static_gnutls+set}" = set; then + withval=$with_static_gnutls; +fi + + # Check whether --with-openssl was given. if test "${with_openssl+set}" = set; then withval=$with_openssl; @@ -4000,6 +4032,30 @@ if test "${with_gmock2+set}" = set; then fi +# Check whether --with-lapack was given. +if test "${with_lapack+set}" = set; then + withval=$with_lapack; +fi + + +# Check whether --with-lapack2 was given. +if test "${with_lapack2+set}" = set; then + withval=$with_lapack2; +fi + + +# Check whether --with-lmdb was given. +if test "${with_lmdb+set}" = set; then + withval=$with_lmdb; +fi + + +# Check whether --with-lmdb was given. +if test "${with_lmdb+set}" = set; then + withval=$with_lmdb; +fi + + # Check whether --with-3psw was given. if test "${with_3psw+set}" = set; then withval=$with_3psw; @@ -4116,56 +4172,105 @@ if test "$with_gbench" = "yes" ; then echo "$as_me: error: incompatible options: --without-dll but --with-gbench" >&2;} { (exit 1); exit 1; }; } else - with_dll=yes + : ${with_dll:=yes} fi if test "$with_mt" = "no"; then { { echo "$as_me:$LINENO: error: incompatible options: --without-mt but --with-gbench" >&5 echo "$as_me: error: incompatible options: --without-mt but --with-gbench" >&2;} { (exit 1); exit 1; }; } else - with_mt=yes + : ${with_mt:=yes} fi if test "$with_gui" = "no"; then { { echo "$as_me:$LINENO: error: incompatible options: --without-gui but --with-gbench" >&5 echo "$as_me: error: incompatible options: --without-gui but --with-gbench" >&2;} { (exit 1); exit 1; }; } else - with_gui=yes + : ${with_gui:=yes} fi if test "$with_exe" = "no"; then { { echo "$as_me:$LINENO: error: incompatible options: --without-exe but --with-gbench" >&5 echo "$as_me: error: incompatible options: --without-exe but --with-gbench" >&2;} { (exit 1); exit 1; }; } else - with_exe=yes + : ${with_exe:=yes} fi if test "$with_serial" = "no"; then { { echo "$as_me:$LINENO: error: incompatible options: --without-serial but --with-gbench" >&5 echo "$as_me: error: incompatible options: --without-serial but --with-gbench" >&2;} { (exit 1); exit 1; }; } else - with_serial=yes + : ${with_serial:=yes} fi if test "$with_objects" = "no"; then { { echo "$as_me:$LINENO: error: incompatible options: --without-objects but --with-gbench" >&5 echo "$as_me: error: incompatible options: --without-objects but --with-gbench" >&2;} { (exit 1); exit 1; }; } else - with_objects=yes + : ${with_objects:=yes} fi if test "$with_algo" = "no"; then { { echo "$as_me:$LINENO: error: incompatible options: --without-algo but --with-gbench" >&5 echo "$as_me: error: incompatible options: --without-algo but --with-gbench" >&2;} { (exit 1); exit 1; }; } else - with_algo=yes + : ${with_algo:=yes} fi if test "$with_glew_mx" = "no"; then { { echo "$as_me:$LINENO: error: incompatible options: --without-glew_mx but --with-gbench" >&5 echo "$as_me: error: incompatible options: --without-glew_mx but --with-gbench" >&2;} { (exit 1); exit 1; }; } else - with_glew_mx=yes + : ${with_glew_mx:=yes} + fi + if test "$with_wxwidgets" = "no"; then + { { echo "$as_me:$LINENO: error: incompatible options: --without-wxwidgets but --with-gbench" >&5 +echo "$as_me: error: incompatible options: --without-wxwidgets but --with-gbench" >&2;} + { (exit 1); exit 1; }; } + else + : ${with_wxwidgets:=yes} + fi + if test "$with_ftgl" = "no"; then + { { echo "$as_me:$LINENO: error: incompatible options: --without-ftgl but --with-gbench" >&5 +echo "$as_me: error: incompatible options: --without-ftgl but --with-gbench" >&2;} + { (exit 1); exit 1; }; } + else + : ${with_ftgl:=yes} + fi + if test "$with_sqlite3" = "no"; then + { { echo "$as_me:$LINENO: error: incompatible options: --without-sqlite3 but --with-gbench" >&5 +echo "$as_me: error: incompatible options: --without-sqlite3 but --with-gbench" >&2;} + { (exit 1); exit 1; }; } + else + : ${with_sqlite3:=yes} + fi + if test "$with_bdb" = "no"; then + { { echo "$as_me:$LINENO: error: incompatible options: --without-bdb but --with-gbench" >&5 +echo "$as_me: error: incompatible options: --without-bdb but --with-gbench" >&2;} + { (exit 1); exit 1; }; } + else + : ${with_bdb:=yes} + fi + if test "$with_boost" = "no"; then + { { echo "$as_me:$LINENO: error: incompatible options: --without-boost but --with-gbench" >&5 +echo "$as_me: error: incompatible options: --without-boost but --with-gbench" >&2;} + { (exit 1); exit 1; }; } + else + : ${with_boost:=yes} + fi + if test "$with_xslt" = "no"; then + { { echo "$as_me:$LINENO: error: incompatible options: --without-xslt but --with-gbench" >&5 +echo "$as_me: error: incompatible options: --without-xslt but --with-gbench" >&2;} + { (exit 1); exit 1; }; } + else + : ${with_xslt:=yes} + fi + if test "$with_gnutls" = "no"; then + { { echo "$as_me:$LINENO: error: incompatible options: --without-gnutls but --with-gbench" >&5 +echo "$as_me: error: incompatible options: --without-gnutls but --with-gbench" >&2;} + { (exit 1); exit 1; }; } + else + : ${with_gnutls:=yes} fi : ${with_projects=scripts/projects/ncbi_gbench.lst} @@ -4237,6 +4342,34 @@ echo "$as_me: error: incompatible options: --without-vdb but ;; esac +case "$with_static_vdb:$with_vdb" in + yes:no ) + { { echo "$as_me:$LINENO: error: incompatible options: --without-vdb but --with-static-vdb" >&5 +echo "$as_me: error: incompatible options: --without-vdb but --with-static-vdb" >&2;} + { (exit 1); exit 1; }; } + ;; + yes: ) + with_vdb=yes + ;; + :* ) + with_static_vdb=$with_bin_release + ;; +esac + +case "$with_static_gnutls:$with_gnutls" in + yes:no ) + { { echo "$as_me:$LINENO: error: incompatible options: --without-gnutls but --with-static-gnutls" >&5 +echo "$as_me: error: incompatible options: --without-gnutls but --with-static-gnutls" >&2;} + { (exit 1); exit 1; }; } + ;; + yes: ) + with_gnutls=yes + ;; + :* ) + with_static_gnutls=$with_bin_release + ;; +esac + #### Check for special options if test "$with_extra_action" = "yes" ; then { { echo "$as_me:$LINENO: error: --with-extra-action must have a value after =" >&5 @@ -4304,12 +4437,18 @@ USER_LDFLAGS=$LDFLAGS if test -n "$with_experimental"; then for x in `echo $with_experimental | tr , ' '`; do case "$x" in + ChaosMonkey ) + CPPFLAGS="$CPPFLAGS -DNCBI_MONKEY" + WithFeatures="$WithFeatures${WithFeaturesSep}ChaosMonkey"; WithFeaturesSep=" " + ;; Int8GI ) CPPFLAGS="$CPPFLAGS -DNCBI_INT8_GI" + NCBI_C_PATH_TAGS="/ncbi.gi64 .gi64" WithFeatures="$WithFeatures${WithFeaturesSep}Int8GI"; WithFeaturesSep=" " ;; StrictGI ) CPPFLAGS="$CPPFLAGS -DNCBI_STRICT_GI" + NCBI_C_PATH_TAGS="/ncbi.gi64 .gi64" WithFeatures="$WithFeatures${WithFeaturesSep}Int8GI"; WithFeaturesSep=" " WithFeatures="$WithFeatures${WithFeaturesSep}StrictGI"; WithFeaturesSep=" " ;; @@ -4329,6 +4468,50 @@ cat >>confdefs.h <<\_ACEOF _ACEOF +{ echo "$as_me:$LINENO: checking TeamCity build number" >&5 +echo $ECHO_N "checking TeamCity build number... $ECHO_C" >&6; } +if test -n "$TEAMCITY_VERSION" -a -n "$BUILD_NUMBER"; then + { echo "$as_me:$LINENO: result: $BUILD_NUMBER" >&5 +echo "${ECHO_T}$BUILD_NUMBER" >&6; } + NCBI_TEAMCITY_BUILD_NUMBER=$BUILD_NUMBER +else + { echo "$as_me:$LINENO: result: none" >&5 +echo "${ECHO_T}none" >&6; } + NCBI_TEAMCITY_BUILD_NUMBER=0 +fi + +{ echo "$as_me:$LINENO: checking Subversion revision" >&5 +echo $ECHO_N "checking Subversion revision... $ECHO_C" >&6; } +svnrev=`svn info "$srcdir" 2>/dev/null | sed -ne 's/^Revision: //p'` +if test -n "$svnrev"; then + { echo "$as_me:$LINENO: result: $svnrev" >&5 +echo "${ECHO_T}$svnrev" >&6; } + NCBI_SUBVERSION_REVISION=$svnrev +else + { echo "$as_me:$LINENO: result: unknown" >&5 +echo "${ECHO_T}unknown" >&6; } + NCBI_SUBVERSION_REVISION=0 +fi + +{ echo "$as_me:$LINENO: checking NCBI stable components' version" >&5 +echo $ECHO_N "checking NCBI stable components' version... $ECHO_C" >&6; } +scver=`svn info "$srcdir/src/build-system" 2>/dev/null | + sed -ne 's,^URL: .*/production/components/[^/]*/\([1-9][0-9]*\)\..*,\1,p'` +if test -n "$scver"; then + { echo "$as_me:$LINENO: result: $scver" >&5 +echo "${ECHO_T}$scver" >&6; } + NCBI_SC_VERSION=$scver +else + { echo "$as_me:$LINENO: result: unknown" >&5 +echo "${ECHO_T}unknown" >&6; } + NCBI_SC_VERSION=0 +fi + + +cat >>confdefs.h <<\_ACEOF +#define HAVE_COMMON_NCBI_BUILD_VER_H 1 +_ACEOF + #### Get the running host's properties ac_aux_dir= @@ -7693,14 +7876,15 @@ echo "$as_me: WARNING: $msg" >&2;}; with_mt=no ;; esac fi +case "$host_os:$compiler" in + solaris2.10:GCC ) : ${THREAD_LIBS:="-lposix4"} ;; + solaris* ) : ${THREAD_LIBS:="-lpthread -lposix4"} ;; + freebsd* ) ;; # -pthread already substitutes libc_r for libc + * ) : ${THREAD_LIBS:="-lpthread"} ;; +esac + if test "$with_mt" != "no" ; then CPPFLAGS="$CPPFLAGS -D_MT -D_REENTRANT -D_THREAD_SAFE" - case "$host_os:$compiler" in - solaris2.10:GCC ) : ${THREAD_LIBS:="-lposix4"} ;; - solaris* ) : ${THREAD_LIBS:="-lpthread -lposix4"} ;; - freebsd* ) ;; # -pthread already substitutes libc_r for libc - * ) : ${THREAD_LIBS:="-lpthread"} ;; - esac LIBS="$LIBS $THREAD_LIBS" case "$host_os:$compiler" in solaris2.??:* | solaris*:GCC | *:Compaq | irix* | aix* | darwin* | cygwin*) @@ -7747,7 +7931,6 @@ if test "$with_mt" != "no" ; then else CPPFLAGS="$CPPFLAGS -DNCBI_WITHOUT_MT" MT_FLAG= - THREAD_LIBS= NCBIATOMIC_LIB= OPENMP_FLAGS= mt_sfx="" @@ -7936,9 +8119,6 @@ case "$host_os:$compiler" in darwin?.* | darwin10.* ) # Mac OS X 10.6.x or older TARGET='-mmacosx-version-min=10.5' sdks="/Developer/SDKs/MacOSX10.6.sdk" - if test "$with_64:${with_universal-no}" != "yes:no"; then - sdks="/Developer/SDKs/MacOSX10.5.sdk $sdks" - fi ;; * ) TARGET='-mmacosx-version-min=10.7' @@ -8029,58 +8209,7 @@ C_LIBS=$LIBS ARCH_CPPFLAGS= #### architecture settings, and extra C++ LIBS -if test "${with_universal-no}" != "no" ; then - bit64_sfx= #"Univ" - case "$host" in - *-*-darwin[89].* | *-*-darwin[1-9][0-9]* ) - case "$with_universal" in - yes ) - case "$with_64:$host_os" in - yes:darwin8.* ) - { { echo "$as_me:$LINENO: error: Unable to build 64-bit universal binaries on $host" >&5 -echo "$as_me: error: Unable to build 64-bit universal binaries on $host" >&2;} - { (exit 1); exit 1; }; } - ;; - yes:* ) - ARCH_CFLAGS="-arch ppc64 -arch x86_64" - ARCH_CPPFLAGS="-m64" - ;; - * ) - ARCH_CFLAGS="-arch ppc -arch i386" - ARCH_CPPFLAGS="-m32" - ;; - esac - ;; - * ) - ARCH_CFLAGS="-arch `echo $with_universal | sed -e 's/,/ -arch /g'`" - ARCH_CPPFLAGS="-arch `echo $with_universal | sed -e 's/,.*//'`" - ;; - esac - case "$host" in - p*pc*-*-darwin8.*) - # Must specify -isysroot ..., but only once; anyway, the preprocessor - # needs to see it, and naturally can't cope with multiple -arch flags. - # The -mmacosx-version-min flag avoids link errors under OS 10.5 - # (Darwin 9), which otherwise tries to use crt1.10.5.o despite the - # request for a sysroot lacking that file. - SYSROOT="-isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.4" - #ARCH_CFLAGS="$SYSROOT $ARCH_CFLAGS" - CC="$CC $SYSROOT" - CXX="$CXX $SYSROOT" - ;; - esac - ;; - * ) { { echo "$as_me:$LINENO: error: Do not know how to build universal binaries on $host" >&5 -echo "$as_me: error: Do not know how to build universal binaries on $host" >&2;} - { (exit 1); exit 1; }; } ;; - esac - -cat >>confdefs.h <<\_ACEOF -#define NCBI_UNIVERSAL_BUILD 1 -_ACEOF - - with_distcc=no -elif test "$with_64" = "yes" ; then +if test "$with_64" = "yes" ; then bit64_sfx="64" case "$host:$compiler" in sparc-sun-solaris*:WorkShop5 | sparc-sun-solaris*:KCC ) @@ -8288,6 +8417,59 @@ echo "$as_me: error: cannot continue; please try different options" >&2;} fi fi +#### Don't let Clang pick up old (pre-C++11) system standard +#### library installations on Linux. +case "$host_os:/$CXX" in + linux*:*/clang* ) + gccver=4.9.3 + gccdir=/opt/ncbi/gcc/$gccver + if test -d $gccdir; then + for d in `$gccdir/bin/g++ -v -E -x c++ $ARCH_CFLAGS $ARCH_CPPFLAGS - \ + &1 | fgrep 'include/c++' | tac`; do + ncbi_fix_dir_tmp=`if cd $d; then $as_unset PWD || test "${PWD+set}" != set || { PWD=; export PWD; }; /bin/pwd; fi` + case "$ncbi_fix_dir_tmp" in + /.*) ncbi_fix_dir_tmp2=`cd $d && $smart_pwd 2>/dev/null` + if test -n "$ncbi_fix_dir_tmp2" -a -d "$ncbi_fix_dir_tmp2"; then + d=$ncbi_fix_dir_tmp2 + else + case "$d" in + /*) ;; + * ) d=$ncbi_fix_dir_tmp ;; + esac + fi + ;; + /*) d=$ncbi_fix_dir_tmp ;; + esac + # We don't use a dedicated CXXCPPFLAGS variable, but sticking + # with -isystem rather than -cxx-isystem avoids spurious + # warnings when also using ccache or distcc, and should still + # be safe in practice. (The three libstdc++ headers that have + # the same names as system headers all arrange to include + # those headers via #include_next, and to conditionalize any + # C++ declarations on compiling as actual C++.) + CPPFLAGS="-isystem $d $CPPFLAGS" + done + CPPFLAGS="-nostdinc++ $CPPFLAGS" + libstdcxx=`$gccdir/bin/g++ --print-file-name=libstdc++.a` + d=`dirname $libstdcxx` + ncbi_fix_dir_tmp=`if cd $d; then $as_unset PWD || test "${PWD+set}" != set || { PWD=; export PWD; }; /bin/pwd; fi` + case "$ncbi_fix_dir_tmp" in + /.*) ncbi_fix_dir_tmp2=`cd $d && $smart_pwd 2>/dev/null` + if test -n "$ncbi_fix_dir_tmp2" -a -d "$ncbi_fix_dir_tmp2"; then + d=$ncbi_fix_dir_tmp2 + else + case "$d" in + /*) ;; + * ) d=$ncbi_fix_dir_tmp ;; + esac + fi + ;; + /*) d=$ncbi_fix_dir_tmp ;; + esac + LDFLAGS="-L$d -Wl,-rpath,$d $LDFLAGS" + fi + ;; +esac case "$host_os:$compiler" in darwin*:GCC ) @@ -8676,16 +8858,6 @@ fi echo "${ECHO_T}$ac_cv_have_decl__LIBCPP_VERSION" >&6; } -case "$ac_cv_have_decl__LIBCPP_VERSION:$compiler:$compiler_version" in - no:GCC:4[0-6]? | no:ICC:1[01]?? ) - ncbi_cv_prog_cxx_11=no - ncbi_cv_prog_c_99=no - ;; - *:ICC:* ) - ncbi_cv_prog_c_99='-std=gnu99 -fgnu89-inline' - ;; -esac - { echo "$as_me:$LINENO: checking how to enable C++ '11 features in $CXX" >&5 echo $ECHO_N "checking how to enable C++ '11 features in $CXX... $ECHO_C" >&6; } if test "${ncbi_cv_prog_cxx_11+set}" = set; then @@ -8693,7 +8865,7 @@ if test "${ncbi_cv_prog_cxx_11+set}" = set; then else orig_CXX=$CXX ncbi_cv_prog_cxx_11=no - for x in -std=gnu++11 -std=gnu++0x; do + for x in -std=gnu++11 -std=gnu++0x ''; do CXX="$orig_CXX $x" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ @@ -8701,11 +8873,11 @@ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ - +#include int main () { - +std::unique_ptr x; ; return 0; } @@ -8760,7 +8932,13 @@ rm -f core conftest.err conftest.$ac_objext \ fi { echo "$as_me:$LINENO: result: $ncbi_cv_prog_cxx_11" >&5 echo "${ECHO_T}$ncbi_cv_prog_cxx_11" >&6; } -test "$ncbi_cv_prog_cxx_11" = no || CXX="$CXX $ncbi_cv_prog_cxx_11" +if test "$ncbi_cv_prog_cxx_11" = no; then + { { echo "$as_me:$LINENO: error: Please upgrade to a compiler supporting C++ '11, such as GCC 4.8 or newer." >&5 +echo "$as_me: error: Please upgrade to a compiler supporting C++ '11, such as GCC 4.8 or newer." >&2;} + { (exit 1); exit 1; }; } +else + CXX="$CXX $ncbi_cv_prog_cxx_11" +fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' @@ -9168,7 +9346,11 @@ echo "$as_me: WARNING: Unable to find static libstdc++ requested by --with-bin-r DLL_LDFLAGS="-static-intel -diag-disable 10237 -nodefaultlibs $DLL_LDFLAGS" # Redundant for apps, but necessary for plugins to be adequately # self-contained, at least on 32-bit Linux. - LIBS="$LIBS -lstdc++" + if test "$with_bin_release" = "yes"; then + LDFLAGS="$LDFLAGS -static-libstdc++" + elif test "$with_dll" != "no"; then + LIBS="$LIBS -lstdc++" + fi LINK="$LINK -Kc++" # Defining _GCC_NEXT_LIMITS_H ensures that chaining doesn't # stop short, as can otherwise happen. :-/ @@ -9458,8 +9640,7 @@ fi ### Support for precompiled headers GCCPCH="#" -if test "$compiler" = GCC -a "$with_pch" = "yes" \ - -a "${with_universal-no}" = "no"; then +if test "$compiler" = GCC -a "$with_pch" = "yes"; then { echo "$as_me:$LINENO: checking whether $CXX supports precompiled headers" >&5 echo $ECHO_N "checking whether $CXX supports precompiled headers... $ECHO_C" >&6; } if test "${ncbi_cv_cxx_pch+set}" = set; then @@ -11245,8 +11426,7 @@ _ACEOF fi -if test "${with_universal-no}" = "no"; then - { echo "$as_me:$LINENO: checking for size_t" >&5 +{ echo "$as_me:$LINENO: checking for size_t" >&5 echo $ECHO_N "checking for size_t... $ECHO_C" >&6; } if test "${ac_cv_type_size_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 @@ -11746,16 +11926,15 @@ cat >>confdefs.h <<_ACEOF _ACEOF - ac_cv_sizeof_size_t=`echo "$ac_cv_sizeof_size_t" | tr -d '\r'` - NCBI_PLATFORM_BITS=`expr 8 \* $ac_cv_sizeof_size_t` +ac_cv_sizeof_size_t=`echo "$ac_cv_sizeof_size_t" | tr -d '\r'` +NCBI_PLATFORM_BITS=`expr 8 \* $ac_cv_sizeof_size_t` cat >>confdefs.h <<_ACEOF #define NCBI_PLATFORM_BITS $NCBI_PLATFORM_BITS _ACEOF - if test $NCBI_PLATFORM_BITS -eq 64; then - bit64_sfx=64 - fi +if test $NCBI_PLATFORM_BITS -eq 64; then + bit64_sfx=64 fi if test "$bit64_sfx" = 64 -o "$with_lfs" = "yes"; then @@ -16851,8 +17030,7 @@ fi ### Check for C standard types and sizes -if test "${with_universal-no}" = "no"; then - { echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 +{ echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6; } if test "${ac_cv_c_bigendian+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 @@ -17214,7 +17392,7 @@ _ACEOF fi - { echo "$as_me:$LINENO: checking for char" >&5 +{ echo "$as_me:$LINENO: checking for char" >&5 echo $ECHO_N "checking for char... $ECHO_C" >&6; } if test "${ac_cv_type_char+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 @@ -17714,7 +17892,7 @@ cat >>confdefs.h <<_ACEOF _ACEOF - { echo "$as_me:$LINENO: checking for double" >&5 +{ echo "$as_me:$LINENO: checking for double" >&5 echo $ECHO_N "checking for double... $ECHO_C" >&6; } if test "${ac_cv_type_double+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 @@ -18214,7 +18392,7 @@ cat >>confdefs.h <<_ACEOF _ACEOF - { echo "$as_me:$LINENO: checking for float" >&5 +{ echo "$as_me:$LINENO: checking for float" >&5 echo $ECHO_N "checking for float... $ECHO_C" >&6; } if test "${ac_cv_type_float+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 @@ -18714,7 +18892,7 @@ cat >>confdefs.h <<_ACEOF _ACEOF - { echo "$as_me:$LINENO: checking for int" >&5 +{ echo "$as_me:$LINENO: checking for int" >&5 echo $ECHO_N "checking for int... $ECHO_C" >&6; } if test "${ac_cv_type_int+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 @@ -19214,7 +19392,7 @@ cat >>confdefs.h <<_ACEOF _ACEOF - { echo "$as_me:$LINENO: checking for long" >&5 +{ echo "$as_me:$LINENO: checking for long" >&5 echo $ECHO_N "checking for long... $ECHO_C" >&6; } if test "${ac_cv_type_long+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 @@ -19714,7 +19892,7 @@ cat >>confdefs.h <<_ACEOF _ACEOF - { echo "$as_me:$LINENO: checking for long double" >&5 +{ echo "$as_me:$LINENO: checking for long double" >&5 echo $ECHO_N "checking for long double... $ECHO_C" >&6; } if test "${ac_cv_type_long_double+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 @@ -20214,7 +20392,7 @@ cat >>confdefs.h <<_ACEOF _ACEOF - { echo "$as_me:$LINENO: checking for long long" >&5 +{ echo "$as_me:$LINENO: checking for long long" >&5 echo $ECHO_N "checking for long long... $ECHO_C" >&6; } if test "${ac_cv_type_long_long+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 @@ -20714,7 +20892,7 @@ cat >>confdefs.h <<_ACEOF _ACEOF - { echo "$as_me:$LINENO: checking for short" >&5 +{ echo "$as_me:$LINENO: checking for short" >&5 echo $ECHO_N "checking for short... $ECHO_C" >&6; } if test "${ac_cv_type_short+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 @@ -21214,7 +21392,7 @@ cat >>confdefs.h <<_ACEOF _ACEOF - { echo "$as_me:$LINENO: checking for void*" >&5 +{ echo "$as_me:$LINENO: checking for void*" >&5 echo $ECHO_N "checking for void*... $ECHO_C" >&6; } if test "${ac_cv_type_voidp+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 @@ -21714,7 +21892,7 @@ cat >>confdefs.h <<_ACEOF _ACEOF - { echo "$as_me:$LINENO: checking for wchar_t" >&5 +{ echo "$as_me:$LINENO: checking for wchar_t" >&5 echo $ECHO_N "checking for wchar_t... $ECHO_C" >&6; } if test "${ac_cv_type_wchar_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 @@ -22221,7 +22399,7 @@ cat >>confdefs.h <<_ACEOF _ACEOF - { echo "$as_me:$LINENO: checking for __int64" >&5 +{ echo "$as_me:$LINENO: checking for __int64" >&5 echo $ECHO_N "checking for __int64... $ECHO_C" >&6; } if test "${ac_cv_type___int64+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 @@ -22721,7 +22899,6 @@ cat >>confdefs.h <<_ACEOF _ACEOF -fi { echo "$as_me:$LINENO: checking for intptr_t" >&5 echo $ECHO_N "checking for intptr_t... $ECHO_C" >&6; } if test "${ac_cv_type_intptr_t+set}" = set; then @@ -29636,6 +29813,28 @@ if test "x$with_gnutls" != xno -a -n "$GNUTLS_CONFIG_LIBS"; then *\ -lgcrypt* ) ;; * ) GNUTLS_LIBS="$GNUTLS_LIBS $GCRYPT_LIBS" ;; esac + if test "$with_static_gnutls" = yes; then + dirs='' + sep='' + static_libs='' + for x in $GNUTLS_LIBS; do + case $x in + -L* ) dirs="$dirs `echo _$x | cut -c4-`" ;; + -l* ) + want=lib`echo _$x | cut -c4-`-static.a + for d in $dirs; do + if test -f $d/$want; then + x=$x-static + break + fi + done + ;; + esac + static_libs=$static_libs$sep$x + sep=' ' + done + GNUTLS_LIBS=$static_libs + fi fi if test "$with_openssl" != "no"; then @@ -29832,6 +30031,7 @@ else TLS_LIBS=$OPENSSL_LIBS fi +NETWORK_LIBS="$TLS_LIBS $NETWORK_LIBS" case "$with_krb5" in no ) ac_cv_path_KRB5_CONFIG=no ;; @@ -30761,9 +30961,9 @@ if test "$with_ftds" != "no" ; then ftds_ver=64 try_local=yes case "$with_ftds" in - 64 | 0.64 | yes | '' ) + 64 | 0.64 ) ;; - 95 | 0.95 ) + 95 | 0.95 | yes | '' ) ftds_ver=95 ;; * ) @@ -30771,7 +30971,7 @@ if test "$with_ftds" != "no" ; then try_local=no ;; esac - : ${FTDS_CTLIBS:="-lct -ltds"} + : ${FTDS_CTLIBS:="-lct -ltds $NETWORK_LIBS"} ncbi_rp_L_flags= ncbi_rp_L_sep=$CONF_f_libpath if test "x${CONF_f_runpath}" = "x${CONF_f_libpath}"; then @@ -30807,7 +31007,7 @@ if test "$with_ftds" != "no" ; then if test $try_local = yes -a -f "${real_srcdir}/src/$d/Makefile.in" ; then test "$ftds_ver" = 64 && FTDS_PATH="<$d>" FTDS64_CTLIB_LIB="ct_ftds64${STATIC} tds_ftds64${STATIC}" - FTDS64_CTLIB_LIBS='$(ICONV_LIBS) $(KRB5_LIBS)' + FTDS64_CTLIB_LIBS='$(ICONV_LIBS) $(KRB5_LIBS) $(NETWORK_LIBS)' FTDS64_CTLIB_INCLUDE="-I\$(includedir)/$d -I\$(includedir0)/$d" freetds=freetds elif test -d "$FTDS_PATH" ; then @@ -30823,7 +31023,7 @@ if test "$with_ftds" != "no" ; then if test $try_local = yes -a -f "${real_srcdir}/src/$d/Makefile.in" ; then test "$ftds_ver" = 95 && FTDS_PATH="<$d>" FTDS95_CTLIB_LIB="ct_ftds95${STATIC} tds_ftds95${STATIC}" - FTDS95_CTLIB_LIBS='$(ICONV_LIBS) $(KRB5_LIBS)' + FTDS95_CTLIB_LIBS='$(ICONV_LIBS) $(KRB5_LIBS) $(NETWORK_LIBS)' FTDS95_CTLIB_INCLUDE="-I\$(includedir)/$d -I\$(includedir0)/$d" freetds=freetds elif test -d "$FTDS_PATH" ; then @@ -31352,15 +31552,21 @@ cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ +cat >/dev/null <<_NCBI_EOF #include -ncbi_cv_lib_berkeley_db_version=DB_VERSION_MAJOR.DB_VERSION_MINOR.DB_VERSION_PATCH +_NCBI_EOF +get_DB_VERSION() { + grep '^[^#]' <<_NCBI_EOF +DB_VERSION_MAJOR.DB_VERSION_MINOR.DB_VERSION_PATCH +_NCBI_EOF +} +ncbi_cv_lib_berkeley_db_version=\`get_DB_VERSION | tr -cd 0123456789.\` _ACEOF - eval "$ac_cpp $BERKELEYDB_INCLUDE conftest.$ac_ext" \ - 2>&5 | grep '^ncbi_cv_' \ - | tr -d "$wschars" > conftest.sh + eval "$ac_cpp $BERKELEYDB_INCLUDE conftest.$ac_ext" > conftest.sh \ + 2>&5 . ./conftest.sh - rm -f contest* + rm -f conftest* fi { echo "$as_me:$LINENO: result: $ncbi_cv_lib_berkeley_db_version" >&5 @@ -32147,16 +32353,15 @@ fi if test -x "$PYTHON"; then - PYTHON_VERSION=`$PYTHON -c 'from distutils import sysconfig; print(sysconfig.get_config_var("VERSION"))' 2>/dev/null` + pyconf="$real_srcdir/scripts/common/impl/python-config.py" + PYTHON_VERSION=`DYLD_BIND_AT_LAUNCH=1 "$PYTHON" "$pyconf" --version 2>&5` else PYTHON_VERSION= ncbi_cv_lib_python=no fi if test -n "$PYTHON_VERSION"; then - PYTHON_INCLUDE=`$PYTHON -c 'from distutils import sysconfig; f=sysconfig.get_python_inc; print("-I%s -I%s" % (f(), f(True)))'` - PYTHON_LIBPATH=`$PYTHON -c 'from distutils import sysconfig; print(" ".join(sysconfig.get_config_vars("LIBDIR", "LIBPL")))'` - PYTHON_DEPS=`$PYTHON -c 'from distutils import sysconfig; print(" ".join(sysconfig.get_config_vars("LIBS", "SYSLIBS")))'` - PYTHON_LDVERSION=`$PYTHON -c 'from distutils import sysconfig; print(sysconfig.get_config_var("LDVERSION") or sysconfig.get_config_var("VERSION"))' 2>/dev/null` + PYTHON_INCLUDE=`"$PYTHON" "$pyconf" --include` + PYTHON_LIBPATH=`"$PYTHON" "$pyconf" --libpath` ncbi_rp_L_flags= ncbi_rp_L_sep=$CONF_f_libpath if test "x${CONF_f_runpath}" = "x${CONF_f_libpath}"; then @@ -32169,7 +32374,7 @@ fi ncbi_rp_L_flags="${ncbi_rp_L_flags}${ncbi_rp_L_sep}$x" ncbi_rp_L_sep=" $CONF_f_libpath" done - PYTHON_LIBS="${ncbi_rp_L_flags} -lpython$PYTHON_LDVERSION $PYTHON_DEPS" + PYTHON_LIBS="${ncbi_rp_L_flags} `"$PYTHON" "$pyconf" --libs`" else ncbi_rp_R_flags= ncbi_rp_R_sep=" $CONF_f_runpath" @@ -32185,7 +32390,7 @@ fi ncbi_rp_R_flags="${ncbi_rp_R_flags}${ncbi_rp_R_sep}$x" ncbi_rp_R_sep=: done - PYTHON_LIBS="${ncbi_rp_L_flags}${ncbi_rp_R_flags} -lpython$PYTHON_LDVERSION $PYTHON_DEPS" + PYTHON_LIBS="${ncbi_rp_L_flags}${ncbi_rp_R_flags} `"$PYTHON" "$pyconf" --libs`" fi CPPFLAGS="$PYTHON_INCLUDE $orig_CPPFLAGS" LIBS="$PYTHON_LIBS $orig_LIBS" @@ -32264,6 +32469,7 @@ fi { echo "$as_me:$LINENO: result: $ncbi_cv_lib_python" >&5 echo "${ECHO_T}$ncbi_cv_lib_python" >&6; } else + PYTHON= ncbi_cv_lib_python=no fi if test "$ncbi_cv_lib_python" = "no"; then @@ -32322,16 +32528,15 @@ fi if test -x "$PYTHON25"; then - PYTHON25_VERSION=`$PYTHON25 -c 'from distutils import sysconfig; print(sysconfig.get_config_var("VERSION"))' 2>/dev/null` + pyconf="$real_srcdir/scripts/common/impl/python-config.py" + PYTHON25_VERSION=`DYLD_BIND_AT_LAUNCH=1 "$PYTHON25" "$pyconf" --version 2>&5` else PYTHON25_VERSION= ncbi_cv_lib_python25=no fi if test -n "$PYTHON25_VERSION"; then - PYTHON25_INCLUDE=`$PYTHON25 -c 'from distutils import sysconfig; f=sysconfig.get_python_inc; print("-I%s -I%s" % (f(), f(True)))'` - PYTHON25_LIBPATH=`$PYTHON25 -c 'from distutils import sysconfig; print(" ".join(sysconfig.get_config_vars("LIBDIR", "LIBPL")))'` - PYTHON25_DEPS=`$PYTHON25 -c 'from distutils import sysconfig; print(" ".join(sysconfig.get_config_vars("LIBS", "SYSLIBS")))'` - PYTHON25_LDVERSION=`$PYTHON25 -c 'from distutils import sysconfig; print(sysconfig.get_config_var("LDVERSION") or sysconfig.get_config_var("VERSION"))' 2>/dev/null` + PYTHON25_INCLUDE=`"$PYTHON25" "$pyconf" --include` + PYTHON25_LIBPATH=`"$PYTHON25" "$pyconf" --libpath` ncbi_rp_L_flags= ncbi_rp_L_sep=$CONF_f_libpath if test "x${CONF_f_runpath}" = "x${CONF_f_libpath}"; then @@ -32344,7 +32549,7 @@ fi ncbi_rp_L_flags="${ncbi_rp_L_flags}${ncbi_rp_L_sep}$x" ncbi_rp_L_sep=" $CONF_f_libpath" done - PYTHON25_LIBS="${ncbi_rp_L_flags} -lpython$PYTHON25_LDVERSION $PYTHON25_DEPS" + PYTHON25_LIBS="${ncbi_rp_L_flags} `"$PYTHON25" "$pyconf" --libs`" else ncbi_rp_R_flags= ncbi_rp_R_sep=" $CONF_f_runpath" @@ -32360,7 +32565,7 @@ fi ncbi_rp_R_flags="${ncbi_rp_R_flags}${ncbi_rp_R_sep}$x" ncbi_rp_R_sep=: done - PYTHON25_LIBS="${ncbi_rp_L_flags}${ncbi_rp_R_flags} -lpython$PYTHON25_LDVERSION $PYTHON25_DEPS" + PYTHON25_LIBS="${ncbi_rp_L_flags}${ncbi_rp_R_flags} `"$PYTHON25" "$pyconf" --libs`" fi CPPFLAGS="$PYTHON25_INCLUDE $orig_CPPFLAGS" LIBS="$PYTHON25_LIBS $orig_LIBS" @@ -32439,6 +32644,7 @@ fi { echo "$as_me:$LINENO: result: $ncbi_cv_lib_python25" >&5 echo "${ECHO_T}$ncbi_cv_lib_python25" >&6; } else + PYTHON25= ncbi_cv_lib_python25=no fi if test "$ncbi_cv_lib_python25" = "no"; then @@ -32497,16 +32703,15 @@ fi if test -x "$PYTHON26"; then - PYTHON26_VERSION=`$PYTHON26 -c 'from distutils import sysconfig; print(sysconfig.get_config_var("VERSION"))' 2>/dev/null` + pyconf="$real_srcdir/scripts/common/impl/python-config.py" + PYTHON26_VERSION=`DYLD_BIND_AT_LAUNCH=1 "$PYTHON26" "$pyconf" --version 2>&5` else PYTHON26_VERSION= ncbi_cv_lib_python26=no fi if test -n "$PYTHON26_VERSION"; then - PYTHON26_INCLUDE=`$PYTHON26 -c 'from distutils import sysconfig; f=sysconfig.get_python_inc; print("-I%s -I%s" % (f(), f(True)))'` - PYTHON26_LIBPATH=`$PYTHON26 -c 'from distutils import sysconfig; print(" ".join(sysconfig.get_config_vars("LIBDIR", "LIBPL")))'` - PYTHON26_DEPS=`$PYTHON26 -c 'from distutils import sysconfig; print(" ".join(sysconfig.get_config_vars("LIBS", "SYSLIBS")))'` - PYTHON26_LDVERSION=`$PYTHON26 -c 'from distutils import sysconfig; print(sysconfig.get_config_var("LDVERSION") or sysconfig.get_config_var("VERSION"))' 2>/dev/null` + PYTHON26_INCLUDE=`"$PYTHON26" "$pyconf" --include` + PYTHON26_LIBPATH=`"$PYTHON26" "$pyconf" --libpath` ncbi_rp_L_flags= ncbi_rp_L_sep=$CONF_f_libpath if test "x${CONF_f_runpath}" = "x${CONF_f_libpath}"; then @@ -32519,7 +32724,7 @@ fi ncbi_rp_L_flags="${ncbi_rp_L_flags}${ncbi_rp_L_sep}$x" ncbi_rp_L_sep=" $CONF_f_libpath" done - PYTHON26_LIBS="${ncbi_rp_L_flags} -lpython$PYTHON26_LDVERSION $PYTHON26_DEPS" + PYTHON26_LIBS="${ncbi_rp_L_flags} `"$PYTHON26" "$pyconf" --libs`" else ncbi_rp_R_flags= ncbi_rp_R_sep=" $CONF_f_runpath" @@ -32535,7 +32740,7 @@ fi ncbi_rp_R_flags="${ncbi_rp_R_flags}${ncbi_rp_R_sep}$x" ncbi_rp_R_sep=: done - PYTHON26_LIBS="${ncbi_rp_L_flags}${ncbi_rp_R_flags} -lpython$PYTHON26_LDVERSION $PYTHON26_DEPS" + PYTHON26_LIBS="${ncbi_rp_L_flags}${ncbi_rp_R_flags} `"$PYTHON26" "$pyconf" --libs`" fi CPPFLAGS="$PYTHON26_INCLUDE $orig_CPPFLAGS" LIBS="$PYTHON26_LIBS $orig_LIBS" @@ -32614,6 +32819,7 @@ fi { echo "$as_me:$LINENO: result: $ncbi_cv_lib_python26" >&5 echo "${ECHO_T}$ncbi_cv_lib_python26" >&6; } else + PYTHON26= ncbi_cv_lib_python26=no fi if test "$ncbi_cv_lib_python26" = "no"; then @@ -32672,16 +32878,15 @@ fi if test -x "$PYTHON27"; then - PYTHON27_VERSION=`$PYTHON27 -c 'from distutils import sysconfig; print(sysconfig.get_config_var("VERSION"))' 2>/dev/null` + pyconf="$real_srcdir/scripts/common/impl/python-config.py" + PYTHON27_VERSION=`DYLD_BIND_AT_LAUNCH=1 "$PYTHON27" "$pyconf" --version 2>&5` else PYTHON27_VERSION= ncbi_cv_lib_python27=no fi if test -n "$PYTHON27_VERSION"; then - PYTHON27_INCLUDE=`$PYTHON27 -c 'from distutils import sysconfig; f=sysconfig.get_python_inc; print("-I%s -I%s" % (f(), f(True)))'` - PYTHON27_LIBPATH=`$PYTHON27 -c 'from distutils import sysconfig; print(" ".join(sysconfig.get_config_vars("LIBDIR", "LIBPL")))'` - PYTHON27_DEPS=`$PYTHON27 -c 'from distutils import sysconfig; print(" ".join(sysconfig.get_config_vars("LIBS", "SYSLIBS")))'` - PYTHON27_LDVERSION=`$PYTHON27 -c 'from distutils import sysconfig; print(sysconfig.get_config_var("LDVERSION") or sysconfig.get_config_var("VERSION"))' 2>/dev/null` + PYTHON27_INCLUDE=`"$PYTHON27" "$pyconf" --include` + PYTHON27_LIBPATH=`"$PYTHON27" "$pyconf" --libpath` ncbi_rp_L_flags= ncbi_rp_L_sep=$CONF_f_libpath if test "x${CONF_f_runpath}" = "x${CONF_f_libpath}"; then @@ -32694,7 +32899,7 @@ fi ncbi_rp_L_flags="${ncbi_rp_L_flags}${ncbi_rp_L_sep}$x" ncbi_rp_L_sep=" $CONF_f_libpath" done - PYTHON27_LIBS="${ncbi_rp_L_flags} -lpython$PYTHON27_LDVERSION $PYTHON27_DEPS" + PYTHON27_LIBS="${ncbi_rp_L_flags} `"$PYTHON27" "$pyconf" --libs`" else ncbi_rp_R_flags= ncbi_rp_R_sep=" $CONF_f_runpath" @@ -32710,7 +32915,7 @@ fi ncbi_rp_R_flags="${ncbi_rp_R_flags}${ncbi_rp_R_sep}$x" ncbi_rp_R_sep=: done - PYTHON27_LIBS="${ncbi_rp_L_flags}${ncbi_rp_R_flags} -lpython$PYTHON27_LDVERSION $PYTHON27_DEPS" + PYTHON27_LIBS="${ncbi_rp_L_flags}${ncbi_rp_R_flags} `"$PYTHON27" "$pyconf" --libs`" fi CPPFLAGS="$PYTHON27_INCLUDE $orig_CPPFLAGS" LIBS="$PYTHON27_LIBS $orig_LIBS" @@ -32789,6 +32994,7 @@ fi { echo "$as_me:$LINENO: result: $ncbi_cv_lib_python27" >&5 echo "${ECHO_T}$ncbi_cv_lib_python27" >&6; } else + PYTHON27= ncbi_cv_lib_python27=no fi if test "$ncbi_cv_lib_python27" = "no"; then @@ -32847,16 +33053,15 @@ fi if test -x "$PYTHON3"; then - PYTHON3_VERSION=`$PYTHON3 -c 'from distutils import sysconfig; print(sysconfig.get_config_var("VERSION"))' 2>/dev/null` + pyconf="$real_srcdir/scripts/common/impl/python-config.py" + PYTHON3_VERSION=`DYLD_BIND_AT_LAUNCH=1 "$PYTHON3" "$pyconf" --version 2>&5` else PYTHON3_VERSION= ncbi_cv_lib_python3=no fi if test -n "$PYTHON3_VERSION"; then - PYTHON3_INCLUDE=`$PYTHON3 -c 'from distutils import sysconfig; f=sysconfig.get_python_inc; print("-I%s -I%s" % (f(), f(True)))'` - PYTHON3_LIBPATH=`$PYTHON3 -c 'from distutils import sysconfig; print(" ".join(sysconfig.get_config_vars("LIBDIR", "LIBPL")))'` - PYTHON3_DEPS=`$PYTHON3 -c 'from distutils import sysconfig; print(" ".join(sysconfig.get_config_vars("LIBS", "SYSLIBS")))'` - PYTHON3_LDVERSION=`$PYTHON3 -c 'from distutils import sysconfig; print(sysconfig.get_config_var("LDVERSION") or sysconfig.get_config_var("VERSION"))' 2>/dev/null` + PYTHON3_INCLUDE=`"$PYTHON3" "$pyconf" --include` + PYTHON3_LIBPATH=`"$PYTHON3" "$pyconf" --libpath` ncbi_rp_L_flags= ncbi_rp_L_sep=$CONF_f_libpath if test "x${CONF_f_runpath}" = "x${CONF_f_libpath}"; then @@ -32869,7 +33074,7 @@ fi ncbi_rp_L_flags="${ncbi_rp_L_flags}${ncbi_rp_L_sep}$x" ncbi_rp_L_sep=" $CONF_f_libpath" done - PYTHON3_LIBS="${ncbi_rp_L_flags} -lpython$PYTHON3_LDVERSION $PYTHON3_DEPS" + PYTHON3_LIBS="${ncbi_rp_L_flags} `"$PYTHON3" "$pyconf" --libs`" else ncbi_rp_R_flags= ncbi_rp_R_sep=" $CONF_f_runpath" @@ -32885,7 +33090,7 @@ fi ncbi_rp_R_flags="${ncbi_rp_R_flags}${ncbi_rp_R_sep}$x" ncbi_rp_R_sep=: done - PYTHON3_LIBS="${ncbi_rp_L_flags}${ncbi_rp_R_flags} -lpython$PYTHON3_LDVERSION $PYTHON3_DEPS" + PYTHON3_LIBS="${ncbi_rp_L_flags}${ncbi_rp_R_flags} `"$PYTHON3" "$pyconf" --libs`" fi CPPFLAGS="$PYTHON3_INCLUDE $orig_CPPFLAGS" LIBS="$PYTHON3_LIBS $orig_LIBS" @@ -32964,6 +33169,7 @@ fi { echo "$as_me:$LINENO: result: $ncbi_cv_lib_python3" >&5 echo "${ECHO_T}$ncbi_cv_lib_python3" >&6; } else + PYTHON3= ncbi_cv_lib_python3=no fi if test "$ncbi_cv_lib_python3" = "no"; then @@ -33569,16 +33775,27 @@ cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ +cat >/dev/null <<_NCBI_EOF #include -ncbi_cv_lib_boost_version_num=BOOST_VERSION -ncbi_cv_lib_boost_version=BOOST_LIB_VERSION +_NCBI_EOF +get_BOOST_VERSION() { + grep '^[^#]' <<_NCBI_EOF +BOOST_VERSION +_NCBI_EOF +} +get_BOOST_LIB_VERSION() { + grep '^[^#]' <<_NCBI_EOF +BOOST_LIB_VERSION +_NCBI_EOF +} +ncbi_cv_lib_boost_version_num=\`get_BOOST_VERSION\` +ncbi_cv_lib_boost_version=\`get_BOOST_LIB_VERSION | tr -d '"'\` _ACEOF - eval "$ac_cpp $BOOST_INCLUDE conftest.$ac_ext" \ - 2>&5 | grep '^ncbi_cv_' \ - | tr -d "$wschars" > conftest.sh + eval "$ac_cpp $BOOST_INCLUDE conftest.$ac_ext" > conftest.sh \ + 2>&5 . ./conftest.sh - rm -f contest* + rm -f conftest* fi { echo "$as_me:$LINENO: result: $ncbi_cv_lib_boost_version" >&5 @@ -33620,7 +33837,7 @@ echo "$as_me: error: --with-boost: Boost library is too old" >&2;} fi with_boost=no ;; - 1_3[5-9] | 1_3[5-9]_* | 1_[45]* | 1_60 | 1_60_* ) ;; + 1_3[5-9] | 1_3[5-9]_* | 1_[45]* | 1_6[0-2] | 1_6[0-2]_* ) ;; '' ) with_boost=no ;; * ) { echo "$as_me:$LINENO: WARNING: Untested Boost version; may prove incompatible." >&5 @@ -34518,6 +34735,14 @@ if test "$with_ncbi_c" != "no" ; then if test "$ncbi_compiler" = ICC -a -d "$NCBI_C_PATH/ncbi_icc"; then NCBI_C_PATH=$NCBI_C_PATH/ncbi_icc fi + if test -n "$NCBI_C_PATH_TAGS"; then + for x in $NCBI_C_PATH_TAGS; do + if test -d "$NCBI_C_PATH$x"; then + NCBI_C_PATH=$NCBI_C_PATH$x + break + fi + done + fi NCBI_C_INCLUDE="-I$NCBI_C_PATH/include${bit64_sfx}" if test "$with_debug" = "no" ; then @@ -40850,6 +41075,12 @@ VDB_REQ=VDB if test "$with_vdb" != "no" ; then # CURL? vdb_deps="$LIBXML_LIBS $NETWORK_LIBS $BZ2_LIBS $Z_LIBS $DL_LIBS" + # In MT builds, ORIG_LIBS already contains THREAD_LIBS. However, + # VDB is always threaded, and may need explicit THREAD_LIBS when + # used statically. + if test "$with_mt" = no; then + vdb_deps="$vdb_deps $THREAD_LIBS" + fi if test "${with_vdb:-yes}" != "yes" -a -d "$with_vdb"; then VDB_PATH=$with_vdb fi @@ -40904,13 +41135,30 @@ echo "$as_me: WARNING: $message" >&2;} ;; in_path=" in $VDB_PATH" for x in interfaces include; do if test -d "$VDB_PATH/$x"; then - : ${VDB_INCLUDE="-I$VDB_PATH/$x"} + vdb_inc_root=$VDB_PATH/$x + : ${VDB_INCLUDE="-I$vdb_inc_root"} break fi done + vdb_inc_subdirs=cc/gcc + case "$host_cpu:$bit64_sfx" in + *86*:64 ) vdb_inc_subdirs="cc/gcc/x86_64 $vdb_inc_subdirs" ;; + *86*:* ) vdb_inc_subdirs="cc/gcc/fat86 $vdb_inc_subdirs" ;; + esac + if test "$ncbi_compiler" = ICC; then + vdb_inc_subdirs="cc/icc $vdb_inc_subdirs" + fi + case "$host_os" in + darwin* ) vdb_inc_subdirs="os/mac os/unix $vdb_inc_subdirs" ;; + linux* ) vdb_inc_subdirs="os/linux os/unix $vdb_inc_subdirs" ;; + solaris* ) vdb_inc_subdirs="os/sun os/unix $vdb_inc_subdirs" ;; + esac + for x in $vdb_inc_subdirs; do + VDB_INCLUDE="$VDB_INCLUDE -I$vdb_inc_root/$x" + done case "$DEBUG_SFX" in Debug ) - VDB_INCLUDE="$VDB_INCLUDE $VDB_INCLUDE/cc/gcc -D_DEBUGGING" + VDB_INCLUDE="$VDB_INCLUDE -D_DEBUGGING" vdb_mode=debug ;; Release ) @@ -41042,9 +41290,11 @@ fi echo "${ECHO_T}$ncbi_cv_lib_ncbi_vdb" >&6; } if test "$ncbi_cv_lib_ncbi_vdb" = yes; then WithPackages="$WithPackages${WithPackagesSep}VDB"; WithPackagesSep=" " - VDB_LIB= if test -f "$VDB_LIBDIR/libncbi-vdb-static.a"; then VDB_STATIC_LIBS="-L$VDB_LIBDIR -lncbi-vdb-static $vdb_deps" + if test "$with_static_vdb" = yes; then + VDB_LIBS=$VDB_STATIC_LIBS + fi else VDB_STATIC_LIBS=$VDB_LIBS fi @@ -41061,10 +41311,35 @@ echo "${ECHO_T}$ncbi_cv_lib_ncbi_vdb" >&6; } esac ;; esac + +cat >>confdefs.h <<\_ACEOF +#define HAVE_NCBI_VDB 1 +_ACEOF + + bamread=bamread + sraread=sraread + ncbi_id2proc_snp=ncbi_id2proc_snp + ncbi_id2proc_wgs=ncbi_id2proc_wgs + ncbi_xloader_bam=ncbi_xloader_bam + ncbi_xloader_csra=ncbi_xloader_csra + ncbi_xloader_snp=ncbi_xloader_snp + ncbi_xloader_sra=ncbi_xloader_sra + ncbi_xloader_vdbgraph=ncbi_xloader_vdbgraph + ncbi_xloader_wgs=ncbi_xloader_wgs else VDB_INCLUDE= VDB_LIBS= VDB_STATIC_LIBS= + bamread= + sraread= + ncbi_id2proc_snp= + ncbi_id2proc_wgs= + ncbi_xloader_bam= + ncbi_xloader_csra= + ncbi_xloader_snp= + ncbi_xloader_sra= + ncbi_xloader_vdbgraph= + ncbi_xloader_wgs= fi # else ... # fi @@ -45300,6 +45575,652 @@ _ACEOF +# LAPACK +CPPFLAGS="-DHAVE_LAPACK_CONFIG_H $orig_CPPFLAGS" +case "$with_lapack" in + yes | no | '' ) ;; + * ) LAPACK_PATH=$with_lapack ;; +esac +if test -d "$LAPACK_PATH"; then + ncbi_fix_dir_tmp=`if cd $LAPACK_PATH; then $as_unset PWD || test "${PWD+set}" != set || { PWD=; export PWD; }; /bin/pwd; fi` + case "$ncbi_fix_dir_tmp" in + /.*) ncbi_fix_dir_tmp2=`cd $LAPACK_PATH && $smart_pwd 2>/dev/null` + if test -n "$ncbi_fix_dir_tmp2" -a -d "$ncbi_fix_dir_tmp2"; then + LAPACK_PATH=$ncbi_fix_dir_tmp2 + else + case "$LAPACK_PATH" in + /*) ;; + * ) LAPACK_PATH=$ncbi_fix_dir_tmp ;; + esac + fi + ;; + /*) LAPACK_PATH=$ncbi_fix_dir_tmp ;; + esac + CPPFLAGS="-I$LAPACK_PATH/include $CPPFLAGS" +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + +for ac_header in lapacke.h lapacke/lapacke.h clapack.h Accelerate/Accelerate.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ---------------------------------------- ## +## Report this to cpp-core@ncbi.nlm.nih.gov ## +## ---------------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +if test "$ac_cv_header_clapack_h:$ac_cv_header_Accelerate_Accelerate_h" != no:no; then + { echo "$as_me:$LINENO: checking for __CLPK_integer" >&5 +echo $ECHO_N "checking for __CLPK_integer... $ECHO_C" >&6; } +if test "${ac_cv_type___CLPK_integer+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef HAVE_CLAPACK_H + # include + #else + # include + #endif + +typedef __CLPK_integer ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type___CLPK_integer=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type___CLPK_integer=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type___CLPK_integer" >&5 +echo "${ECHO_T}$ac_cv_type___CLPK_integer" >&6; } +if test $ac_cv_type___CLPK_integer = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE___CLPK_INTEGER 1 +_ACEOF + + +fi + +fi + +if test "$with_lapack" != "no"; then + case "$with_lapack" in + yes | "" ) ;; + * ) LAPACK_PATH=$with_lapack ;; + esac + if test "$LAPACK_PATH" != /usr -a -d "$LAPACK_PATH"; then + in_path=" in $LAPACK_PATH" + if test -z "$LAPACK_INCLUDE" -a -d "$LAPACK_PATH/include"; then + LAPACK_INCLUDE="-I$LAPACK_PATH/include" + fi + if test -n "$LAPACK_LIBPATH"; then + : + elif test -d "$LAPACK_PATH/lib${bit64_sfx}"; then + ncbi_rp_L_flags= + ncbi_rp_L_sep=$CONF_f_libpath + if test "x${CONF_f_runpath}" = "x${CONF_f_libpath}"; then + for x in $LAPACK_PATH/lib${bit64_sfx}; do + case "$x" in + /lib | /usr/lib | /usr/lib32 | /usr/lib64 | /usr/lib/$multiarch ) + continue + ;; + esac + ncbi_rp_L_flags="${ncbi_rp_L_flags}${ncbi_rp_L_sep}$x" + ncbi_rp_L_sep=" $CONF_f_libpath" + done + LAPACK_LIBPATH="${ncbi_rp_L_flags}" + else + ncbi_rp_R_flags= + ncbi_rp_R_sep=" $CONF_f_runpath" + for x in $LAPACK_PATH/lib${bit64_sfx}; do + case "$x" in + /lib | /usr/lib | /usr/lib32 | /usr/lib64 | /usr/lib/$multiarch ) + continue + ;; + esac + ncbi_rp_L_flags="${ncbi_rp_L_flags}${ncbi_rp_L_sep}$x" + ncbi_rp_L_sep=" $CONF_f_libpath" + x=`echo $x | sed -e "$ncbi_rpath_sed"` + ncbi_rp_R_flags="${ncbi_rp_R_flags}${ncbi_rp_R_sep}$x" + ncbi_rp_R_sep=: + done + LAPACK_LIBPATH="${ncbi_rp_L_flags}${ncbi_rp_R_flags}" + fi + elif test -d "$LAPACK_PATH/lib"; then + ncbi_rp_L_flags= + ncbi_rp_L_sep=$CONF_f_libpath + if test "x${CONF_f_runpath}" = "x${CONF_f_libpath}"; then + for x in $LAPACK_PATH/lib; do + case "$x" in + /lib | /usr/lib | /usr/lib32 | /usr/lib64 | /usr/lib/$multiarch ) + continue + ;; + esac + ncbi_rp_L_flags="${ncbi_rp_L_flags}${ncbi_rp_L_sep}$x" + ncbi_rp_L_sep=" $CONF_f_libpath" + done + LAPACK_LIBPATH="${ncbi_rp_L_flags}" + else + ncbi_rp_R_flags= + ncbi_rp_R_sep=" $CONF_f_runpath" + for x in $LAPACK_PATH/lib; do + case "$x" in + /lib | /usr/lib | /usr/lib32 | /usr/lib64 | /usr/lib/$multiarch ) + continue + ;; + esac + ncbi_rp_L_flags="${ncbi_rp_L_flags}${ncbi_rp_L_sep}$x" + ncbi_rp_L_sep=" $CONF_f_libpath" + x=`echo $x | sed -e "$ncbi_rpath_sed"` + ncbi_rp_R_flags="${ncbi_rp_R_flags}${ncbi_rp_R_sep}$x" + ncbi_rp_R_sep=: + done + LAPACK_LIBPATH="${ncbi_rp_L_flags}${ncbi_rp_R_flags}" + fi + fi + LAPACK_LIBS="$LAPACK_LIBPATH -llapack -lblas" + else + LAPACK_INCLUDE="" + LAPACK_LIBS="-llapack -lblas" + in_path= + fi + { echo "$as_me:$LINENO: checking for liblapack$in_path" >&5 +echo $ECHO_N "checking for liblapack$in_path... $ECHO_C" >&6; } +if test "${ncbi_cv_lib_lapack+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + CPPFLAGS=" $LAPACK_INCLUDE $orig_CPPFLAGS" + LIBS="$LAPACK_LIBS $orig_LIBS" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +extern "C" int dsyev_(); +int +main () +{ +return dsyev_(); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ncbi_cv_lib_lapack=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ncbi_cv_lib_lapack=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ncbi_cv_lib_lapack" >&5 +echo "${ECHO_T}$ncbi_cv_lib_lapack" >&6; } + if test "$ncbi_cv_lib_lapack" = "no"; then + if test "${with_lapack:=no}" != no; then + { { echo "$as_me:$LINENO: error: --with-lapack explicitly specified, but no usable version found." >&5 +echo "$as_me: error: --with-lapack explicitly specified, but no usable version found." >&2;} + { (exit 1); exit 1; }; } + fi + fi + fi + if test "$with_lapack" = "no"; then + LAPACK_PATH="No_LAPACK" + LAPACK_INCLUDE= + LAPACK_LIBS= + else + WithPackages="$WithPackages${WithPackagesSep}LAPACK"; WithPackagesSep=" " + LAPACK_INCLUDE=" $LAPACK_INCLUDE" + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LIBLAPACK 1 +_ACEOF + + fi + + + + +# LMDB +if test "$with_lmdb" != "no"; then + case "$with_lmdb" in + yes | "" ) ;; + * ) LMDB_PATH=$with_lmdb ;; + esac + if test "$LMDB_PATH" != /usr -a -d "$LMDB_PATH"; then + in_path=" in $LMDB_PATH" + if test -z "$LMDB_INCLUDE" -a -d "$LMDB_PATH/include"; then + LMDB_INCLUDE="-I$LMDB_PATH/include" + fi + if test -n "$LMDB_LIBPATH"; then + : + elif test -d "$LMDB_PATH/lib${bit64_sfx}"; then + ncbi_rp_L_flags= + ncbi_rp_L_sep=$CONF_f_libpath + if test "x${CONF_f_runpath}" = "x${CONF_f_libpath}"; then + for x in $LMDB_PATH/lib${bit64_sfx}; do + case "$x" in + /lib | /usr/lib | /usr/lib32 | /usr/lib64 | /usr/lib/$multiarch ) + continue + ;; + esac + ncbi_rp_L_flags="${ncbi_rp_L_flags}${ncbi_rp_L_sep}$x" + ncbi_rp_L_sep=" $CONF_f_libpath" + done + LMDB_LIBPATH="${ncbi_rp_L_flags}" + else + ncbi_rp_R_flags= + ncbi_rp_R_sep=" $CONF_f_runpath" + for x in $LMDB_PATH/lib${bit64_sfx}; do + case "$x" in + /lib | /usr/lib | /usr/lib32 | /usr/lib64 | /usr/lib/$multiarch ) + continue + ;; + esac + ncbi_rp_L_flags="${ncbi_rp_L_flags}${ncbi_rp_L_sep}$x" + ncbi_rp_L_sep=" $CONF_f_libpath" + x=`echo $x | sed -e "$ncbi_rpath_sed"` + ncbi_rp_R_flags="${ncbi_rp_R_flags}${ncbi_rp_R_sep}$x" + ncbi_rp_R_sep=: + done + LMDB_LIBPATH="${ncbi_rp_L_flags}${ncbi_rp_R_flags}" + fi + elif test -d "$LMDB_PATH/lib"; then + ncbi_rp_L_flags= + ncbi_rp_L_sep=$CONF_f_libpath + if test "x${CONF_f_runpath}" = "x${CONF_f_libpath}"; then + for x in $LMDB_PATH/lib; do + case "$x" in + /lib | /usr/lib | /usr/lib32 | /usr/lib64 | /usr/lib/$multiarch ) + continue + ;; + esac + ncbi_rp_L_flags="${ncbi_rp_L_flags}${ncbi_rp_L_sep}$x" + ncbi_rp_L_sep=" $CONF_f_libpath" + done + LMDB_LIBPATH="${ncbi_rp_L_flags}" + else + ncbi_rp_R_flags= + ncbi_rp_R_sep=" $CONF_f_runpath" + for x in $LMDB_PATH/lib; do + case "$x" in + /lib | /usr/lib | /usr/lib32 | /usr/lib64 | /usr/lib/$multiarch ) + continue + ;; + esac + ncbi_rp_L_flags="${ncbi_rp_L_flags}${ncbi_rp_L_sep}$x" + ncbi_rp_L_sep=" $CONF_f_libpath" + x=`echo $x | sed -e "$ncbi_rpath_sed"` + ncbi_rp_R_flags="${ncbi_rp_R_flags}${ncbi_rp_R_sep}$x" + ncbi_rp_R_sep=: + done + LMDB_LIBPATH="${ncbi_rp_L_flags}${ncbi_rp_R_flags}" + fi + fi + LMDB_LIBS="$LMDB_LIBPATH -llmdb " + else + LMDB_INCLUDE="" + LMDB_LIBS="-llmdb " + in_path= + fi + { echo "$as_me:$LINENO: checking for liblmdb$in_path" >&5 +echo $ECHO_N "checking for liblmdb$in_path... $ECHO_C" >&6; } +if test "${ncbi_cv_lib_lmdb+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + CPPFLAGS=" $LMDB_INCLUDE $orig_CPPFLAGS" + LIBS="$LMDB_LIBS $orig_LIBS" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +MDB_env *env; return mdb_env_create(&env); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ncbi_cv_lib_lmdb=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ncbi_cv_lib_lmdb=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ncbi_cv_lib_lmdb" >&5 +echo "${ECHO_T}$ncbi_cv_lib_lmdb" >&6; } + if test "$ncbi_cv_lib_lmdb" = "no"; then + if test "${with_lmdb:=no}" != no; then + { { echo "$as_me:$LINENO: error: --with-lmdb explicitly specified, but no usable version found." >&5 +echo "$as_me: error: --with-lmdb explicitly specified, but no usable version found." >&2;} + { (exit 1); exit 1; }; } + fi + fi + fi + if test "$with_lmdb" = "no"; then + LMDB_PATH="No_LMDB" + LMDB_INCLUDE= + LMDB_LIBS= + else + WithPackages="$WithPackages${WithPackagesSep}LMDB"; WithPackagesSep=" " + LMDB_INCLUDE=" $LMDB_INCLUDE" + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LIBLMDB 1 +_ACEOF + + fi + + + + ### Restore original compiler/linker flags LIBS="$orig_LIBS" CPPFLAGS="$orig_CPPFLAGS" @@ -45622,6 +46543,14 @@ if test "$with_gbench" != "no" -a -d "$real_srcdir/src/app/gbench"; then reason="$reason${sep}OpenGL" sep=", " fi + if test "$with_glew_mx" = "no"; then + reason="$reason${sep}GLEWmx" + sep=", " + fi + if test "$with_ftgl" = "no"; then + reason="$reason${sep}FTGL" + sep=", " + fi if test "$with_sqlite3" = "no"; then reason="$reason${sep}SQLite 3.x" sep=", " @@ -45630,6 +46559,18 @@ if test "$with_gbench" != "no" -a -d "$real_srcdir/src/app/gbench"; then reason="$reason${sep}Berkeley DB" sep=", " fi + if test "$ncbi_cv_lib_boost_spirit" != "yes"; then + reason=Boost.Spirit + sep=", " + fi + if test "$with_libxslt" = "no"; then + reason="$reason${sep}libxslt" + sep=", " + fi + if test "$with_gnutls" = "no"; then + reason="$reason${sep}GNUTLS" + sep=", " + fi if test "$with_mt" = "no"; then reason="$reason${sep}multithreading" sep=", " @@ -45723,7 +46664,7 @@ FEATURES="$WithFeatures $WithPackages $WithProjects" ### Compute Without{Features,Packages,Projects}. Takes quadratic time, ### but that's life. -for x in Int8GI StrictGI GCC KCC ICC VisualAge CompaqCompiler Cray WorkShop MIPSpro MSVC MT LFS DLL DLL_BUILD MaxDebug MSWin unix WinMain AIX BSD Cygwin CygwinMT Darwin XCODE IRIX Linux OSF Solaris MacOS in-house-resources JDK Ncbi-JNI PubSeqOS check Valgrind LimitedLinker; do +for x in ChaosMonkey Int8GI StrictGI GCC KCC ICC VisualAge CompaqCompiler Cray WorkShop MIPSpro MSVC MT LFS DLL DLL_BUILD MaxDebug MSWin unix WinMain AIX BSD Cygwin CygwinMT Darwin XCODE IRIX Linux OSF Solaris MacOS in-house-resources JDK Ncbi-JNI PubSeqOS check Valgrind LimitedLinker; do case " $WithFeatures " in *" $x "*) ;; *) WithoutFeatures="$WithoutFeatures$WithoutFeaturesSep$x" @@ -45732,7 +46673,7 @@ for x in Int8GI StrictGI GCC KCC ICC VisualAge CompaqCompiler Cray WorkShop MIPS ;; esac done - for x in UUID FUSE Iconv Z LocalZ BZ2 LocalBZ2 LZO PCRE LocalPCRE GMP GCRYPT NETTLE GNUTLS OPENSSL KRB5 CURL Sybase DBLib FreeTDS MySQL BerkeleyDB BerkeleyDB++ ODBC PYTHON PYTHON25 PYTHON26 PYTHON27 PYTHON3 PERL Boost.Filesystem Boost.Iostreams Boost.Program-Options Boost.Regex Boost.Spirit Boost.System Boost.Test Boost.Test.Included Boost.Thread C-Toolkit OpenGL MESA GLUT GLEW wxWidgets wx2.8 Fast-CGI LocalSSS LocalMSGMAIL2 SSSUTILS LocalNCBILS NCBILS2 SSSDB SP ORBacus ICU EXPAT SABLOT LIBXML LIBXSLT LIBEXSLT Xerces Xalan Zorba SQLITE3 SQLITE3ASYNC VDB OECHEM SGE MUPARSER HDF5 JPEG PNG TIFF UNGIF GIF XPM FreeType FTGL MAGIC MIMETIC GSOAP AVRO Cereal SASL2 MONGODB GMOCK; do + for x in UUID FUSE Iconv Z LocalZ BZ2 LocalBZ2 LZO PCRE LocalPCRE GMP GCRYPT NETTLE GNUTLS OPENSSL KRB5 CURL Sybase DBLib FreeTDS MySQL BerkeleyDB BerkeleyDB++ ODBC PYTHON PYTHON25 PYTHON26 PYTHON27 PYTHON3 PERL Boost.Filesystem Boost.Iostreams Boost.Program-Options Boost.Regex Boost.Spirit Boost.System Boost.Test Boost.Test.Included Boost.Thread C-Toolkit OpenGL MESA GLUT GLEW wxWidgets wx2.8 Fast-CGI LocalSSS LocalMSGMAIL2 SSSUTILS LocalNCBILS NCBILS2 SSSDB SP ORBacus ICU EXPAT SABLOT LIBXML LIBXSLT LIBEXSLT Xerces Xalan Zorba SQLITE3 SQLITE3ASYNC VDB OECHEM SGE MUPARSER HDF5 JPEG PNG TIFF UNGIF GIF XPM FreeType FTGL MAGIC MIMETIC GSOAP AVRO Cereal SASL2 MONGODB GMOCK LAPACK LMDB; do case " $WithPackages " in *" $x "*) ;; *) WithoutPackages="$WithoutPackages$WithoutPackagesSep$x" @@ -46100,6 +47041,18 @@ c_ncbi_runpath=`echo "$ncbi_runpath" | sed -e 's:\\$\\$:\\$:g'` + + + + + + + + + + + + @@ -46139,7 +47092,7 @@ ac_config_headers="$ac_config_headers ${ncbiconf}:src/build-system/config.h.in" ## ## Configure makefiles, shell scripts, etc. ## -ac_config_files="$ac_config_files $configurables $srcdir/./Makefile:src/build-system/Makefile.in.top" +ac_config_files="$ac_config_files $configurables $srcdir/./Makefile:src/build-system/Makefile.in.top $build_root/inc/common/ncbi_build_ver.h:include/common/ncbi_build_ver.h.in" ac_config_commands="$ac_config_commands default" @@ -46726,6 +47679,7 @@ do "${ncbiconf}") CONFIG_HEADERS="$CONFIG_HEADERS ${ncbiconf}:src/build-system/config.h.in" ;; "$configurables") CONFIG_FILES="$CONFIG_FILES $configurables" ;; "$srcdir/./Makefile") CONFIG_FILES="$CONFIG_FILES $srcdir/./Makefile:src/build-system/Makefile.in.top" ;; + "$build_root/inc/common/ncbi_build_ver.h") CONFIG_FILES="$CONFIG_FILES $build_root/inc/common/ncbi_build_ver.h:include/common/ncbi_build_ver.h.in" ;; "default") CONFIG_COMMANDS="$CONFIG_COMMANDS default" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 @@ -47092,6 +48046,10 @@ MONGODB_INCLUDE!$MONGODB_INCLUDE$ac_delim MONGODB_LIBS!$MONGODB_LIBS$ac_delim GMOCK_INCLUDE!$GMOCK_INCLUDE$ac_delim GMOCK_LIBS!$GMOCK_LIBS$ac_delim +LAPACK_INCLUDE!$LAPACK_INCLUDE$ac_delim +LAPACK_LIBS!$LAPACK_LIBS$ac_delim +LMDB_INCLUDE!$LMDB_INCLUDE$ac_delim +LMDB_LIBS!$LMDB_LIBS$ac_delim signature!$signature$ac_delim build_root!$build_root$ac_delim top_srcdir!$top_srcdir$ac_delim @@ -47158,10 +48116,6 @@ lib_pre!$lib_pre$ac_delim lib_l_pre!$lib_l_pre$ac_delim lib_ext!$lib_ext$ac_delim dll_ext!$dll_ext$ac_delim -loadable_ext!$loadable_ext$ac_delim -lib_l_ext!$lib_l_ext$ac_delim -exe_ext!$exe_ext$ac_delim -f_compile!$f_compile$ac_delim _ACEOF if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then @@ -47203,6 +48157,10 @@ _ACEOF ac_delim='%!_!# ' for ac_last_try in false false false false false :; do cat >conf$$subs.sed <<_ACEOF +loadable_ext!$loadable_ext$ac_delim +lib_l_ext!$lib_l_ext$ac_delim +exe_ext!$exe_ext$ac_delim +f_compile!$f_compile$ac_delim f_outobj!$f_outobj$ac_delim f_outlib!$f_outlib$ac_delim f_libpath!$f_libpath$ac_delim @@ -47296,10 +48254,6 @@ GLEW_STATIC_LIBS!$GLEW_STATIC_LIBS$ac_delim WXWIDGETS_INCLUDE!$WXWIDGETS_INCLUDE$ac_delim WXWIDGETS_LIBS!$WXWIDGETS_LIBS$ac_delim WXWIDGETS_STATIC_LIBS!$WXWIDGETS_STATIC_LIBS$ac_delim -WXWIDGETS_GL_LIBS!$WXWIDGETS_GL_LIBS$ac_delim -WXWIDGETS_GL_STATIC_LIBS!$WXWIDGETS_GL_STATIC_LIBS$ac_delim -WXWIDGETS_POST_LINK!$WXWIDGETS_POST_LINK$ac_delim -FASTCGI_INCLUDE!$FASTCGI_INCLUDE$ac_delim _ACEOF if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then @@ -47341,6 +48295,10 @@ _ACEOF ac_delim='%!_!# ' for ac_last_try in false false false false false :; do cat >conf$$subs.sed <<_ACEOF +WXWIDGETS_GL_LIBS!$WXWIDGETS_GL_LIBS$ac_delim +WXWIDGETS_GL_STATIC_LIBS!$WXWIDGETS_GL_STATIC_LIBS$ac_delim +WXWIDGETS_POST_LINK!$WXWIDGETS_POST_LINK$ac_delim +FASTCGI_INCLUDE!$FASTCGI_INCLUDE$ac_delim FASTCGI_LIBS!$FASTCGI_LIBS$ac_delim FASTCGI_OBJS!$FASTCGI_OBJS$ac_delim NCBI_SSS_INCLUDE!$NCBI_SSS_INCLUDE$ac_delim @@ -47349,9 +48307,18 @@ LIBSSSUTILS!$LIBSSSUTILS$ac_delim LIBSSSDB!$LIBSSSDB$ac_delim sssutils!$sssutils$ac_delim VDB_INCLUDE!$VDB_INCLUDE$ac_delim -VDB_LIB!$VDB_LIB$ac_delim VDB_LIBS!$VDB_LIBS$ac_delim VDB_STATIC_LIBS!$VDB_STATIC_LIBS$ac_delim +bamread!$bamread$ac_delim +sraread!$sraread$ac_delim +ncbi_id2proc_snp!$ncbi_id2proc_snp$ac_delim +ncbi_id2proc_wgs!$ncbi_id2proc_wgs$ac_delim +ncbi_xloader_bam!$ncbi_xloader_bam$ac_delim +ncbi_xloader_csra!$ncbi_xloader_csra$ac_delim +ncbi_xloader_snp!$ncbi_xloader_snp$ac_delim +ncbi_xloader_sra!$ncbi_xloader_sra$ac_delim +ncbi_xloader_vdbgraph!$ncbi_xloader_vdbgraph$ac_delim +ncbi_xloader_wgs!$ncbi_xloader_wgs$ac_delim VDB_REQ!$VDB_REQ$ac_delim VDB_POST_LINK!$VDB_POST_LINK$ac_delim SP_INCLUDE!$SP_INCLUDE$ac_delim @@ -47421,11 +48388,13 @@ compiler_version!$compiler_version$ac_delim COMPILER!$COMPILER$ac_delim OSTYPE!$OSTYPE$ac_delim NCBI_PLATFORM_BITS!$NCBI_PLATFORM_BITS$ac_delim +NCBI_TEAMCITY_BUILD_NUMBER!$NCBI_TEAMCITY_BUILD_NUMBER$ac_delim +NCBI_SUBVERSION_REVISION!$NCBI_SUBVERSION_REVISION$ac_delim +NCBI_SC_VERSION!$NCBI_SC_VERSION$ac_delim LIBOBJS!$LIBOBJS$ac_delim -LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 82; then + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 @@ -47444,6 +48413,48 @@ fi cat >>$CONFIG_STATUS <<_ACEOF cat >"\$tmp/subs-5.sed" <<\CEOF$ac_eof +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +_ACEOF +sed ' +s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g +s/^/s,@/; s/!/@,|#_!!_#|/ +:n +t n +s/'"$ac_delim"'$/,g/; t +s/$/\\/; p +N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n +' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF +CEOF$ac_eof +_ACEOF + + +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + cat >conf$$subs.sed <<_ACEOF +LTLIBOBJS!$LTLIBOBJS$ac_delim +_ACEOF + + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 1; then + break + elif $ac_last_try; then + { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 +echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} + { (exit 1); exit 1; }; } + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` +if test -n "$ac_eof"; then + ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` + ac_eof=`expr $ac_eof + 1` +fi + +cat >>$CONFIG_STATUS <<_ACEOF +cat >"\$tmp/subs-6.sed" <<\CEOF$ac_eof /@[a-zA-Z_][a-zA-Z_0-9]*@/!b end _ACEOF sed ' @@ -47748,7 +48759,7 @@ s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t $ac_datarootdir_hack -" $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed -f "$tmp/subs-2.sed" | sed -f "$tmp/subs-3.sed" | sed -f "$tmp/subs-4.sed" | sed -f "$tmp/subs-5.sed" >$tmp/out +" $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed -f "$tmp/subs-2.sed" | sed -f "$tmp/subs-3.sed" | sed -f "$tmp/subs-4.sed" | sed -f "$tmp/subs-5.sed" | sed -f "$tmp/subs-6.sed" >$tmp/out test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && @@ -47931,17 +48942,19 @@ else rm -f "$build_root/inc/ncbiconf_extra.h" fi -ncbicfg="$builddir/corelib/ncbicfg.c" -if test -f "$ncbicfg.last" && cmp -s "$ncbicfg.last" "$ncbicfg"; then - echo "$ncbicfg" is unchanged - touch -r "$ncbicfg.last" "$ncbicfg" -elif test -f "$ncbicfg"; then - echo "$ncbicfg" is updated - rm -f "$ncbicfg.last" - cp -p "$ncbicfg" "$ncbicfg.last" -else - echo "$ncbicfg" is not present -fi +for f in "$builddir/corelib/ncbicfg.c" \ + "$build_root/inc/common/ncbi_build_ver.h"; do + if test -f "$f.last" && cmp -s "$f.last" "$f"; then + echo "$f" is unchanged + touch -r "$f.last" "$f" + elif test -f "$f"; then + echo "$f" is updated + rm -f "$f.last" + cp -p "$f" "$f.last" + else + echo "$f" is not present + fi +done (cd $builddir/build-system/helpers && $MAKE -k) diff --git a/c++/src/build-system/configure.ac b/c++/src/build-system/configure.ac index fd0d72de..73537f01 100644 --- a/c++/src/build-system/configure.ac +++ b/c++/src/build-system/configure.ac @@ -1,5 +1,5 @@ ############################################################################# -# $Id: configure.ac 500366 2016-05-04 12:05:44Z ivanov $ +# $Id: configure.ac 521038 2016-12-05 16:02:28Z ivanov $ # Derived from configure.in version 1.173. # ========================================================================== # @@ -65,13 +65,13 @@ case "$with_3psw" in with_ncbi_c=no fi m4_foreach(X, [sss, sssutils, sssdb, vdb, z, bz2, lzo, pcre, - gmp, gcrypt, nettle, gnutls, openssl, krb5, boost, + gmp, gcrypt, nettle, gnutls, openssl, krb5, boost, lmdb, sybase, ftds, mysql, opengl, mesa, glut, glew, wxwidgets, freetype, ftgl, fastcgi, bdb, orbacus, odbc, python, perl, jni, sqlite3, mimetic, sge, icu, sp, expat, sablot, libxml, libxslt, libexslt, xerces, xalan, zorba, - oechem, muparser, hdf5, gif, jpeg, png, tiff, xpm, - magic, curl, gsoap, avro, cereal, sasl2, mongodb, gmock], + oechem, muparser, hdf5, gif, jpeg, png, tiff, xpm, magic, + curl, gsoap, avro, cereal, sasl2, mongodb, gmock, lapack], [if test "${[with_]X-no}" != "no"; then AC_MSG_ERROR([incompatible options: --with-]X[ but --without-3psw]) else @@ -147,10 +147,6 @@ AC_ARG_WITH(openmp, [ --with-openmp enable OpenMP extensions for all projects]) AC_ARG_WITH(64, [ --with-64 compile to 64-bit code]) -AC_ARG_WITH(universal, - [ --with-universal build universal binaries on Mac OS X]) -AC_ARG_WITH(universal2, - [ --with-universal=CPUs build universal binaries targeting the given CPUs]) AC_ARG_WITH(exe, [ --without-exe do not build executables]) AC_ARG_WITH(runpath, @@ -243,6 +239,8 @@ AC_ARG_WITH(vdb2, [ --without-vdb do not use the NCBI SRA/VDB Toolkit]) AC_ARG_WITH(downloaded-vdb, [ --with-downloaded-vdb download and build SRA/VDB from GitHub]) +AC_ARG_WITH(static-vdb, + [ --with-static-vdb always link statically against SRA/VDB]) ## Third-party and system packages AC_ARG_WITH(z, @@ -277,6 +275,8 @@ AC_ARG_WITH(gnutls, [ --with-gnutls=DIR use GNUTLS installation in DIR]) AC_ARG_WITH(gnutls2, [ --without-gnutls do not use GNUTLS]) +AC_ARG_WITH(static-gnutls, + [ --with-static-gnutls link GNUTLS statically if possible]) AC_ARG_WITH(openssl, [ --with-openssl=DIR use OpenSSL installation in DIR]) AC_ARG_WITH(openssl2, @@ -485,6 +485,14 @@ AC_ARG_WITH(gmock, [ --with-gmock=DIR use Google Mock installation in DIR]) AC_ARG_WITH(gmock2, [ --without-gmock do not use Google Mock]) +AC_ARG_WITH(lapack, + [ --with-lapack=DIR use LAPACK installation in DIR]) +AC_ARG_WITH(lapack2, + [ --without-lapack do not use LAPACK]) +AC_ARG_WITH(lmdb, + [ --with-lmdb=DIR use LMDB installation in DIR]) +AC_ARG_WITH(lmdb, + [ --without-lmdb do not use LMDB]) AC_ARG_WITH(3psw, [ --with-3psw=std:netopt favor standard (system) builds of the above pkgs.]) AC_ARG_WITH(3psw2, @@ -532,21 +540,21 @@ m4_rename([AS_MESSAGE_LOG_FD], [NCBI_ORIG_ASMLFD]) #### Check the passed arguments against the list of available ones x_with_list="\ debug max-debug symbols optimization profiling tcheck dll static static-exe \ -plugin-auto-load bundles bin-release mt 64 universal exe runpath hard-runpath \ +plugin-auto-load bundles bin-release mt 64 exe runpath hard-runpath \ lfs limited-linker openmp \ autodep suffix hostspec version execopy bincopy lib-rebuilds lib-rebuilds=ask \ deactivation makefile-auto-update projects flat-makefile configure-dialog \ check ncbi-public strip pch caution ccache distcc \ ncbi-c wxwidgets wxwidgets-ucs fastcgi sss sssdb sssutils included-sss \ -geo included-geo vdb downloaded-vdb \ -z bz2 lzo pcre gmp gcrypt nettle gnutls openssl krb5 \ +geo included-geo vdb downloaded-vdb static-vdb \ +z bz2 lzo pcre gmp gcrypt nettle gnutls static-gnutls openssl krb5 \ sybase sybase-local sybase-new ftds mysql \ orbacus freetype ftgl opengl mesa glut glew glew-mx \ bdb python perl jni sqlite3 icu boost boost-tag \ sp expat sablot libxml libxslt libexslt xerces xalan zorba \ oechem sge muparser hdf5 \ gif jpeg tiff png xpm \ -magic curl mimetic gsoap avro cereal sasl2 mongodb gmock 3psw \ +magic curl mimetic gsoap avro cereal sasl2 mongodb gmock lapack lmdb 3psw \ local-lbsm ncbi-crypt connext \ serial objects dbapi app ctools gui algo internal gbench" @@ -615,7 +623,7 @@ for x_arg in "$@" ; do | --with-jpeg=* | --with-png=* | --with-tiff=* | --with-xpm=* \ | --with-magic=* | --with-curl=* | --with-mimetic=* | --with-gsoap=* \ | --with-avro=* | --with-cereal=* | --with-sasl2* | --with-mongodb=* \ - | --with-gmock=* ) + | --with-gmock=* | --with-lapack=* | --with-lmdb=* ) # Confirm that the specified directory exists and is readable. dir=`echo $x_arg | sed -e 's/^[[^=]]*=//'` case "$x_arg" in @@ -637,7 +645,7 @@ for x_arg in "$@" ; do | --silent | --cache-file=* | -C | --config-cache | -n | --no-create \ | --no-recursion | --prefix=* | --exec-prefix=* | --bindir=* \ | --libdir=* | --includedir=* | --build=* | --host=* | --target=* \ - | --with-universal=* | --with-runpath=* | --with-relative-runpath=* \ + | --with-runpath=* | --with-relative-runpath=* \ | --with-experimental=* | --with-extra-action=* | --with-build-root=* \ | --with-fake-root=* | --with-build-root-sfx=* | --with-check=* \ | --with-check-tools=* | --with-ftds=[[0-9]]* | --with-fastcgi=[[0-9]]* \ @@ -654,11 +662,11 @@ AC_DIVERT_POP if test "$with_gbench" = "yes" ; then - m4_foreach(OPT, [dll,mt,gui,exe,serial,objects,algo,glew_mx], + m4_foreach(OPT, [dll,mt,gui,exe,serial,objects,algo,glew_mx,wxwidgets,ftgl,sqlite3,bdb,boost,xslt,gnutls], [if test "$[with_]OPT" = "no"; then AC_MSG_ERROR([incompatible options: --without-]OPT[ but --with-gbench]) else - [with_]OPT=yes + : ${[with_]OPT:=yes} fi ]) : ${with_projects=scripts/projects/ncbi_gbench.lst} @@ -712,6 +720,30 @@ case "$with_downloaded_vdb:$with_vdb" in ;; esac +case "$with_static_vdb:$with_vdb" in + yes:no ) + AC_MSG_ERROR([incompatible options: --without-vdb but --with-static-vdb]) + ;; + yes: ) + with_vdb=yes + ;; + :* ) + with_static_vdb=$with_bin_release + ;; +esac + +case "$with_static_gnutls:$with_gnutls" in + yes:no ) + AC_MSG_ERROR([incompatible options: --without-gnutls but --with-static-gnutls]) + ;; + yes: ) + with_gnutls=yes + ;; + :* ) + with_static_gnutls=$with_bin_release + ;; +esac + #### Check for special options if test "$with_extra_action" = "yes" ; then AC_MSG_ERROR([--with-extra-action must have a value after =]) @@ -765,12 +797,18 @@ USER_LDFLAGS=$LDFLAGS if test -n "$with_experimental"; then for x in `echo $with_experimental | tr , ' '`; do case "$x" in + ChaosMonkey ) + CPPFLAGS="$CPPFLAGS -DNCBI_MONKEY" + NCBI_FEATURE(ChaosMonkey) + ;; Int8GI ) CPPFLAGS="$CPPFLAGS -DNCBI_INT8_GI" + NCBI_C_PATH_TAGS="/ncbi.gi64 .gi64" NCBI_FEATURE(Int8GI) ;; StrictGI ) CPPFLAGS="$CPPFLAGS -DNCBI_STRICT_GI" + NCBI_C_PATH_TAGS="/ncbi.gi64 .gi64" NCBI_FEATURE(Int8GI) NCBI_FEATURE(StrictGI) ;; @@ -784,6 +822,38 @@ fi #### Always define this AC_DEFINE(NCBI_CXX_TOOLKIT, 1, [This is the NCBI C++ Toolkit.]) +AC_MSG_CHECKING([TeamCity build number]) +if test -n "$TEAMCITY_VERSION" -a -n "$BUILD_NUMBER"; then + AC_MSG_RESULT($BUILD_NUMBER) + NCBI_TEAMCITY_BUILD_NUMBER=$BUILD_NUMBER +else + AC_MSG_RESULT(none) + NCBI_TEAMCITY_BUILD_NUMBER=0 +fi + +AC_MSG_CHECKING([Subversion revision]) +svnrev=`svn info "$srcdir" 2>/dev/null | sed -ne 's/^Revision: //p'` +if test -n "$svnrev"; then + AC_MSG_RESULT($svnrev) + NCBI_SUBVERSION_REVISION=$svnrev +else + AC_MSG_RESULT(unknown) + NCBI_SUBVERSION_REVISION=0 +fi + +AC_MSG_CHECKING([NCBI stable components' version]) +scver=`svn info "$srcdir/src/build-system" 2>/dev/null | + sed -ne ['s,^URL: .*/production/components/[^/]*/\([1-9][0-9]*\)\..*,\1,p']` +if test -n "$scver"; then + AC_MSG_RESULT($scver) + NCBI_SC_VERSION=$scver +else + AC_MSG_RESULT(unknown) + NCBI_SC_VERSION=0 +fi + +AC_DEFINE(HAVE_COMMON_NCBI_BUILD_VER_H, 1, + [Define to 1 if you have the header file.]) #### Get the running host's properties AC_CONFIG_AUX_DIR(src/build-system) @@ -1139,14 +1209,15 @@ if test "$with_mt" != "no" ; then esac fi +case "$host_os:$compiler" in + solaris2.10:GCC ) : ${THREAD_LIBS:="-lposix4"} ;; + solaris* ) : ${THREAD_LIBS:="-lpthread -lposix4"} ;; + freebsd* ) ;; # -pthread already substitutes libc_r for libc + * ) : ${THREAD_LIBS:="-lpthread"} ;; +esac + if test "$with_mt" != "no" ; then CPPFLAGS="$CPPFLAGS -D_MT -D_REENTRANT -D_THREAD_SAFE" - case "$host_os:$compiler" in - solaris2.10:GCC ) : ${THREAD_LIBS:="-lposix4"} ;; - solaris* ) : ${THREAD_LIBS:="-lpthread -lposix4"} ;; - freebsd* ) ;; # -pthread already substitutes libc_r for libc - * ) : ${THREAD_LIBS:="-lpthread"} ;; - esac LIBS="$LIBS $THREAD_LIBS" case "$host_os:$compiler" in solaris2.??:* | solaris*:GCC | *:Compaq | irix* | aix* | darwin* | cygwin*) @@ -1193,7 +1264,6 @@ if test "$with_mt" != "no" ; then else CPPFLAGS="$CPPFLAGS -DNCBI_WITHOUT_MT" MT_FLAG= - THREAD_LIBS= NCBIATOMIC_LIB= OPENMP_FLAGS= mt_sfx="" @@ -1382,9 +1452,6 @@ case "$host_os:$compiler" in darwin?.* | darwin10.* ) # Mac OS X 10.6.x or older TARGET='-mmacosx-version-min=10.5' sdks="/Developer/SDKs/MacOSX10.6.sdk" - if test "$with_64:${with_universal-no}" != "yes:no"; then - sdks="/Developer/SDKs/MacOSX10.5.sdk $sdks" - fi ;; * ) TARGET='-mmacosx-version-min=10.7' @@ -1457,51 +1524,7 @@ C_LIBS=$LIBS ARCH_CPPFLAGS= #### architecture settings, and extra C++ LIBS -if test "${with_universal-no}" != "no" ; then - bit64_sfx= #"Univ" - case "$host" in - *-*-darwin[[89]].* | *-*-darwin[[1-9]][[0-9]]* ) - case "$with_universal" in - yes ) - case "$with_64:$host_os" in - yes:darwin8.* ) - AC_MSG_ERROR([Unable to build 64-bit universal binaries on $host]) - ;; - yes:* ) - ARCH_CFLAGS="-arch ppc64 -arch x86_64" - ARCH_CPPFLAGS="-m64" - ;; - * ) - ARCH_CFLAGS="-arch ppc -arch i386" - ARCH_CPPFLAGS="-m32" - ;; - esac - ;; - * ) - ARCH_CFLAGS="-arch `echo $with_universal | sed -e 's/,/ -arch /g'`" - ARCH_CPPFLAGS="-arch `echo $with_universal | sed -e 's/,.*//'`" - ;; - esac - case "$host" in - p*pc*-*-darwin8.*) - # Must specify -isysroot ..., but only once; anyway, the preprocessor - # needs to see it, and naturally can't cope with multiple -arch flags. - # The -mmacosx-version-min flag avoids link errors under OS 10.5 - # (Darwin 9), which otherwise tries to use crt1.10.5.o despite the - # request for a sysroot lacking that file. - SYSROOT="-isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.4" - #ARCH_CFLAGS="$SYSROOT $ARCH_CFLAGS" - CC="$CC $SYSROOT" - CXX="$CXX $SYSROOT" - ;; - esac - ;; - * ) AC_MSG_ERROR([Do not know how to build universal binaries on $host]) ;; - esac - AC_DEFINE(NCBI_UNIVERSAL_BUILD, 1, - [Define to 1 if building universal (multi-architecture) binaries.]) - with_distcc=no -elif test "$with_64" = "yes" ; then +if test "$with_64" = "yes" ; then bit64_sfx="64" case "$host:$compiler" in sparc-sun-solaris*:WorkShop5 | sparc-sun-solaris*:KCC ) @@ -1640,6 +1663,33 @@ if test -n "$with_64"; then fi fi +#### Don't let Clang pick up old (pre-C++11) system standard +#### library installations on Linux. +case "$host_os:/$CXX" in + linux*:*/clang* ) + gccver=4.9.3 + gccdir=/opt/ncbi/gcc/$gccver + if test -d $gccdir; then + for d in `$gccdir/bin/g++ -v -E -x c++ $ARCH_CFLAGS $ARCH_CPPFLAGS - \ + &1 | fgrep 'include/c++' | tac`; do + NCBI_FIX_DIR(d) + # We don't use a dedicated CXXCPPFLAGS variable, but sticking + # with -isystem rather than -cxx-isystem avoids spurious + # warnings when also using ccache or distcc, and should still + # be safe in practice. (The three libstdc++ headers that have + # the same names as system headers all arrange to include + # those headers via #include_next, and to conditionalize any + # C++ declarations on compiling as actual C++.) + CPPFLAGS="-isystem $d $CPPFLAGS" + done + CPPFLAGS="-nostdinc++ $CPPFLAGS" + libstdcxx=`$gccdir/bin/g++ --print-file-name=libstdc++.a` + d=`dirname $libstdcxx` + NCBI_FIX_DIR(d) + LDFLAGS="-L$d -Wl,-rpath,$d $LDFLAGS" + fi + ;; +esac case "$host_os:$compiler" in darwin*:GCC ) @@ -1707,28 +1757,23 @@ fi AC_CHECK_DECL([_LIBCPP_VERSION], [], [], [#include ]) -case "$ac_cv_have_decl__LIBCPP_VERSION:$compiler:$compiler_version" in - no:GCC:4[[0-6]]? | no:ICC:1[[01]]?? ) - ncbi_cv_prog_cxx_11=no - ncbi_cv_prog_c_99=no - ;; - *:ICC:* ) - ncbi_cv_prog_c_99='-std=gnu99 -fgnu89-inline' - ;; -esac - AC_CACHE_CHECK([how to enable C++ '11 features in $CXX], ncbi_cv_prog_cxx_11, [orig_CXX=$CXX ncbi_cv_prog_cxx_11=no - for x in -std=gnu++11 -std=gnu++0x; do + for x in -std=gnu++11 -std=gnu++0x ''; do CXX="$orig_CXX $x" - AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])], + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], + [std::unique_ptr x;])], [ncbi_cv_prog_cxx_11=$x]) test "x$ncbi_cv_prog_cxx_11" = "xno" || break done CXX=$orig_CXX]) -test "$ncbi_cv_prog_cxx_11" = no || CXX="$CXX $ncbi_cv_prog_cxx_11" +if test "$ncbi_cv_prog_cxx_11" = no; then + AC_MSG_ERROR([Please upgrade to a compiler supporting C++ '11, such as GCC 4.8 or newer.]) +else + CXX="$CXX $ncbi_cv_prog_cxx_11" +fi AC_LANG_PUSH(C) AC_CACHE_CHECK([how to enable C '11 or at least '99 features in $CC], @@ -2022,7 +2067,11 @@ case "$compiler:$compiler_version:$with_bin_release" in DLL_LDFLAGS="-static-intel -diag-disable 10237 -nodefaultlibs $DLL_LDFLAGS" # Redundant for apps, but necessary for plugins to be adequately # self-contained, at least on 32-bit Linux. - LIBS="$LIBS -lstdc++" + if test "$with_bin_release" = "yes"; then + LDFLAGS="$LDFLAGS -static-libstdc++" + elif test "$with_dll" != "no"; then + LIBS="$LIBS -lstdc++" + fi LINK="$LINK -Kc++" # Defining _GCC_NEXT_LIMITS_H ensures that chaining doesn't # stop short, as can otherwise happen. :-/ @@ -2179,8 +2228,7 @@ fi ### Support for precompiled headers GCCPCH="#" -if test "$compiler" = GCC -a "$with_pch" = "yes" \ - -a "${with_universal-no}" = "no"; then +if test "$compiler" = GCC -a "$with_pch" = "yes"; then AC_CACHE_CHECK([whether $CXX supports precompiled headers], ncbi_cv_cxx_pch, [echo '#include ' > conftest.hpp echo $CXX $CPPFLAGS $CXXFLAGS -xc++-header -c conftest.hpp >&AS_MESSAGE_LOG_FD @@ -2504,15 +2552,13 @@ fi #### Determine whether this is implicitly a 64-bit platform AC_TYPE_SIZE_T -if test "${with_universal-no}" = "no"; then - AC_CHECK_SIZEOF(size_t) - ac_cv_sizeof_size_t=`echo "$ac_cv_sizeof_size_t" | tr -d '\r'` - NCBI_PLATFORM_BITS=`expr 8 \* $ac_cv_sizeof_size_t` - AC_DEFINE_UNQUOTED(NCBI_PLATFORM_BITS, $NCBI_PLATFORM_BITS, - [Define to the architecture size.]) - if test $NCBI_PLATFORM_BITS -eq 64; then - bit64_sfx=64 - fi +AC_CHECK_SIZEOF(size_t) +ac_cv_sizeof_size_t=`echo "$ac_cv_sizeof_size_t" | tr -d '\r'` +NCBI_PLATFORM_BITS=`expr 8 \* $ac_cv_sizeof_size_t` +AC_DEFINE_UNQUOTED(NCBI_PLATFORM_BITS, $NCBI_PLATFORM_BITS, + [Define to the architecture size.]) +if test $NCBI_PLATFORM_BITS -eq 64; then + bit64_sfx=64 fi if test "$bit64_sfx" = 64 -o "$with_lfs" = "yes"; then @@ -3473,21 +3519,19 @@ fi AC_C_CONST ### Check for C standard types and sizes -if test "${with_universal-no}" = "no"; then - AC_C_BIGENDIAN - AC_C_CHAR_UNSIGNED - AC_CHECK_SIZEOF(char) - AC_CHECK_SIZEOF(double) - AC_CHECK_SIZEOF(float) - AC_CHECK_SIZEOF(int) - AC_CHECK_SIZEOF(long) - AC_CHECK_SIZEOF(long double) - AC_CHECK_SIZEOF(long long) - AC_CHECK_SIZEOF(short) - AC_CHECK_SIZEOF(void*) - AC_CHECK_SIZEOF(wchar_t, [], [#include ]) - AC_CHECK_SIZEOF(__int64) -fi +AC_C_BIGENDIAN +AC_C_CHAR_UNSIGNED +AC_CHECK_SIZEOF(char) +AC_CHECK_SIZEOF(double) +AC_CHECK_SIZEOF(float) +AC_CHECK_SIZEOF(int) +AC_CHECK_SIZEOF(long) +AC_CHECK_SIZEOF(long double) +AC_CHECK_SIZEOF(long long) +AC_CHECK_SIZEOF(short) +AC_CHECK_SIZEOF(void*) +AC_CHECK_SIZEOF(wchar_t, [], [#include ]) +AC_CHECK_SIZEOF(__int64) AC_CHECK_TYPES([intptr_t, uintptr_t]) AC_CHECK_MEMBER(struct sockaddr_in.sin_len, @@ -4374,6 +4418,28 @@ if test "x$with_gnutls" != xno -a -n "$GNUTLS_CONFIG_LIBS"; then *\ -lgcrypt* ) ;; * ) GNUTLS_LIBS="$GNUTLS_LIBS $GCRYPT_LIBS" ;; esac + if test "$with_static_gnutls" = yes; then + dirs='' + sep='' + static_libs='' + for x in $GNUTLS_LIBS; do + case $x in + -L* ) dirs="$dirs `echo _$x | cut -c4-`" ;; + -l* ) + want=lib`echo _$x | cut -c4-`-static.a + for d in $dirs; do + if test -f $d/$want; then + x=$x-static + break + fi + done + ;; + esac + static_libs=$static_libs$sep$x + sep=' ' + done + GNUTLS_LIBS=$static_libs + fi fi NCBI_CHECK_THIRD_PARTY_LIB_EX(openssl, OPENSSL, ssl, @@ -4400,6 +4466,7 @@ else TLS_LIBS=$OPENSSL_LIBS fi +NETWORK_LIBS="$TLS_LIBS $NETWORK_LIBS" case "$with_krb5" in no ) ac_cv_path_KRB5_CONFIG=no ;; @@ -4718,9 +4785,9 @@ if test "$with_ftds" != "no" ; then ftds_ver=64 try_local=yes case "$with_ftds" in - 64 | 0.64 | yes | '' ) + 64 | 0.64 ) ;; - 95 | 0.95 ) + 95 | 0.95 | yes | '' ) ftds_ver=95 ;; * ) @@ -4728,7 +4795,7 @@ if test "$with_ftds" != "no" ; then try_local=no ;; esac - : ${FTDS_CTLIBS:="-lct -ltds"} + : ${FTDS_CTLIBS:="-lct -ltds $NETWORK_LIBS"} NCBI_RPATHIFY(FTDS_CTLIBS, $FTDS_PATH/lib, [ ]$FTDS_CTLIBS) FTDS_INCLUDE="-I$FTDS_PATH/include" NCBI_LOCAL_FTDS(64) @@ -4905,14 +4972,20 @@ if test "$with_bdb" != "no" ; then AC_CACHE_CHECK([Berkeley DB version (4.3 or newer required)], ncbi_cv_lib_berkeley_db_version, [AC_LANG_CONFTEST([AC_LANG_SOURCE([[ +cat >/dev/null <<_NCBI_EOF #include -ncbi_cv_lib_berkeley_db_version=DB_VERSION_MAJOR.DB_VERSION_MINOR.DB_VERSION_PATCH +_NCBI_EOF +get_DB_VERSION() { + grep '^[^#]' <<_NCBI_EOF +DB_VERSION_MAJOR.DB_VERSION_MINOR.DB_VERSION_PATCH +_NCBI_EOF +} +ncbi_cv_lib_berkeley_db_version=\`get_DB_VERSION | tr -cd 0123456789.\` ]])]) - eval "$ac_cpp $BERKELEYDB_INCLUDE conftest.$ac_ext" \ - 2>&AS_MESSAGE_LOG_FD | grep '^ncbi_cv_' \ - | tr -d "$wschars" > conftest.sh + eval "$ac_cpp $BERKELEYDB_INCLUDE conftest.$ac_ext" > conftest.sh \ + 2>&AS_MESSAGE_LOG_FD . ./conftest.sh - rm -f contest* + rm -f conftest* ]) case "$ncbi_cv_lib_berkeley_db_version" in 1.* | 2.* | 3.* | 4.[[0-2]].* ) @@ -5181,15 +5254,26 @@ if test "$with_boost" != "no"; then AC_CACHE_CHECK([Boost version], ncbi_cv_lib_boost_version, [AC_LANG_CONFTEST([AC_LANG_SOURCE([[ +cat >/dev/null <<_NCBI_EOF #include -ncbi_cv_lib_boost_version_num=BOOST_VERSION -ncbi_cv_lib_boost_version=BOOST_LIB_VERSION +_NCBI_EOF +get_BOOST_VERSION() { + grep '^[^#]' <<_NCBI_EOF +BOOST_VERSION +_NCBI_EOF +} +get_BOOST_LIB_VERSION() { + grep '^[^#]' <<_NCBI_EOF +BOOST_LIB_VERSION +_NCBI_EOF +} +ncbi_cv_lib_boost_version_num=\`get_BOOST_VERSION\` +ncbi_cv_lib_boost_version=\`get_BOOST_LIB_VERSION | tr -d '"'\` ]])]) - eval "$ac_cpp $BOOST_INCLUDE conftest.$ac_ext" \ - 2>&AS_MESSAGE_LOG_FD | grep '^ncbi_cv_' \ - | tr -d "$wschars" > conftest.sh + eval "$ac_cpp $BOOST_INCLUDE conftest.$ac_ext" > conftest.sh \ + 2>&AS_MESSAGE_LOG_FD . ./conftest.sh - rm -f contest* + rm -f conftest* ]) AC_DEFINE_UNQUOTED(NCBI_EXPECTED_BOOST_VERSION, $ncbi_cv_lib_boost_version_num, @@ -5224,7 +5308,7 @@ ncbi_cv_lib_boost_version=BOOST_LIB_VERSION fi with_boost=no ;; - 1_3[[5-9]] | 1_3[[5-9]]_* | 1_[[45]]* | 1_60 | 1_60_* ) ;; + 1_3[[5-9]] | 1_3[[5-9]]_* | 1_[[45]]* | 1_6[[0-2]] | 1_6[[0-2]]_* ) ;; '' ) with_boost=no ;; * ) AC_MSG_WARN( @@ -5611,6 +5695,14 @@ if test "$with_ncbi_c" != "no" ; then if test "$ncbi_compiler" = ICC -a -d "$NCBI_C_PATH/ncbi_icc"; then NCBI_C_PATH=$NCBI_C_PATH/ncbi_icc fi + if test -n "$NCBI_C_PATH_TAGS"; then + for x in $NCBI_C_PATH_TAGS; do + if test -d "$NCBI_C_PATH$x"; then + NCBI_C_PATH=$NCBI_C_PATH$x + break + fi + done + fi NCBI_C_INCLUDE="-I$NCBI_C_PATH/include${bit64_sfx}" if test "$with_debug" = "no" ; then @@ -6736,6 +6828,12 @@ VDB_REQ=VDB if test "$with_vdb" != "no" ; then # CURL? vdb_deps="$LIBXML_LIBS $NETWORK_LIBS $BZ2_LIBS $Z_LIBS $DL_LIBS" + # In MT builds, ORIG_LIBS already contains THREAD_LIBS. However, + # VDB is always threaded, and may need explicit THREAD_LIBS when + # used statically. + if test "$with_mt" = no; then + vdb_deps="$vdb_deps $THREAD_LIBS" + fi if test "${with_vdb:-yes}" != "yes" -a -d "$with_vdb"; then VDB_PATH=$with_vdb fi @@ -6772,13 +6870,30 @@ if test "$with_vdb" != "no" ; then in_path=" in $VDB_PATH" for x in interfaces include; do if test -d "$VDB_PATH/$x"; then - : ${VDB_INCLUDE="-I$VDB_PATH/$x"} + vdb_inc_root=$VDB_PATH/$x + : ${VDB_INCLUDE="-I$vdb_inc_root"} break fi done + vdb_inc_subdirs=cc/gcc + case "$host_cpu:$bit64_sfx" in + *86*:64 ) vdb_inc_subdirs="cc/gcc/x86_64 $vdb_inc_subdirs" ;; + *86*:* ) vdb_inc_subdirs="cc/gcc/fat86 $vdb_inc_subdirs" ;; + esac + if test "$ncbi_compiler" = ICC; then + vdb_inc_subdirs="cc/icc $vdb_inc_subdirs" + fi + case "$host_os" in + darwin* ) vdb_inc_subdirs="os/mac os/unix $vdb_inc_subdirs" ;; + linux* ) vdb_inc_subdirs="os/linux os/unix $vdb_inc_subdirs" ;; + solaris* ) vdb_inc_subdirs="os/sun os/unix $vdb_inc_subdirs" ;; + esac + for x in $vdb_inc_subdirs; do + VDB_INCLUDE="$VDB_INCLUDE -I$vdb_inc_root/$x" + done case "$DEBUG_SFX" in Debug ) - VDB_INCLUDE="$VDB_INCLUDE $VDB_INCLUDE/cc/gcc -D_DEBUGGING" + VDB_INCLUDE="$VDB_INCLUDE -D_DEBUGGING" vdb_mode=debug ;; Release ) @@ -6813,9 +6928,11 @@ if test "$with_vdb" != "no" ; then [ncbi_cv_lib_ncbi_vdb=yes], [ncbi_cv_lib_ncbi_vdb=no])) if test "$ncbi_cv_lib_ncbi_vdb" = yes; then NCBI_PACKAGE(VDB) - VDB_LIB= if test -f "$VDB_LIBDIR/libncbi-vdb-static.a"; then VDB_STATIC_LIBS="-L$VDB_LIBDIR -lncbi-vdb-static $vdb_deps" + if test "$with_static_vdb" = yes; then + VDB_LIBS=$VDB_STATIC_LIBS + fi else VDB_STATIC_LIBS=$VDB_LIBS fi @@ -6832,10 +6949,32 @@ if test "$with_vdb" != "no" ; then esac ;; esac + AC_DEFINE(HAVE_NCBI_VDB, 1, + [Define to 1 if you have NCBI's SRA/VDB SDK/Toolkit.]) + bamread=bamread + sraread=sraread + ncbi_id2proc_snp=ncbi_id2proc_snp + ncbi_id2proc_wgs=ncbi_id2proc_wgs + ncbi_xloader_bam=ncbi_xloader_bam + ncbi_xloader_csra=ncbi_xloader_csra + ncbi_xloader_snp=ncbi_xloader_snp + ncbi_xloader_sra=ncbi_xloader_sra + ncbi_xloader_vdbgraph=ncbi_xloader_vdbgraph + ncbi_xloader_wgs=ncbi_xloader_wgs else VDB_INCLUDE= VDB_LIBS= VDB_STATIC_LIBS= + bamread= + sraread= + ncbi_id2proc_snp= + ncbi_id2proc_wgs= + ncbi_xloader_bam= + ncbi_xloader_csra= + ncbi_xloader_snp= + ncbi_xloader_sra= + ncbi_xloader_vdbgraph= + ncbi_xloader_wgs= fi # else ... # fi @@ -7280,6 +7419,38 @@ NCBI_CHECK_THIRD_PARTY_LIB(gmock, [-lgtest]) +# LAPACK +CPPFLAGS="-DHAVE_LAPACK_CONFIG_H $orig_CPPFLAGS" +case "$with_lapack" in + yes | no | '' ) ;; + * ) LAPACK_PATH=$with_lapack ;; +esac +if test -d "$LAPACK_PATH"; then + NCBI_FIX_DIR(LAPACK_PATH) + CPPFLAGS="-I$LAPACK_PATH/include $CPPFLAGS" +fi +AC_LANG_PUSH(C) +AC_CHECK_HEADERS(lapacke.h lapacke/lapacke.h clapack.h Accelerate/Accelerate.h) +AC_LANG_POP(C) +if test "$ac_cv_header_clapack_h:$ac_cv_header_Accelerate_Accelerate_h" != no:no; then + AC_CHECK_TYPES([__CLPK_integer], [], [], + [[#ifdef HAVE_CLAPACK_H + # include + #else + # include + #endif]]) +fi + +NCBI_CHECK_THIRD_PARTY_LIB(lapack, + [AC_LANG_PROGRAM([[extern "C" int dsyev_();]], + [[return dsyev_();]])], + [-lblas]) + +# LMDB +NCBI_CHECK_THIRD_PARTY_LIB(lmdb, + [AC_LANG_PROGRAM([[#include ]], + [[MDB_env *env; return mdb_env_create(&env);]])]) + ### Restore original compiler/linker flags LIBS="$orig_LIBS" CPPFLAGS="$orig_CPPFLAGS" @@ -7568,6 +7739,14 @@ if test "$with_gbench" != "no" -a -d "$real_srcdir/src/app/gbench"; then reason="$reason${sep}OpenGL" sep=", " fi + if test "$with_glew_mx" = "no"; then + reason="$reason${sep}GLEWmx" + sep=", " + fi + if test "$with_ftgl" = "no"; then + reason="$reason${sep}FTGL" + sep=", " + fi if test "$with_sqlite3" = "no"; then reason="$reason${sep}SQLite 3.x" sep=", " @@ -7576,6 +7755,18 @@ if test "$with_gbench" != "no" -a -d "$real_srcdir/src/app/gbench"; then reason="$reason${sep}Berkeley DB" sep=", " fi + if test "$ncbi_cv_lib_boost_spirit" != "yes"; then + reason=Boost.Spirit + sep=", " + fi + if test "$with_libxslt" = "no"; then + reason="$reason${sep}libxslt" + sep=", " + fi + if test "$with_gnutls" = "no"; then + reason="$reason${sep}GNUTLS" + sep=", " + fi if test "$with_mt" = "no"; then reason="$reason${sep}multithreading" sep=", " @@ -7956,9 +8147,18 @@ AC_SUBST(LIBSSSUTILS) AC_SUBST(LIBSSSDB) AC_SUBST(sssutils) AC_SUBST(VDB_INCLUDE) -AC_SUBST(VDB_LIB) AC_SUBST(VDB_LIBS) AC_SUBST(VDB_STATIC_LIBS) +AC_SUBST(bamread) +AC_SUBST(sraread) +AC_SUBST(ncbi_id2proc_snp) +AC_SUBST(ncbi_id2proc_wgs) +AC_SUBST(ncbi_xloader_bam) +AC_SUBST(ncbi_xloader_csra) +AC_SUBST(ncbi_xloader_snp) +AC_SUBST(ncbi_xloader_sra) +AC_SUBST(ncbi_xloader_vdbgraph) +AC_SUBST(ncbi_xloader_wgs) AC_SUBST(VDB_REQ) AC_SUBST(VDB_POST_LINK) AC_SUBST(SP_INCLUDE) @@ -8036,6 +8236,9 @@ AC_SUBST(COMPILER) AC_SUBST(OSTYPE) AC_SUBST(NCBI_PLATFORM_BITS) +AC_SUBST(NCBI_TEAMCITY_BUILD_NUMBER) +AC_SUBST(NCBI_SUBVERSION_REVISION) +AC_SUBST(NCBI_SC_VERSION) ############################################################################# ### Create output files and do some post-configuration @@ -8064,7 +8267,9 @@ AC_CONFIG_HEADER(${ncbiconf}:src/build-system/config.h.in) ## ## Configure makefiles, shell scripts, etc. ## -AC_CONFIG_FILES($configurables $srcdir/./Makefile:src/build-system/Makefile.in.top) +AC_CONFIG_FILES($configurables \ + $srcdir/./Makefile:src/build-system/Makefile.in.top \ + $build_root/inc/common/ncbi_build_ver.h:include/common/ncbi_build_ver.h.in) AC_CONFIG_COMMANDS([default], [ dnl make all shell scripts *.sh be executable @@ -8137,18 +8342,20 @@ else rm -f "$build_root/inc/ncbiconf_extra.h" fi -dnl Avoid gratuitous relinking -ncbicfg="$builddir/corelib/ncbicfg.c" -if test -f "$ncbicfg.last" && cmp -s "$ncbicfg.last" "$ncbicfg"; then - echo "$ncbicfg" is unchanged - touch -r "$ncbicfg.last" "$ncbicfg" -elif test -f "$ncbicfg"; then - echo "$ncbicfg" is updated - rm -f "$ncbicfg.last" - cp -p "$ncbicfg" "$ncbicfg.last" -else - echo "$ncbicfg" is not present -fi +dnl Avoid gratuitous rebuilding +for f in "$builddir/corelib/ncbicfg.c" \ + "$build_root/inc/common/ncbi_build_ver.h"; do + if test -f "$f.last" && cmp -s "$f.last" "$f"; then + echo "$f" is unchanged + touch -r "$f.last" "$f" + elif test -f "$f"; then + echo "$f" is updated + rm -f "$f.last" + cp -p "$f" "$f.last" + else + echo "$f" is not present + fi +done dnl Try to build simple helpers (cd $builddir/build-system/helpers && $MAKE -k) diff --git a/c++/src/build-system/datatool_version.txt b/c++/src/build-system/datatool_version.txt index edcfe40d..75249069 100644 --- a/c++/src/build-system/datatool_version.txt +++ b/c++/src/build-system/datatool_version.txt @@ -1 +1 @@ -2.14.0 +2.16.0 diff --git a/c++/src/build-system/helpers/Makefile.run_with_lock.app b/c++/src/build-system/helpers/Makefile.run_with_lock.app index 97317f4e..442fb766 100644 --- a/c++/src/build-system/helpers/Makefile.run_with_lock.app +++ b/c++/src/build-system/helpers/Makefile.run_with_lock.app @@ -1,4 +1,4 @@ -# $Id: Makefile.run_with_lock.app 493416 2016-02-26 18:48:41Z ivanov $ +# $Id: Makefile.run_with_lock.app 492995 2016-02-23 17:06:47Z ucko $ APP = run_with_lock SRC = run_with_lock diff --git a/c++/src/build-system/helpers/run_with_lock.c b/c++/src/build-system/helpers/run_with_lock.c index f492fb5b..f0159b0a 100644 --- a/c++/src/build-system/helpers/run_with_lock.c +++ b/c++/src/build-system/helpers/run_with_lock.c @@ -1,4 +1,4 @@ -/* $Id: run_with_lock.c 500280 2016-05-03 17:21:37Z ivanov $ +/* $Id: run_with_lock.c 520549 2016-11-29 18:58:00Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -185,13 +185,14 @@ int s_Tee(int in, FILE* out1, FILE* out2, EFilterState* state) if (*state == eFS_esc) { if (*p == '[') { ++p; - --n; + /* --n; */ /* overadjusts when the final m turns up */ *state = eFS_csi; } else { fputc('\033', out2); *state = eFS_on; } - } else if (*state == eFS_csi) { + } + if (*state == eFS_csi) { p = memchr(buffer, 'm', n); if (p == NULL) { continue; @@ -211,23 +212,25 @@ int s_Tee(int in, FILE* out1, FILE* out2, EFilterState* state) if (src > dest && start > src) { memmove(dest, src, start - src); } + dest += start - src; if (start == p + n - 1) { *state = eFS_esc; - n = start - p; + n = dest - p; break; } - dest += start - src; const char* end = memchr(start + 2, 'm', n - 2 - (start - p)); if (end == NULL) { *state = eFS_csi; - n = start - p; + n = dest - p; break; } else { src = end + 1; } } - memmove(dest, src, n - (src - p)); - n -= src - dest; + if (*state == eFS_on) { + memmove(dest, src, n - (src - p)); + n -= src - dest; + } } if (fwrite(p, 1, n, out2) < n) { fprintf(stderr, "%s: Error logging process output: %s.\n", @@ -256,7 +259,8 @@ static int s_OpenPipeOrPty(int fd_to_mimic, const char* label, int fds[2], EFilterState* state) { - if (isatty(fd_to_mimic)) { + const char* term = getenv("TERM"); + if (term != NULL && strcmp(term, "dumb") && isatty(fd_to_mimic)) { struct termios attr; const char* name; *state = eFS_on; diff --git a/c++/src/build-system/install.sh.in b/c++/src/build-system/install.sh.in index 65791cea..4fd31d79 100644 --- a/c++/src/build-system/install.sh.in +++ b/c++/src/build-system/install.sh.in @@ -17,7 +17,7 @@ echo "[`date`]" -svn_location=`echo '$HeadURL: https://svn.ncbi.nlm.nih.gov/repos/toolkit/release/blast/2.4.0/c++/src/build-system/install.sh.in $' | sed "s%\\$[H]eadURL: *\\([^$][^$]*\\) \\$.*%\\1%"` +svn_location=`echo '$HeadURL: https://svn.ncbi.nlm.nih.gov/repos/toolkit/release/blast/2.6.0/c++/src/build-system/install.sh.in $' | sed "s%\\$[H]eadURL: *\\([^$][^$]*\\) \\$.*%\\1%"` svn_revision=`echo '$Revision: 117476 $' | sed "s%\\$[R]evision: *\\([^$][^$]*\\) \\$.*%\\1%"` script_name=`basename $0` diff --git a/c++/src/build-system/library_relations.txt b/c++/src/build-system/library_relations.txt index 45ad8abe..279fae5b 100644 --- a/c++/src/build-system/library_relations.txt +++ b/c++/src/build-system/library_relations.txt @@ -1,7 +1,8 @@ -# $Id: library_relations.txt 490610 2016-01-27 15:05:28Z syncbot $ +# $Id: library_relations.txt 507530 2016-07-19 20:26:26Z syncbot $ # Pregenerated summary of library relations, for use by project_tree_builder. $(ORIG_LIBS) needs3party 16S_common needs seqset +16S_common needs xmlwrapp 16S_summaries needs 16S_common 16S_summaries needs gpipe_xmlutil 16S_summaries needs xregexp @@ -27,15 +28,12 @@ GLEW needs3party $(ORIG_LIBS) GLU needs3party $(ORIG_LIBS) GLU needs3party X11 GLU needs3party Xext -GMA needs $(SDBAPI_LIB) -GMA needs xconnect -GMA needs xutil -GMC needs geomyncbi +GMC needs $(CONNEXT) +GMC needs softparse GMC needs xgridcgi -GMU needs $(COMPRESS_LIBS) -GMU needs geoauth OSMesa needs3party $(OPENGL_LIBS) OSMesa needs3party $(ORIG_LIBS) +TxPubmedBackend needs txserv VDBUtils needs bdbasncli VDBUtils needs ncbi_xloader_csra VDBUtils needs ncbi_xloader_wgs @@ -64,8 +62,6 @@ align_format needs taxon1 align_format needs xalnmgr align_format needs xcgi align_format needs xhtml -align_part_ci needs $(SEQ_LIBS) -align_part_ci needs pub aligndb_client needs $(SEQ_LIBS) aligndb_client needs pub aligndb_reader needs $(COMPRESS_LIBS) @@ -77,55 +73,52 @@ alndb_query needs $(SEQ_LIBS) alndb_query needs pub alndbaccess needs alndb_query alndbaccess needs generic_db_core +an_core needs $(GPIPE_COMMON_LIBS) an_core needs 16S_common an_core needs gc_util_sdbapi an_core needs gpinit_bag_util an_core needs gpipe_an_base an_core needs gpipe_kmer -an_core needs gpipe_xmlutil -an_core needs ncbi_xcache_netcache an_core needs pathogen_connection an_core needs reftrack_access an_euk_pipeline needs $(GPIPE_COMMON_LIBS) an_euk_pipeline needs bag_access an_euk_pipeline needs gpipe_an_base an_euk_pipeline needs gpipe_val -an_euk_pipeline needs reftrack_admin +an_euk_pipeline needs reftrack_access an_euk_pipeline needs3party $(BOOST_FILESYSTEM_LIBS) an_euk_pipeline needs3party $(BOOST_SYSTEM_LIBS) -an_prok_pipeline needs $(GPIPE_COMMON_LIBS) an_prok_pipeline needs gpipe_an_base an_prok_pipeline needs gpipe_asn_proc an_prok_pipeline needs pathogen_connection an_prok_pipeline needs tax_xml an_prok_pipeline needs xobjwrite an_worker_nodes needs gpipe_an_base -asn_cache includes id_dump +asn_cache needs $(COMPRESS_LIBS) +asn_cache needs bdb +asn_cache needs seqset asn_config needs build_config_base asn_config needs config_access asn_config needs gpipe_objutil -asn_config needs reftrack_access asn_sample_lib needs xser asngendefs needs xser asnmuxdblb needs dbloadb_asn asnmuxdblb needs generic_db_asn asnmuxdblb needs mux +attr_cd needs3party $(ORIG_LIBS) auxcomm_g needs muxex-C_g auxcomm_g needs splitdbasncpp_g auxcomm_g needs tea_crypt auxcommcpp_g needs muxex_g auxnet_g needs generic_db_utils -backendcommon needs $(SDBAPI_LIB) -backendcommon needs txxmldoc -backendcommon needs xconnect +bacterial_pipeline_proc needs attr_cd bacterial_pipeline_proc needs gencoll_client -bacterial_pipeline_proc needs gpipe_objutil -bacterial_pipeline_proc needs prok_align_monomer +bacterial_pipeline_proc needs gpipe_alnutil bacterial_pipeline_proc needs xalgoalignutil bag_access needs $(SEQ_LIBS) bag_access needs gpipe_common bag_access needs pub -bamread needs $(VDB_LIB) +bamread needs $(COMPRESS_LIBS) bamread needs seqset bamread needs3party $(VDB_LIBS) basic_sample_lib needs xncbi @@ -136,7 +129,6 @@ bdbasncli needs bdb2ez bdbasncli needs xconnect biblio needs general biosample needs $(SDBAPI_LIB) -biosample needs xconnect biosample needs xmlwrapp biosample needs xregexp biosample needs xutil @@ -150,6 +142,9 @@ blast needs tables blast_app_util needs $(BLAST_INPUT_LIBS) blast_app_util needs $(BLAST_LIBS) blast_services needs xnetblastcli +blast_sra_input needs $(BLAST_INPUT_LIBS) +blast_sra_input needs $(BLAST_LIBS) +blast_sra_input needs $(SRAREAD_LIBS) blast_unit_test_util needs $(BLAST_LIBS) blast_unit_test_util needs $(OBJMGR_LIBS) blast_unit_test_util needs3party $(BOOST_TEST_LIBS) @@ -171,27 +166,24 @@ blastxml needs xser blastxml2 needs xser bob_g needs splitdbasn_g bob_g needs3party netblast -boost_filesystem-gcc44-mt-d-64 needs3party $(BOOST_SYSTEM_LIBS) -boost_filesystem-gcc44-mt-d-64 needs3party $(ORIG_LIBS) -boost_system-gcc44-mt-d-64 needs3party $(ORIG_LIBS) -boost_unit_test_framework-gcc44-mt-d-64 needs3party $(ORIG_LIBS) -build_config needs $(GPIPE_COMMON_LIBS) +boost_filesystem-gcc48-mt-d-64 needs3party $(BOOST_SYSTEM_LIBS) +boost_filesystem-gcc48-mt-d-64 needs3party $(ORIG_LIBS) +boost_system-gcc48-mt-d-64 needs3party $(ORIG_LIBS) +boost_unit_test_framework-gcc48-mt-d-64 needs3party $(ORIG_LIBS) build_config needs $(GPIPE_GENCOLL_LIBS) build_config needs bacterial_pipeline_proc build_config needs build_config_base build_config needs gpipe_xmlutil build_config needs reftrack_access +build_config needs simple_asm build_config_base needs gencoll_client build_config_base needs gpinit_bag_util build_config_base needs gpinit_register bz2 needs3party $(ORIG_LIBS) -cache_blob needs $(COMPRESS_LIBS) -cache_blob needs xser cache_g needs generic_db_utils cdd needs cn3d cdd needs scoremat clog needs3party $(ORIG_LIBS) -cluster needs3party $(ORIG_LIBS) cluster_assignment needs xser cluster_utils needs gpipe_objutil clustering needs cobalt @@ -206,13 +198,10 @@ com_err needs3party $(ORIG_LIBS) composition_adjustment needs3party $(ORIG_LIBS) config_access needs gpinit_obj config_access needs gpipe_common -configure_ctl needs gpipe_common connect needs3party $(NETWORK_LIBS) connect needs3party $(ORIG_LIBS) connext needs connect connssl needs connect -connssl needs3party $(GCRYPT_LIBS) -connssl needs3party $(GNUTLS_LIBS) creaders needs3party $(ORIG_LIBS) crypto needs $(Z_LIB) crypto needs3party $(ORIG_LIBS) @@ -220,13 +209,19 @@ crypto needs3party $(Z_LIBS) ct_ftds64 needs tds_ftds64 ct_ftds95 needs tds_ftds95 ctransition needs xncbi -ctutils needs $(VDB_LIB) ctutils needs3party $(SYBASE_DLLS) ctutils needs3party $(SYBASE_LIBS) ctutils needs3party $(VDB_LIBS) ctutils needs3party ncbiobj -ctutils needs3party sybunic64 curl needs3party $(ORIG_LIBS) +data_loaders_util needs $(OBJMGR_LIBS) +data_loaders_util needs $(ncbi_xreader_pubseqos2) +data_loaders_util needs ncbi_xdbapi_ftds +data_loaders_util needs ncbi_xloader_asn_cache +data_loaders_util needs ncbi_xloader_blastdb +data_loaders_util needs ncbi_xloader_csra +data_loaders_util needs ncbi_xloader_lds2 +data_loaders_util needs ncbi_xloader_wgs db needs3party $(ORIG_LIBS) dbapi needs dbapi_driver dbapi_driver needs xncbi @@ -260,9 +255,10 @@ docsum needs xser drmaa needs3party $(ORIG_LIBS) dtd_sample_lib needs xser dummy_gpipe needs3party $(ORIG_LIBS) +ec_hmm_relation_cd needs3party $(ORIG_LIBS) edirect needs eueid edirect needs ncqhst -edirect needs txservbase +edirect needs txserv egenedb needs $(COMPRESS_LIBS) egenedb needs $(CONNEXT) egenedb needs dbapi_driver_wrap_s @@ -295,7 +291,6 @@ eutils needs espell eutils needs esummary eutils needs uilist eutils needs xconnect -eutils_client needs xconnect eutils_client needs xmlwrapp eutilsapp includes eueid eutilsapp needs ncqhst @@ -310,6 +305,10 @@ fbsdstd_g needs3party $(ORIG_LIBS) fcgi needs3party $(ORIG_LIBS) featdef needs xser filter_snps needs xalnmgr +flatfile needs $(OBJMGR_LIBS) +flatfile needs ncbi_xcache_netcache +flatfile needs ncbi_xloader_wgs +flatfile needs xobjwrite freetype needs3party $(ORIG_LIBS) fscreen needs agp_lookup fscreen needs dbapi_util_blobstore @@ -319,7 +318,10 @@ ftgl needs3party $(ORIG_LIBS) gbproj needs submit gbproj needs xconnect gbseq needs xser +gc_assm_rpt needs gcaccess_utils +gc_common needs xser gc_load_utils needs $(GPIPE_COMMON_LIBS) +gc_load_utils needs gc_common gc_load_utils needs gc_organism gc_load_utils needs gc_utils gc_organism needs gpipe_attr @@ -329,10 +331,10 @@ gc_util_sdbapi needs gencoll_client gc_util_sdbapi needs gpipe_common gc_utils needs gpipe_objutil gcaccess_utils needs $(GPIPE_GENCOLL_LIBS) +gcaccess_utils needs simple_asm gcedit needs agp_lookup gcedit needs gc_load_utils gcrypt needs3party $(ORIG_LIBS) -gdsutil needs xncbi gencoll_client needs $(COMPRESS_LIBS) gencoll_client needs genome_collection gencoll_client needs xconnect @@ -344,7 +346,6 @@ gene_info needs xncbi gene_info_writer needs gene_info gene_info_writer needs seqdb genemark_proc needs bacterial_pipeline_proc -genemark_proc needs genomic_repeat_region general needs xser generic_db_asn needs xser generic_db_core needs $(CONNEXT) @@ -360,45 +361,22 @@ genome_collection needs pub genome_size needs $(COMPRESS_LIBS) genome_size needs xconnect genome_size needs xutil -genomic_repeat_region needs $(SOBJMGR_LIBS) gensvc_g needs xser -geoauth needs GMA -geobrowse needs xser -geocgi needs $(SDBAPI_LIB) -geocgi needs xcgi -geocgi needs xconnect -geocgi needs xmlwrapp -geocgi2 needs geomyncbi -geocgi2 needs xcgi geodataset needs biblio -geoindex needs $(COMPRESS_LIBS) -geoindex needs xmlwrapp -geoindex needs xutil -geometa needs GMA -geometa needs xmlwrapp -geometa needs xser -geomyncbi includes geoauth -geomyncbi needs connssl -geomyncbi needs xmlwrapp -geostat needs xncbi gif needs3party $(ORIG_LIBS) gif needs3party X11 gmap needs xmlwrapp -gmap needs xncbi gmp needs3party $(ORIG_LIBS) gnomon_access needs sqlitewrapp gnomon_access needs xalgognomon gnomon_access needs xqueryparse gnomon_asn_proc needs xobjutil -gnutls needs $(Z_LIB) gnutls needs3party $(GMP_LIBS) gnutls needs3party $(NETTLE_LIBS) gnutls needs3party $(ORIG_LIBS) -gnutls needs3party $(Z_LIBS) gpcgi needs $(SDBAPI_LIB) -gpcgi needs gpipe_xmlutil gpcgi needs xcgi -gpcgi needs xconnect +gpcgi needs xmlwrapp gpcgi needs xregexp gpexec_query needs gpipe_common gpexec_query needs monitor_buildrun @@ -408,15 +386,15 @@ gpinit needs entrez2cli gpinit needs gc_organism gpinit needs gpinit_access gpinit needs gpipe_objutil -gpinit_access needs gpipe_common +gpinit_access needs $(SDBAPI_LIB) +gpinit_access needs xconnect +gpinit_access needs xutil gpinit_bag_util needs bag_access gpinit_bag_util needs gpinit_access gpinit_obj needs general gpinit_register needs gc_organism -gpinit_register needs gpinit_access gpinit_reports needs xmlwrapp gpinit_reports needs xregexp -gpinit_stats_report needs gpipe_attr gpipe_align_format needs $(BLAST_FORMATTER_MINIMAL_LIBS) gpipe_align_format needs gpipe_objutil gpipe_align_format needs prosplign @@ -439,51 +417,51 @@ gpipe_attr needs gpipe_property gpipe_best_placement needs gpipe_alnutil gpipe_best_placement needs xalgoalignutil gpipe_blast needs $(BLAST_INPUT_LIBS) +gpipe_blast needs $(BLAST_LIBS) gpipe_blast needs gpipe_alnutil -gpipe_clean_prot_names needs $(SDBAPI_LIB) +gpipe_clean_prot_names needs gpipe_attr gpipe_clean_prot_names needs xdiscrepancy_report gpipe_common needs $(SDBAPI_LIB) gpipe_common needs eutils_client gpipe_common needs xcgi gpipe_common needs xregexp +gpipe_curl needs xncbi +gpipe_curl needs3party $(CURL_LIBS) gpipe_dateutil needs xregexp -gpipe_ftp needs gc_utils gpipe_ftp needs gcaccess_utils gpipe_ftp needs gpinit gpipe_ftp needs gpipe_alnutil gpipe_ftp needs xalgoalignutil gpipe_ftp needs xobjwrite gpipe_ftp needs xrepeatdb -gpipe_ftp_new needs $(GPIPE_COMMON_LIBS) -gpipe_ftp_new needs gc_utils gpipe_ftp_new needs gcaccess_utils gpipe_ftp_new needs gpinit gpipe_ftp_new needs gpipe_alnutil gpipe_ftp_new needs xalgoalignutil gpipe_ftp_new needs xobjwrite gpipe_ftp_new needs xrepeatdb -gpipe_jira needs connssl gpipe_jira needs gpinit_access gpipe_jira needs gpipe_attr -gpipe_jira needs3party $(CURL_LIBS) +gpipe_jira needs gpipe_curl gpipe_jira needs3party $(GSOAP_LIBS) gpipe_kmer needs gpipe_objutil gpipe_kmer needs sampling gpipe_kpi needs xmlwrapp -gpipe_kpi needs xncbi -gpipe_meta_access needs gpipe_common +gpipe_meta_access needs $(SDBAPI_LIB) +gpipe_meta_access needs xconnect +gpipe_meta_access needs xutil gpipe_object_edit needs xalgoalignutil -gpipe_objutil needs $(GPIPE_LOADER_LIBS) +gpipe_objutil needs $(DATA_LOADERS_UTIL_LIB) +gpipe_objutil needs $(DATA_LOADERS_UTIL_LIBS) gpipe_objutil needs $(OBJEDIT_LIBS) gpipe_objutil needs $(OBJMGR_LIBS) gpipe_objutil needs $(XFORMAT_LIBS) gpipe_objutil needs gpipe_attr gpipe_objutil needs taxon1 gpipe_objutil needs writedb -gpipe_objutil needs3party $(GPIPE_LOADER_THIRDPARTY_LIBS) +gpipe_objutil needs xalnmgr gpipe_objutil needs3party $(UUID_LIBS) -gpipe_prok_clean_prot_names needs gpipe_attr -gpipe_prok_clean_prot_names needs gpipe_clean_prot_names +gpipe_prodigal needs bacterial_pipeline_proc gpipe_property needs gpipe_common gpipe_remap needs xobjreadex gpipe_resource_req needs xncbi @@ -498,7 +476,9 @@ gpipe_sqlite needs sqlitewrapp gpipe_sqlite needs xconnect gpipe_sqlite needs xregexp gpipe_standalone needs gpipe_an_base -gpipe_tree needs gpipe_property +gpipe_teamcity needs gpipe_common +gpipe_teamcity needs gpipe_curl +gpipe_tree needs gpipe_common gpipe_tree needs xalgophytree gpipe_type_verifier needs gpipe_asn_cleanup gpipe_type_verifier needs xalgognomon @@ -508,12 +488,12 @@ gpipe_val needs pub gpipe_val needs valerr gpipe_val needs xmlwrapp gpipe_xml needs $(SEQ_LIBS) -gpipe_xml needs connssl gpipe_xml needs gpipe_attr gpipe_xml needs gpipe_dateutil gpipe_xml needs pub -gpipe_xmlutil needs xmlwrapp gpipe_xmlutil needs xutil +gpipe_xmlutil needs3party $(LIBXML_LIBS) +gpipe_xmlutil needs3party $(LIBXSLT_LIBS) gpxapi needs general gpxapi needs xconnect gpxlib needs $(COMPRESS_LIBS) @@ -554,10 +534,10 @@ gui_objutils needs eutils_client gui_objutils needs gbproj gui_objutils needs gencoll_client gui_objutils needs gui_utils -gui_objutils needs macro gui_objutils needs snputil gui_objutils needs xalgoalignutil gui_objutils needs xcgi +gui_objutils needs xdiscrepancy gui_objutils needs xobjwrite gui_objutils needs xvalidate gui_opengl needs gui_utils @@ -583,14 +563,15 @@ hgvs needs xregexp hgvs_name needs $(OBJMGR_LIBS) hgvs_name needs gui_objutils hgvs_name needs sv_objects -hmm_file needs xregexp -hmm_hit_handle needs xobjutil hogweed needs3party $(GMP_LIBS) hogweed needs3party $(ORIG_LIBS) homologene needs $(SEQ_LIBS) homologene needs pub -htbcli needs txserv -htbcon needs txserv +htbbase needs txxmldoc +htbcli includes htbcon +htbcon needs htbbase +htbcon needs txclient +hydra_client needs xmlwrapp icudata needs3party $(ORIG_LIBS) icui18n needs3party $(ORIG_LIBS) icuuc needs3party $(ORIG_LIBS) @@ -602,9 +583,6 @@ id2_split needs $(COMPRESS_LIBS) id2_split needs $(SOBJMGR_LIBS) id2cli needs id2 id2cli needs xconnect -id_dump needs bdb -id_dump needs cache_blob -id_dump needs seqset ideo needs xmvdatacache ideochr needs3party vibrant ideocli needs ideo @@ -615,33 +593,7 @@ idload needs3party ctutils idload_utils needs gpipe_common idload_utils needs xid_utils idload_utils needs xobjutil -idx needs $(CONNEXT) -idx needs dbapi_driver -idx needs spellsrvbase -idx needs xutil -idxgenome2 needs idxnucleotide2 -idxlinkout needs $(CONNEXT) -idxlinkout needs $(IDX_COMMON_LIB) -idxlinkout needs dbapi_driver -idxlinkout needs spellsrvbase -idxlinkout needs xutil -idxlinkout2 needs $(CONNEXT) -idxlinkout2 needs $(IDX_COMMON_LIB) -idxlinkout2 needs dbapi_driver -idxlinkout2 needs spellsrvbase -idxlinkout2 needs txxmldoc -idxnucleotide2 needs idxseq2base -idxpopset2 needs idxseq2base -idxprotein2 needs idxseq2base -idxseq2base needs $(IDX_COMMON_LIB) -idxseq2base needs spellsrvbase -idxseq2base needs xid_utils -idxumbrella needs idxnucleotide2 igblast needs $(BLAST_LIBS) -ilink needs $(CONNEXT) -ilink needs dbapi_driver -ilink needs spellsrvbase -ilink needs xutil insdseq needs xser jiracli needs jirasvc jiracli needs xconnect @@ -656,6 +608,9 @@ krb5 needs3party $(NETWORK_LIBS) krb5 needs3party $(ORIG_LIBS) krb5 needs3party com_err krb5 needs3party k5crypto +lapack needs3party $(ORIG_LIBS) +lapackwrapp needs3party $(LAPACK_LIBS) +lapackwrapp needs3party $(ORIG_LIBS) lbsmdapi needs connect lds2 needs $(COMPRESS_LIBS) lds2 needs $(OBJREAD_LIBS) @@ -763,12 +718,12 @@ ncbi_xdbapi_dblib needs3party $(SYBASE_LIBS) ncbi_xdbapi_ftds needs $(FTDS_LIB) ncbi_xdbapi_ftds needs dbapi_driver ncbi_xdbapi_ftds needs3party $(FTDS_LIBS) -ncbi_xdbapi_ftds64 needs $(FTDS_LIB) +ncbi_xdbapi_ftds64 needs $(FTDS64_LIB) ncbi_xdbapi_ftds64 needs dbapi_driver -ncbi_xdbapi_ftds64 needs3party $(FTDS_LIBS) -ncbi_xdbapi_ftds95 needs $(FTDS95_LIB) +ncbi_xdbapi_ftds64 needs3party $(FTDS64_LIBS) +ncbi_xdbapi_ftds95 needs $(FTDS_LIB) ncbi_xdbapi_ftds95 needs dbapi_driver -ncbi_xdbapi_ftds95 needs3party $(FTDS95_LIBS) +ncbi_xdbapi_ftds95 needs3party $(FTDS_LIBS) ncbi_xdbapi_mysql needs dbapi_driver ncbi_xdbapi_mysql needs3party $(MYSQL_LIBS) ncbi_xdbapi_mysql needs3party $(NETWORK_LIBS) @@ -780,8 +735,6 @@ ncbi_xloader_bam needs xobjreadex ncbi_xloader_blastdb needs seqdb ncbi_xloader_blastdb_rmt needs blast_services ncbi_xloader_blastdb_rmt needs ncbi_xloader_blastdb -ncbi_xloader_cdd needs $(SOBJMGR_LIBS) -ncbi_xloader_cdd needs xconnect ncbi_xloader_csra needs $(SOBJMGR_LIBS) ncbi_xloader_csra needs $(SRAREAD_LIBS) ncbi_xloader_genbank needs ncbi_xreader_cache @@ -790,10 +743,10 @@ ncbi_xloader_genbank needs ncbi_xreader_id2 ncbi_xloader_lds2 needs $(SOBJMGR_LIBS) ncbi_xloader_lds2 needs lds2 ncbi_xloader_patcher needs $(SOBJMGR_LIBS) +ncbi_xloader_snp needs $(SOBJMGR_LIBS) +ncbi_xloader_snp needs $(SRAREAD_LIBS) ncbi_xloader_sra needs $(SOBJMGR_LIBS) ncbi_xloader_sra needs $(SRAREAD_LIBS) -ncbi_xloader_trace needs $(SOBJMGR_LIBS) -ncbi_xloader_trace needs id1cli ncbi_xloader_vdbgraph needs $(SOBJMGR_LIBS) ncbi_xloader_vdbgraph needs $(SRAREAD_LIBS) ncbi_xloader_wgs needs $(SOBJMGR_LIBS) @@ -872,7 +825,6 @@ netblast needs3party netcli netcli needs3party $(NCBI_C_ncbi) netentr needs3party ncbiacc netentr needs3party netcli -netstorage needs connssl netstorage needs ncbi_xcache_netcache nettle needs3party $(ORIG_LIBS) nlmzip needs3party $(NCBI_C_ncbi) @@ -890,16 +842,12 @@ osutils needs3party ctutils pathogen_cluster_loader needs $(SDBAPI_LIB) pathogen_cluster_loader needs xasmcompare pathogen_cluster_loader needs xconnect -pathogen_cluster_loader needs xutil -pathogen_connection needs connssl pathogen_connection needs gpipe_common pathogen_connection needs gpipe_dateutil pathogen_ctl needs $(GPIPE_COMMON_LIBS) -pathogen_ctl needs $(SRAREAD_LIBS) pathogen_ctl needs bag_access -pathogen_ctl needs gencoll_client +pathogen_ctl needs gpipe_kmer pathogen_ctl needs pathogen_connection -pathogen_ctl needs taxon1 pathogen_ctl needs xvalidate pathogen_fill_taxa needs gpipe_common pathogen_target_loader needs gpinit_register @@ -912,27 +860,29 @@ pepXML needs xser phytree_format needs taxon1 phytree_format needs xalgophytree pn_ctl needs $(GPIPE_GENCOLL_LIBS) -pn_ctl needs gpipe_prok_clean_prot_names -pn_ctl needs hmm_file -pn_ctl needs hmm_hit_handle +pn_ctl needs bacterial_pipeline_proc +pn_ctl needs ec_hmm_relation_cd +pn_ctl needs gpipe_clean_prot_names +pn_ctl needs gpipe_jira pn_ctl needs idload_utils -pn_ctl needs third_party +pn_ctl needs simple_asm png needs $(Z_LIB) png needs3party $(ORIG_LIBS) png needs3party $(Z_LIBS) +process_annotation_stats needs xser proj needs pubmed proj needs seqset -prok_align_monomer needs $(SOBJMGR_LIBS) -prok_align_monomer needs align_part_ci prosplign needs xalgoalignutil proxsort needs taxoscli pstub needs3party $(ORIG_LIBS) pub needs medline pubmed needs medline -python2.5 needs3party $(ORIG_LIBS) -python_ncbi_dbapi needs connect +python2.7 needs3party $(ORIG_LIBS) +python_ncbi_dbapi needs $(Z_LIB) +python_ncbi_dbapi needs connssl python_ncbi_dbapi needs dbapi python_ncbi_dbapi needs3party $(PYTHON_LIBS) +python_ncbi_dbapi needs3party $(Z_LIBS) rcobaltasn_g needs xser refseq_aln_source needs $(COMPRESS_LIBS) refseq_aln_source needs dbapi @@ -941,9 +891,14 @@ refseq_aln_source needs xalgoalignsplign refseq_ctl needs bacterial_pipeline_proc refseq_ctl needs bag_access refseq_ctl needs gpinit_access +refseq_ctl needs process_annotation_stats refseq_ctl needs xid_utils -reftrack_access needs gpipe_common -reftrack_admin needs reftrack_access +reftrack_access needs $(SDBAPI_LIB) +reftrack_access needs xconnect +reftrack_access needs xutil +reftrack_admin needs $(SDBAPI_LIB) +reftrack_admin needs xconnect +reftrack_admin needs xutil remap needs $(SEQ_LIBS) remap needs pub remapcli needs remap @@ -956,9 +911,10 @@ scoremat needs seqset sdbapi needs $(XCONNEXT) sdbapi needs dbapi sdbapi needs ncbi_xdbapi_ftds +sdbapi needs ncbi_xdbapi_ftds64 +sdbapi needs ncbi_xdbapi_ftds95 sdbapi needs xconnect sdbapi needs xutil -sdncbiauth needs auxcomm_g sdncbiauth needs generic_db_core sdncbiauth needs muxex_g sdncbiauth needs xmyncbi @@ -971,6 +927,7 @@ seqcode needs xser seqdb needs $(SOBJMGR_LIBS) seqdb needs blastdb seqedit needs seqset +seqentry_comparator needs xobjwrite seqgapscan needs $(SDBAPI_LIB) seqgapscan needs xconnect seqgapscan needs xobjutil @@ -983,21 +940,21 @@ seqsplit needs seqset seqtest needs $(SEQ_LIBS) seqtest needs pub sequtil needs xncbi +simple_asm needs gc_load_utils smartasn_g needs submit smartnet needs3party vibrant smartnetclient needs xconnect -snphgvs needs $(GPIPE_LOADER_LIBS) -snphgvs needs $(SDBAPI_LIB) -snphgvs needs hgvs -snphgvs needs ncbi_xcache_netcache -snphgvs needs refseq_aln_source -snphgvs needs3party $(GPIPE_LOADER_THIRDPARTY_LIBS) snputil needs $(SOBJMGR_LIBS) snputil needs variation soap_dataobj needs xser -spcgi needs geomyncbi +softparse needs $(COMPRESS_LIBS) +softparse needs affy +softparse needs taxon1 +softparse needs xmlwrapp +spcgi needs $(CONNEXT) +spcgi needs softparse spcgi needs xgridcgi -spellsrvbase needs txservbase +spellsrvbase needs txserv splitdbasn_g needs gendefasn_g splitdbasn_g needs3party ncbiobj splitdbasncpp_g needs asngendefs @@ -1006,13 +963,7 @@ sqlite3 needs3party $(ORIG_LIBS) sqlitewrapp needs xncbi sqlitewrapp needs3party $(SQLITE3_LIBS) sraread needs $(SOBJMGR_LIBS) -sraread needs $(VDB_LIB) sraread needs3party $(VDB_LIBS) -srprism needs srprism_seq -srprism_common needs $(COMPRESS_LIBS) -srprism_common needs xutil -srprism_seq needs srprism_common -srprism_setup needs xncbi ssl needs $(Z_LIB) ssl needs3party $(KRB5_LIBS) ssl needs3party $(NETWORK_LIBS) @@ -1067,8 +1018,8 @@ sybtcl64 needs3party sybintl64 sybtcl64 needs3party sybunic64 sybunic64 needs3party $(ORIG_LIBS) tables needs3party $(ORIG_LIBS) -tax_assignment_region needs gpipe_objutil -tax_xml needs gpipe_objutil +tax_xml needs $(GPIPE_GENCOLL_LIBS) +tax_xml needs simple_asm taxon needs xser taxon1 needs $(SEQ_LIBS) taxon1 needs pub @@ -1098,8 +1049,6 @@ test_stat_ext needs dbapi test_stat_ext needs ncbi_xdbapi_ftds test_stat_ext needs xconnect test_stat_ext needs xutil -third_party needs xmlwrapp -third_party needs xregexp tiff needs $(Z_LIB) tiff needs3party $(JPEG_LIBS) tiff needs3party $(ORIG_LIBS) @@ -1111,6 +1060,11 @@ tiol needs3party $(Z_LIBS) tracking_utils needs gpipe_attr trackmgr needs $(SEQ_LIBS) trackmgr needs pub +trackmgr_objtools needs $(OBJMGR_LIBS) +trackmgr_objtools needs gencoll_client +trackmgr_objtools needs trackmgrgridcli +trackmgr_objtools needs uudutil +trackmgr_objtools needs xid_mapper trackmgrcli needs trackmgr trackmgrcli needs xconnect trackmgrgridcli needs $(COMPRESS_LIBS) @@ -1123,18 +1077,15 @@ tvlib needs tv_objects tvlib needs uudutil tvlib needs w_phylo_tree txclient needs xconnect -txserv includes txservbase -txserv needs txxmldoc +txserv needs xmlwrapp +txserv needs3party $(RT_LIBS) txserv14 needs txxmldoc txserv14 needs xconnect txserv14 needs3party $(RT_LIBS) -txservbase needs xconnect -txservbase needs3party $(RT_LIBS) txxmldoc needs $(COMPRESS_LIBS) txxmldoc needs xutil txxmldoc needs3party $(LIBXML_LIBS) txxmldoc needs3party $(LIBXSLT_LIBS) -txxmltrans needs3party $(ORIG_LIBS) u2tl needs $(Z_LIB) u2tl needs3party $(NETWORK_LIBS) u2tl needs3party $(ORIG_LIBS) @@ -1144,6 +1095,8 @@ u2tl needs3party $(SYBASE_LIBS) u2tl needs3party $(Z_LIBS) uilist needs xser unicoll_dump_access needs gpipe_sqlite +univ_prot_access needs gpipe_common +univ_prot_access needs xser uudutil needs $(COMPRESS_LIBS) uudutil needs gbproj uudutil needs xconnserv @@ -1152,12 +1105,13 @@ valerr needs xser valid needs general valid needs xregexp validate_regions needs $(GPIPE_GENCOLL_LIBS) +validate_regions needs simple_asm variation needs $(SEQ_LIBS) variation needs pub variation_utils needs variation variation_utils needs xobjutil +varrep needs xser vdb2blast needs $(BLAST_LIBS) -vdb2blast needs $(VDB_LIB) vdb2blast needs3party $(VDB_LIBS) vibgif needs3party $(NCBI_C_ncbi) vibnet needs3party ncbiacc @@ -1171,15 +1125,15 @@ vibrantOGL includes3party vibrant vibrantOGL needs3party $(OPENGL_LIBS) vibrantOGL needs3party ncbiobj w_aln_crossaln needs w_hit_matrix -w_aln_multi needs w_aln_score -w_aln_multi needs w_data -w_aln_multi needs w_gl +w_aln_multi needs w_seq_graphic w_aln_score needs w_wx w_aln_table needs w_wx w_data needs w_wx w_edit needs align_format +w_edit needs hydra_client w_edit needs prosplign w_edit needs w_loaders +w_edit needs w_seq w_feat_table needs w_wx w_gl needs w_wx w_grid_widget needs w_data @@ -1207,6 +1161,7 @@ w_seq_graphic needs gui_graph w_seq_graphic needs gui_objects w_seq_graphic needs hgvs w_seq_graphic needs ncbi_xcache_netcache +w_seq_graphic needs trackmgr w_seq_graphic needs w_aln_score w_seq_graphic needs w_gl w_seq_graphic needs w_seq @@ -1229,54 +1184,54 @@ w_wx needs3party $(WXWIDGETS_LIBS) we_cpp needs xser writedb needs $(OBJREAD_LIBS) writedb needs seqdb -wx_base-2.9 needs $(Z_LIB) -wx_base-2.9 needs3party $(ORIG_LIBS) -wx_base-2.9 needs3party $(Z_LIBS) -wx_base_net-2.9 needs $(Z_LIB) -wx_base_net-2.9 needs3party $(ORIG_LIBS) -wx_base_net-2.9 needs3party $(Z_LIBS) -wx_base_xml-2.9 needs $(Z_LIB) -wx_base_xml-2.9 needs3party $(EXPAT_LIBS) -wx_base_xml-2.9 needs3party $(ORIG_LIBS) -wx_base_xml-2.9 needs3party $(Z_LIBS) -wx_gtk2_adv-2.9 needs3party $(ORIG_LIBS) -wx_gtk2_adv-2.9 needs3party $(PNG_LIBS) -wx_gtk2_adv-2.9 needs3party $(TIFF_LIBS) -wx_gtk2_adv-2.9 needs3party X11 -wx_gtk2_aui-2.9 needs3party $(ORIG_LIBS) -wx_gtk2_aui-2.9 needs3party $(PNG_LIBS) -wx_gtk2_aui-2.9 needs3party $(TIFF_LIBS) -wx_gtk2_aui-2.9 needs3party X11 -wx_gtk2_core-2.9 needs3party $(ORIG_LIBS) -wx_gtk2_core-2.9 needs3party $(PNG_LIBS) -wx_gtk2_core-2.9 needs3party $(TIFF_LIBS) -wx_gtk2_core-2.9 needs3party X11 -wx_gtk2_gl-2.9 needs3party $(OPENGL_LIBS) -wx_gtk2_gl-2.9 needs3party $(ORIG_LIBS) -wx_gtk2_gl-2.9 needs3party $(WXWIDGETS_LIBS) -wx_gtk2_html-2.9 needs3party $(ORIG_LIBS) -wx_gtk2_html-2.9 needs3party $(PNG_LIBS) -wx_gtk2_html-2.9 needs3party $(TIFF_LIBS) -wx_gtk2_html-2.9 needs3party X11 -wx_gtk2_propgrid-2.9 needs3party $(ORIG_LIBS) -wx_gtk2_propgrid-2.9 needs3party $(PNG_LIBS) -wx_gtk2_propgrid-2.9 needs3party $(TIFF_LIBS) -wx_gtk2_propgrid-2.9 needs3party X11 -wx_gtk2_qa-2.9 needs3party $(EXPAT_LIBS) -wx_gtk2_qa-2.9 needs3party $(ORIG_LIBS) -wx_gtk2_qa-2.9 needs3party $(PNG_LIBS) -wx_gtk2_qa-2.9 needs3party $(TIFF_LIBS) -wx_gtk2_qa-2.9 needs3party X11 -wx_gtk2_richtext-2.9 needs3party $(EXPAT_LIBS) -wx_gtk2_richtext-2.9 needs3party $(ORIG_LIBS) -wx_gtk2_richtext-2.9 needs3party $(PNG_LIBS) -wx_gtk2_richtext-2.9 needs3party $(TIFF_LIBS) -wx_gtk2_richtext-2.9 needs3party X11 -wx_gtk2_xrc-2.9 needs3party $(EXPAT_LIBS) -wx_gtk2_xrc-2.9 needs3party $(ORIG_LIBS) -wx_gtk2_xrc-2.9 needs3party $(PNG_LIBS) -wx_gtk2_xrc-2.9 needs3party $(TIFF_LIBS) -wx_gtk2_xrc-2.9 needs3party X11 +wx_base-3.0 needs $(Z_LIB) +wx_base-3.0 needs3party $(ORIG_LIBS) +wx_base-3.0 needs3party $(Z_LIBS) +wx_base_net-3.0 needs $(Z_LIB) +wx_base_net-3.0 needs3party $(ORIG_LIBS) +wx_base_net-3.0 needs3party $(Z_LIBS) +wx_base_xml-3.0 needs $(Z_LIB) +wx_base_xml-3.0 needs3party $(EXPAT_LIBS) +wx_base_xml-3.0 needs3party $(ORIG_LIBS) +wx_base_xml-3.0 needs3party $(Z_LIBS) +wx_gtk2_adv-3.0 needs3party $(ORIG_LIBS) +wx_gtk2_adv-3.0 needs3party $(PNG_LIBS) +wx_gtk2_adv-3.0 needs3party $(TIFF_LIBS) +wx_gtk2_adv-3.0 needs3party X11 +wx_gtk2_aui-3.0 needs3party $(ORIG_LIBS) +wx_gtk2_aui-3.0 needs3party $(PNG_LIBS) +wx_gtk2_aui-3.0 needs3party $(TIFF_LIBS) +wx_gtk2_aui-3.0 needs3party X11 +wx_gtk2_core-3.0 needs3party $(ORIG_LIBS) +wx_gtk2_core-3.0 needs3party $(PNG_LIBS) +wx_gtk2_core-3.0 needs3party $(TIFF_LIBS) +wx_gtk2_core-3.0 needs3party X11 +wx_gtk2_gl-3.0 needs3party $(OPENGL_LIBS) +wx_gtk2_gl-3.0 needs3party $(ORIG_LIBS) +wx_gtk2_gl-3.0 needs3party $(WXWIDGETS_LIBS) +wx_gtk2_html-3.0 needs3party $(ORIG_LIBS) +wx_gtk2_html-3.0 needs3party $(PNG_LIBS) +wx_gtk2_html-3.0 needs3party $(TIFF_LIBS) +wx_gtk2_html-3.0 needs3party X11 +wx_gtk2_propgrid-3.0 needs3party $(ORIG_LIBS) +wx_gtk2_propgrid-3.0 needs3party $(PNG_LIBS) +wx_gtk2_propgrid-3.0 needs3party $(TIFF_LIBS) +wx_gtk2_propgrid-3.0 needs3party X11 +wx_gtk2_qa-3.0 needs3party $(EXPAT_LIBS) +wx_gtk2_qa-3.0 needs3party $(ORIG_LIBS) +wx_gtk2_qa-3.0 needs3party $(PNG_LIBS) +wx_gtk2_qa-3.0 needs3party $(TIFF_LIBS) +wx_gtk2_qa-3.0 needs3party X11 +wx_gtk2_richtext-3.0 needs3party $(EXPAT_LIBS) +wx_gtk2_richtext-3.0 needs3party $(ORIG_LIBS) +wx_gtk2_richtext-3.0 needs3party $(PNG_LIBS) +wx_gtk2_richtext-3.0 needs3party $(TIFF_LIBS) +wx_gtk2_richtext-3.0 needs3party X11 +wx_gtk2_xrc-3.0 needs3party $(EXPAT_LIBS) +wx_gtk2_xrc-3.0 needs3party $(ORIG_LIBS) +wx_gtk2_xrc-3.0 needs3party $(PNG_LIBS) +wx_gtk2_xrc-3.0 needs3party $(TIFF_LIBS) +wx_gtk2_xrc-3.0 needs3party X11 wx_tools needs xncbi wx_tools needs3party $(WXWIDGETS_LIBS) xalan-c needs3party $(CURL_LIBS) @@ -1322,7 +1277,8 @@ xalnmgr needs xobjutil xalntool needs xhtml xalntool needs xobjutil xannot_builder needs gpipe_asn_proc -xasmcompare needs xncbi +xasmcompare needs $(SEQ_LIBS) +xasmcompare needs pub xasn needs xhtml xasn needs3party $(NCBI_C_ncbi) xassembly_svc needs gcaccess_utils @@ -1361,7 +1317,7 @@ xcleanup needs xobjutil xcompress needs $(CMPRS_LIB) xcompress needs xutil xcompress needs3party $(CMPRS_LIBS) -xconnect includes connect +xconnect includes connssl xconnect needs xncbi xconnext includes $(CONNEXT) xconnext needs xconnect @@ -1372,8 +1328,10 @@ xctools needs xncbi xctools needs3party $(NCBI_C_ncbi) xdb needs xncbi xdiff needs xncbi +xdiscrepancy needs $(OBJEDIT_LIBS) +xdiscrepancy needs $(XFORMAT_LIBS) xdiscrepancy needs macro -xdiscrepancy needs xvalidate +xdiscrepancy needs xalnmgr xdiscrepancy_report needs $(OBJMGR_LIBS) xdiscrepancy_report needs macro xdiscrepancy_report needs xmlwrapp @@ -1386,28 +1344,17 @@ xformat needs gbseq xformat needs mlacli xformat needs xalnmgr xformat needs xcleanup -xgdsapi needs $(CONNEXT) -xgdsapi needs connect -xgdsapi needs dbapi -xgdsapi needs ncbi_xdbapi_ftds -xgdsdata needs $(CONNEXT) -xgdsdata needs $(EUTILS_LIBS) -xgdsdata needs $(SEQ_LIBS) -xgdsdata needs dbapi -xgdsdata needs geodataset -xgdsdata needs ncbi_xdbapi_ftds -xgdsdata needs pub -xgdsdata needs txxmldoc -xgdsdata needs xconnect -xgdsdata_misc needs xncbi xgencoll needs aligndb_reader xgencoll needs gencoll_client -xgencoll needs gpipe_objutil +xgencoll needs ncbi_xcache_netcache +xgencoll needs simple_asm xgencollstats needs $(GPIPE_GENCOLL_LIBS) xgencollstats needs gencoll_stats +xgencollstats needs simple_asm xgp_manifest needs xser xgpgcreport needs $(GPIPE_GENCOLL_LIBS) xgpgcreport needs gencoll_release_report +xgpgcreport needs simple_asm xgpp_console needs dbapi xgpp_console_access needs xgpp_console_commands xgpp_console_commands needs gpipe_common @@ -1416,8 +1363,9 @@ xgpsubmit needs gc_load_utils xgpsubmit needs gpinit_access xgpsubmit needs gpipe_asn_cleanup xgpsubmit needs grid_wrapper +xgpsubmit needs idload_utils +xgpsubmit needs seqgapscan xgpsubmit needs xasmcompare -xgpsubmit needs xid_utils xgraphiccgi needs gui_glmesa xgraphiccgi needs gui_opengl xgraphiccgi needs xsvcgi @@ -1431,24 +1379,23 @@ xid_estsub needs xregexp xid_mapper needs $(SOBJMGR_LIBS) xid_utils needs $(CONNEXT) xid_utils needs $(SEQ_LIBS) -xid_utils needs connssl xid_utils needs dbapi_driver xid_utils needs pub xid_utils needs xcgi -xid_utils needs xconnect xid_utils needs xmlwrapp xid_utils_noncorelib needs txclient xid_utils_noncorelib needs xid_utils +xid_wgs needs xncbi +xid_wgs needs3party $(VDB_LIBS) xid_wgsdb needs xid_utils ximage needs xncbi ximage needs3party $(IMAGE_LIBS) xmergetree needs $(SOBJMGR_LIBS) xml2 needs3party $(ORIG_LIBS) xmlreaders needs xmlwrapp -xmlreaders needs xncbi +xmlwrapp needs xconnect xmlwrapp needs3party $(LIBXML_LIBS) xmlwrapp needs3party $(LIBXSLT_LIBS) -xmlwrapp needs3party $(ORIG_LIBS) xmvdatacache needs mapview xmyncbi needs txclient xmyncbi needs txxmldoc @@ -1477,6 +1424,7 @@ xobjreadex needs xobjutil xobjsimple needs $(OBJMGR_LIBS) xobjutil needs $(SOBJMGR_LIBS) xobjwrite needs $(OBJREAD_LIBS) +xobjwrite needs $(XFORMAT_LIBS) xobjwrite needs variation_utils xobjwrite needs xalnmgr xomssa needs $(COMPRESS_LIBS) @@ -1519,11 +1467,14 @@ xstruct_dp needs xncbi xstruct_thread needs xutil xstruct_util needs $(BLAST_LIBS) xstruct_util needs xstruct_dp +xsubmit2id needs sqlitewrapp +xsubmit2id needs xid_utils xsvcgi needs $(DBAPI_CTLIB) xsvcgi needs $(OBJMGR_LIBS) xsvcgi needs $(ncbi_xreader_pubseqos2) -xsvcgi needs gui_objutils +xsvcgi needs gui_objects xsvcgi needs ncbi_xcache_netcache +xsvcgi needs ncbi_xloader_bam xsvcgi needs ncbi_xloader_csra xsvcgi needs ncbi_xloader_vdbgraph xsvcgi needs ncbi_xloader_wgs @@ -1531,18 +1482,11 @@ xsvcgi needs uudutil xsvcgi needs3party $(SYBASE_DLLS) xsvcgi needs3party $(SYBASE_LIBS) xsvdata needs $(BLAST_INPUT_LIBS) -xsvdata needs $(DBAPI_CTLIB) -xsvdata needs $(ncbi_xreader_pubseqos2) -xsvdata needs gui_objects xsvdata needs hgvs -xsvdata needs ncbi_xcache_netcache xsvdata needs sv_objects xsvdata needs trackmgr -xsvdata needs uudutil xsvdata needs xalgophytree -xsvdata needs xobjreadex -xsvdata needs3party $(SYBASE_DLLS) -xsvdata needs3party $(SYBASE_LIBS) +xsvdata needs xsvcgi xsvlink needs gui_objutils xsvlink needs sv_objects xsvnaa needs xutil @@ -1557,6 +1501,7 @@ xvalidate needs $(OBJEDIT_LIBS) xvalidate needs $(XFORMAT_LIBS) xvalidate needs valerr xvalidate needs xalnmgr +xxconnect includes connssl xxconnect needs xncbi xxconnect needs3party $(NCBI_C_ncbi) z needs3party $(ORIG_LIBS) diff --git a/c++/src/build-system/ncbi_package_version b/c++/src/build-system/ncbi_package_version index 9183195a..914ec967 100644 --- a/c++/src/build-system/ncbi_package_version +++ b/c++/src/build-system/ncbi_package_version @@ -1 +1 @@ -2.4.0 \ No newline at end of file +2.6.0 \ No newline at end of file diff --git a/c++/src/build-system/project_tree_builder.ini b/c++/src/build-system/project_tree_builder.ini index 00770050..bf6c052f 100644 --- a/c++/src/build-system/project_tree_builder.ini +++ b/c++/src/build-system/project_tree_builder.ini @@ -1,4 +1,4 @@ -# $Id: project_tree_builder.ini 498370 2016-04-15 17:19:18Z ivanov $ +# $Id: project_tree_builder.ini 520070 2016-11-22 14:36:17Z ivanov $ ############################################################################### @@ -68,7 +68,12 @@ NotProvidedRequests = unix \ # Whether the following requirements are met or not is up to user # One must use GUI tool to enable them -UserRequests = Ncbi-JNI Ncbi-Unicode +UserRequests = Ncbi-int8-gi Ncbi-JNI Ncbi-Unicode + +#---------------------------------------------------------------------------- +# This file will be generated during the configuration process +ExtraDefines = ncbi_random_macro.h +RandomValueCount = 10 #---------------------------------------------------------------------------- # This file will be generated during the configuration process @@ -93,6 +98,7 @@ Defines = HAVE_BERKELEY_DB \ HAVE_LIBGNUTLS \ HAVE_LIBJPEG \ HAVE_LIBLZO \ + HAVE_LIBLMDB \ HAVE_LIBMIMETIC \ HAVE_LIBMUPARSER \ HAVE_LIBOPENSSL \ @@ -105,6 +111,7 @@ Defines = HAVE_BERKELEY_DB \ HAVE_LIBEXSLT \ HAVE_LIBMONGODB \ HAVE_LOCAL_LBSM \ + HAVE_NCBI_VDB \ HAVE_ODBC \ HAVE_ODBCSS_H \ HAVE_OPENGL \ @@ -118,7 +125,8 @@ Defines = HAVE_BERKELEY_DB \ USE_LOCAL_PCRE \ HAVE_SQLITE3ASYNC_H \ HAVE_SQLITE3_UNLOCK_NOTIFY \ - NCBI_JNI + NCBI_JNI \ + NCBI_INT8_GI #---------------------------------------------------------------------------- @@ -128,7 +136,10 @@ Defines = HAVE_BERKELEY_DB \ Macros = BDB_LIB BDB_CACHE_LIB NCBI_CRYPT CONNEXT XCONNEXT \ ncbi_xreader_pubseqos ncbi_xreader_pubseqos2 UNLESS_PUBSEQOS \ FASTCGI_OBJS DBAPI_DRIVER DBAPI_CTLIB DBAPI_DBLIB \ - DBAPI_ODBC LOCAL_LBSM ncbi_java VDB_REQ + DBAPI_ODBC LOCAL_LBSM ncbi_java VDB_REQ bamread sraread \ + ncbi_id2proc_snp ncbi_id2proc_wgs ncbi_xloader_bam \ + ncbi_xloader_csra ncbi_xloader_snp ncbi_xloader_sra \ + ncbi_xloader_vdbgraph ncbi_xloader_wgs #---------------------------------------------------------------------------- # Some 3rd party libraries have analog in the toolkit. @@ -183,10 +194,11 @@ ThirdParty_FreeType = $(ThirdPartyBasePath)\\freetype\\$(msvc_3rd)\\2.4.10 ThirdParty_FTGL = $(ThirdPartyBasePath)\\ftgl\\$(msvc_3rd)\\2.1.3-rc5 ThirdParty_GIF = $(ThirdPartyBasePath)\\gif\\$(msvc_3rd)\\4.1.3 ThirdParty_GLEW = $(ThirdPartyBasePath)\\glew\\$(msvc_3rd)\\1.5.8 -ThirdParty_GNUTLS = $(ThirdPartyBasePath)\\gnutls\\$(msvc_3rd)\\3.1.6 +ThirdParty_GNUTLS = $(ThirdPartyBasePath)\\gnutls\\$(msvc_3rd)\\3.4.9 ThirdParty_ICU = $(ThirdPartyBasePath)\\icu\\$(msvc_3rd)\\3.2 ThirdParty_JPEG = $(ThirdPartyBasePath)\\jpeg\\$(msvc_3rd)\\6b ThirdParty_LZO = $(ThirdPartyBasePath)\\lzo\\$(msvc_3rd)\\2.05 +ThirdParty_LMDB = $(ThirdPartyBasePath)\\lmdb\\$(msvc_3rd)\\0.9.18 ThirdParty_Mimetic = $(ThirdPartyBasePath)\\mimetic\\$(msvc_3rd)\\0.9.7 ThirdParty_MongoDB = $(ThirdPartyBasePath)\\mongodb\\$(msvc_3rd)\\legacy_1.0.0-rc0 ThirdParty_MSSQL = $(ThirdPartyBasePath)\\MSSQL\\$(msvc_3rd)\\8.0.1.94 @@ -197,14 +209,14 @@ ThirdParty_PNG = $(ThirdPartyBasePath)\\png\\$(msvc_3rd)\\1.2.7 ThirdParty_SQLITE3 = $(ThirdPartyBasePath)\\sqlite\\$(msvc_3rd)\\3.6.14.2 ThirdParty_Sybase = $(ThirdPartyBasePath)\\sybase\\$(msvc_3rd)\\15.5 ThirdParty_TIFF = $(ThirdPartyBasePath)\\tiff\\$(msvc_3rd)\\3.6.1 -ThirdParty_wxWidgets = $(ThirdPartyBasePath)\\wxwidgets\\$(msvc_3rd)\\3.0.1 +ThirdParty_wxWidgets = $(ThirdPartyBasePath)\\wxwidgets\\$(msvc_3rd)\\3.1.0_no28 ThirdParty_Xalan = $(ThirdPartyBasePath)\\xalan\\$(msvc_3rd)\\1.10.0-20080814 ThirdParty_Xerces = $(ThirdPartyBasePath)\\xerces\\$(msvc_3rd)\\2.8.0 ThirdParty_XML = $(ThirdPartyBasePath)\\xml\\$(msvc_3rd)\\2.7.8 ThirdParty_XSLT = $(ThirdPartyBasePath)\\xslt\\$(msvc_3rd)\\1.1.26 ThirdParty_Z = $(ThirdPartyBasePath)\\z\\$(msvc_3rd)\\1.2.8 ThirdParty_JDK = $(ThirdPartyBasePath)\\jdk\\1.6.0_25 -ThirdParty_VDB = $(ThirdPartyVDBBasePath)\\vdb\\vdb-versions\\2.6.1 +ThirdParty_VDB = $(ThirdPartyVDBBasePath)\\vdb\\vdb-versions\\2.8.0 PYTHON_PATH = $(ThirdPartyAppsBasePath)\\Python252\\$(msvc_3rd) @@ -275,6 +287,7 @@ msvc_prj = msvc900_prj # Macro msvc_3rd = msvc9 vdb_arch = i386 +vdb_arch_inc = i386 #---------------------------------------------------------------------------- # Settings for MSVC 2008 (v.9.00, x64) @@ -290,6 +303,7 @@ msvc_prj = msvc900_prj # Macro msvc_3rd = msvc9.64 vdb_arch = x86_64 +vdb_arch_inc = x86_64 #---------------------------------------------------------------------------- # Settings for MSVC 2010 (v.10.00, Win32) @@ -305,6 +319,7 @@ msvc_prj = msvc1000_prj # Macro msvc_3rd = msvc10 vdb_arch = i386 +vdb_arch_inc = i386 #---------------------------------------------------------------------------- # Settings for MSVC 2010 (v.10.00, x64) @@ -320,6 +335,7 @@ msvc_prj = msvc1000_prj # Macro msvc_3rd = msvc10.64 vdb_arch = x86_64 +vdb_arch_inc = x86_64 #---------------------------------------------------------------------------- # Settings for MSVC 2012 (v.11, Win32) @@ -335,6 +351,7 @@ msvc_prj = vs2012 # Macro msvc_3rd = vs2012 vdb_arch = i386 +vdb_arch_inc = i386 #---------------------------------------------------------------------------- @@ -351,6 +368,7 @@ msvc_prj = vs2012 # Macro msvc_3rd = vs2012.64 vdb_arch = x86_64 +vdb_arch_inc = x86_64 #---------------------------------------------------------------------------- @@ -367,6 +385,7 @@ msvc_prj = vs2013 # Macro msvc_3rd = vs2013 vdb_arch = i386/vs2013.32 +vdb_arch_inc = i386 #---------------------------------------------------------------------------- @@ -383,6 +402,7 @@ msvc_prj = vs2013 # Macro msvc_3rd = vs2013.64 vdb_arch = x86_64/vs2013.64 +vdb_arch_inc = x86_64 #---------------------------------------------------------------------------- @@ -399,6 +419,7 @@ msvc_prj = vs2015 # Macro msvc_3rd = vs2015 vdb_arch = i386/vs2013.32 +vdb_arch_inc = i386 #---------------------------------------------------------------------------- @@ -415,6 +436,7 @@ msvc_prj = vs2015 # Macro msvc_3rd = vs2015.64 vdb_arch = x86_64/vs2013.64 +vdb_arch_inc = x86_64 #============================================================================ @@ -447,7 +469,7 @@ Projects = build # XCODE specific metadata # It describes default settings of compiler, linker etc MetaMakefile = build-system/Makefile.mk.in.xcode -StandardFeatures = unix Darwin XCODE GCC LFS DBLib algo app dbapi gui objects serial FreeTDS +StandardFeatures = unix Darwin XCODE GCC LFS algo app dbapi gui objects serial FreeTDS LAPACK NotProvidedRequests = MSWin MSVC KCC ICC VisualAge CompaqCompiler WorkShop MIPSpro -LimitedLinker MaxDebug LocalSSS SSSUTILS MESA GEO SSSDB SP ODBC LIBMAGIC GIF DefinesPath = common/config/ncbiconf_xcode_site.h @@ -462,13 +484,14 @@ ThirdParty_SQLITE3 = $(XCode_ThirdPartyBasePath)/sqlite-3.6.14.2-ncbi1 ThirdParty_XML = $(XCode_ThirdPartyBasePath)/libxml-2.7.8 ThirdParty_XSLT = $(XCode_ThirdPartyBasePath)/libxml-2.7.8 ThirdParty_GLEW = $(XCode_ThirdPartyBasePath)/glew-1.5.8 -ThirdParty_wxWidgets = $(XCode_ThirdPartyBasePath)/wxWidgets-3.0.2-ncbi1 +ThirdParty_wxWidgets = $(XCode_ThirdPartyBasePath)/wxWidgets-3.1.0-ncbi2 ThirdParty_FreeType = /opt/X11 ThirdParty_FTGL = $(XCode_ThirdPartyBasePath)/ftgl-2.1.3-rc5 -ThirdParty_VDB = $(XCode_ThirdPartyVDBBasePath)/vdb/vdb-versions/2.6.1 +ThirdParty_VDB = $(XCode_ThirdPartyVDBBasePath)/vdb/vdb-versions/2.8.0 ThirdParty_GMP = $(Xcode_ThirdPartyBasePath)/gmp-6.0.0a ThirdParty_Nettle = $(Xcode_ThirdPartyBasePath)/nettle-3.1.1 ThirdParty_GNUTLS = $(Xcode_ThirdPartyBasePath)/gnutls-3.4.0 +ThirdParty_LMDB = $(Xcode_ThirdPartyBasePath)/lmdb-0.9.18 LIBXML_INCLUDE = $(ThirdParty_XML)/include/libxml2 LIBXSLT_INCLUDE = $(ThirdParty_XSLT)/include @@ -483,6 +506,7 @@ DllBuildDefine = NCBI_DLL_BUILD msvc_prj = xcode30_prj # vdb_arch = i386 vdb_arch = fat86 +vdb_arch_inc = fat86 [xcode30.x86_64] Version=44 @@ -492,6 +516,7 @@ DllBuildDefine = NCBI_DLL_BUILD msvc_prj = xcode30_prj sfx64 = 64 vdb_arch = x86_64 +vdb_arch_inc = x86_64 [xcode30.i386_x86_64] Version=44 @@ -500,6 +525,7 @@ DllConfigurations = DebugDLL ReleaseDLL DllBuildDefine = NCBI_DLL_BUILD msvc_prj = xcode30_prj vdb_arch = fat86 +vdb_arch_inc = fat86 #============================================================================ @@ -535,7 +561,6 @@ BZ2_LIB = bz2 Z_LIB = z LZO_LIB = lzo PCRE_LIB = regexp -VDB_LIB = ncbi-vdb-read FTDS64_INCLUDE = dbapi/driver/ftds64/ dbapi/driver/ftds64/freetds/ FTDS64_LIB = ct_ftds64 tds_ftds64 @@ -545,11 +570,12 @@ FTDS95_INCLUDE = dbapi/driver/ftds95/ dbapi/driver/ftds95/freetds/ FTDS95_LIB = ct_ftds95 tds_ftds95 FTDS95_CTLIB_LIB = ct_ftds95 tds_ftds95 -FTDS_INCLUDE = dbapi/driver/ftds64/ dbapi/driver/ftds64/freetds/ -FTDS_LIB = ct_ftds64 tds_ftds64 +FTDS_INCLUDE = dbapi/driver/ftds95/ dbapi/driver/ftds95/freetds/ +FTDS_LIB = ct_ftds95 tds_ftds95 FTDS_LIBS = TLS_INCLUDE = $(ThirdParty_OpenSSL)/include +GNUTLS_INCLUDE = $(ThirdParty_GNUTLS)/include LIBXML_INCLUDE = $(ThirdParty_XML)/include LIBXSLT_INCLUDE = $(ThirdParty_XSLT)/include @@ -629,6 +655,9 @@ Component=LZO [HAVE_LIBGNUTLS] Component=GNUTLS +[NETWORK_LIBS] +Component=GNUTLS + [LIBS] Component= @@ -800,24 +829,24 @@ Component=Sybase Component=SQLITE3 [FTDS64_CTLIB_LIBS] -Component=Iconv, KRB5 +Component=Iconv, KRB5, GNUTLS [ICONV_LIBS] Component=Iconv [FTDS64_LIBS] -Component=Iconv, KRB5 +Component=Iconv, KRB5, GNUTLS [FTDS95_CTLIB_LIBS] -Component=Iconv, KRB5 +Component=Iconv, KRB5, GNUTLS [FTDS95_LIBS] -Component=Iconv, KRB5 +Component=Iconv, KRB5, GNUTLS [FTDS_CTLIB_LIBS] -Component=Iconv, KRB5 +Component=Iconv, KRB5, GNUTLS [FTDS_LIBS] -Component=Iconv, KRB5 +Component=Iconv, KRB5, GNUTLS [TLS_LIBS] -Component=OpenSSL +Component=GNUTLS [KRB5_LIBS] Component=KRB5 @@ -848,7 +877,8 @@ Component = gbench FILES = src\\app\\gbench\\gbench\\Makefile.in CONFS = DebugMT DebugDLL ReleaseMT ReleaseDLL - +[NCBI_INT8_GI] +Component = Ncbi-int8-gi #============================================================================ # Description of Components (non-toolkit libraries) @@ -1001,7 +1031,7 @@ Component=GLEW #---------------------------------------------------------------------------- [GNUTLS] INCLUDE = $(ThirdParty_GNUTLS)\\include -LIB = libgnutls-28.lib +LIB = libgnutls-30.lib CONFS = DebugDLL ReleaseDLL [GNUTLS.debug.DebugDLL] LIBPATH = $(ThirdParty_GNUTLS)\\lib_dll\\debugdll @@ -1137,6 +1167,32 @@ LIBPATH = $(ThirdParty_LZO)/lib$(sfx64) Component=LZO +#---------------------------------------------------------------------------- +[LMDB] +INCLUDE = $(ThirdParty_LMDB)\\include +CONFS = DebugMT DebugDLL ReleaseMT ReleaseDLL +LIB = liblmdb.lib +[LMDB.debug.DebugMT] +LIBPATH = $(ThirdParty_LMDB)\\lib_static\\debugmt +[LMDB.debug.DebugDLL] +LIBPATH = $(ThirdParty_LMDB)\\lib_static\\debugdll +[LMDB.release.ReleaseMT] +LIBPATH = $(ThirdParty_LMDB)\\lib_static\\releasemt +[LMDB.release.ReleaseDLL] +LIBPATH = $(ThirdParty_LMDB)\\lib_static\\releasedll + +[LMDB.xcode] +INCLUDE = $(ThirdParty_LMDB)/include +LIB = -llmdb +LIBPATH = $(ThirdParty_LMDB)/lib$(sfx64) + +[HAVE_LIBLMDB] +Component=LMDB + +[LMDB_LIBS] +Component=LMDB + + #---------------------------------------------------------------------------- [Mimetic] INCLUDE = $(ThirdParty_Mimetic)\\include @@ -1155,6 +1211,7 @@ LIBPATH = $(ThirdParty_Mimetic)\\lib_static\\releasedll [HAVE_LIBMIMETIC] Component=Mimetic + [MIMETIC_LIBS] Component=Mimetic @@ -1178,6 +1235,7 @@ LIBPATH = $(ThirdParty_MongoDB)\\lib_static\\releasedll [HAVE_LIBMONGODB] Component=MongoDB + [MONGODB_LIBS] Component=MongoDB @@ -1203,6 +1261,7 @@ LIBPATH = $(ThirdParty_muParser)/lib [HAVE_LIBMUPARSER] Component=muParser + [MUPARSER_LIBS] Component=muParser @@ -1787,7 +1846,7 @@ LIB = [VDB] #MACRO = VDB_INCLUDE VDB_LIBS VDB_STATIC_LIBS -INCLUDE = $(ThirdParty_VDB)\\interfaces +INCLUDE = $(ThirdParty_VDB)\\interfaces $(ThirdParty_VDB)\\interfaces\\cc\\vc++\\$(vdb_arch_inc) $(ThirdParty_VDB)\\interfaces\\cc\\vc++ $(ThirdParty_VDB)\\interfaces\\os\\win LIB = ncbi-vdb-md.lib CONFS = DebugMT DebugDLL ReleaseMT ReleaseDLL BINPATH = . @@ -1798,13 +1857,16 @@ LIBPATH = $(ThirdParty_VDB)\\win\\release\\$(vdb_arch)\\bin LIBPATH = $(ThirdParty_VDB)\\win\\release\\$(vdb_arch)\\bin [VDB.xcode] -INCLUDE = $(ThirdParty_VDB)/interfaces +INCLUDE = $(ThirdParty_VDB)/interfaces $(ThirdParty_VDB)/interfaces/cc/gcc/$(vdb_arch) $(ThirdParty_VDB)/interfaces/cc/gcc $(ThirdParty_VDB)/interfaces/os/mac $(ThirdParty_VDB)/interfaces/os/unix LIB = -lncbi-vdb [VDB.xcode.debug] LIBPATH = $(ThirdParty_VDB)/mac/debug/$(vdb_arch)/lib [VDB.xcode.release] LIBPATH = $(ThirdParty_VDB)/mac/release/$(vdb_arch)/lib +[HAVE_NCBI_VDB] +Component=VDB + #[VDB_INCLUDE] #Component=VDB #[VDB_LIB] @@ -1816,7 +1878,42 @@ Component=VDB,LIBXML,BZ2,Z [VDB_REQ] Component=VDB Value=VDB -#DefValue=LocalVDBReq +[bamread] +Component=VDB +Value=bamread +[sraread] +Component=VDB +Value=sraread +[ncbi_id2proc_snp] +Component=VDB +Value=ncbi_id2proc_snp +[ncbi_id2proc_wgs] +Component=VDB +Value=ncbi_id2proc_wgs +[ncbi_xloader_bam] +Component=VDB +Value=ncbi_xloader_bam +[ncbi_xloader_csra] +Component=VDB +Value=ncbi_xloader_csra +[ncbi_xloader_snp] +Component=VDB +Value=ncbi_xloader_snp +[ncbi_xloader_sra] +Component=VDB +Value=ncbi_xloader_sra +[ncbi_xloader_vdbgraph] +Component=VDB +Value=ncbi_xloader_vdbgraph +[ncbi_xloader_wgs] +Component=VDB +Value=ncbi_xloader_wgs + +# LAPACK (Xcode-only) +[LAPACK_LIBS] +Component = LAPACK +[LAPACK.xcode] +LIB = -llapack # CURL diff --git a/c++/src/build-system/project_tree_builder/msvc_prj_generator.cpp b/c++/src/build-system/project_tree_builder/msvc_prj_generator.cpp index a42efabf..79019a25 100644 --- a/c++/src/build-system/project_tree_builder/msvc_prj_generator.cpp +++ b/c++/src/build-system/project_tree_builder/msvc_prj_generator.cpp @@ -1316,7 +1316,7 @@ void CMsvcProjectGenerator::GenerateMsbuild( // File version CRef t(new msbuild::CProject::C_ProjectLevelTagType::C_E); project.SetProjectLevelTagType().SetProjectLevelTagType().push_back(t); - { + if (CMsvc7RegSettings::GetMsvcVersion() < CMsvc7RegSettings::eMsvc1400) { string prj_ver(GetApp().GetRegSettings().GetProjectFileFormatVersion()); if (!prj_ver.empty()) { __SET_PROPGROUP_ELEMENT(t, "_ProjectFileVersion", prj_ver); diff --git a/c++/src/build-system/project_tree_builder/msvc_prj_utils.cpp b/c++/src/build-system/project_tree_builder/msvc_prj_utils.cpp index 43e2f58b..bcc9ab87 100644 --- a/c++/src/build-system/project_tree_builder/msvc_prj_utils.cpp +++ b/c++/src/build-system/project_tree_builder/msvc_prj_utils.cpp @@ -1,4 +1,4 @@ -/* $Id: msvc_prj_utils.cpp 485908 2015-11-30 14:28:08Z gouriano $ +/* $Id: msvc_prj_utils.cpp 493103 2016-02-24 13:52:12Z gouriano $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -576,7 +576,11 @@ string CMsvc7RegSettings::sm_MsvcPlatformName = "i386"; #elif defined(NCBI_COMPILER_MSVC) -#if _MSC_VER >= 1800 +#if _MSC_VER >= 1900 +CMsvc7RegSettings::EMsvcVersion CMsvc7RegSettings::sm_MsvcVersion = +CMsvc7RegSettings::eMsvc1400; +string CMsvc7RegSettings::sm_MsvcVersionName = "1400"; +#elif _MSC_VER >= 1800 CMsvc7RegSettings::EMsvcVersion CMsvc7RegSettings::sm_MsvcVersion = CMsvc7RegSettings::eMsvc1200; string CMsvc7RegSettings::sm_MsvcVersionName = "1200"; @@ -687,6 +691,10 @@ void CMsvc7RegSettings::IdentifyPlatform() sm_MsvcVersion = eMsvc1200; sm_MsvcVersionName = "1200"; break; + case 1400: + sm_MsvcVersion = eMsvc1400; + sm_MsvcVersionName = NStr::NumericToString(ide); + break; default: NCBI_THROW(CProjBulderAppException, eBuildConfiguration, "Unsupported IDE version"); break; @@ -775,6 +783,8 @@ string CMsvc7RegSettings::GetSolutionFileFormatVersion(void) return "12.00\n# Visual Studio 2012"; } else if (GetMsvcVersion() == eMsvc1200) { return "12.00\n# Visual Studio 2013"; + } else if (GetMsvcVersion() == eMsvc1400) { + return GetApp().GetRegSettings().m_Version; } return ""; } diff --git a/c++/src/build-system/project_tree_builder/msvc_prj_utils.hpp b/c++/src/build-system/project_tree_builder/msvc_prj_utils.hpp index ef833d55..17f9e315 100644 --- a/c++/src/build-system/project_tree_builder/msvc_prj_utils.hpp +++ b/c++/src/build-system/project_tree_builder/msvc_prj_utils.hpp @@ -1,7 +1,7 @@ #ifndef PROJECT_TREE_BUILDER__MSVC_PRJ_UTILS__HPP #define PROJECT_TREE_BUILDER__MSVC_PRJ_UTILS__HPP -/* $Id: msvc_prj_utils.hpp 430659 2014-03-27 18:13:30Z gouriano $ +/* $Id: msvc_prj_utils.hpp 493103 2016-02-24 13:52:12Z gouriano $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -256,6 +256,7 @@ public: eMsvc1000, eMsvc1100, // vs2012 eMsvc1200, // vs2013 + eMsvc1400, // vs2015 eXCode30, eMsvcNone }; diff --git a/c++/src/build-system/project_tree_builder/proj_builder_app.cpp b/c++/src/build-system/project_tree_builder/proj_builder_app.cpp index 536ed602..6e64ebe6 100644 --- a/c++/src/build-system/project_tree_builder/proj_builder_app.cpp +++ b/c++/src/build-system/project_tree_builder/proj_builder_app.cpp @@ -1,4 +1,4 @@ -/* $Id: proj_builder_app.cpp 485908 2015-11-30 14:28:08Z gouriano $ +/* $Id: proj_builder_app.cpp 509504 2016-08-05 19:09:50Z fukanchi $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -405,7 +405,7 @@ struct PIsExcludedByDisuse //----------------------------------------------------------------------------- CProjBulderApp::CProjBulderApp(void) { - SetVersion( CVersionInfo(4,2,0) ); + SetVersion( CVersionInfo(4,1,5) ); m_ScanningWholeTree = false; m_Dll = false; m_AddMissingLibs = false; @@ -507,7 +507,7 @@ void CProjBulderApp::Init(void) CArgDescriptions::eString); #elif defined(NCBI_COMPILER_MSVC) arg_desc->AddOptionalKey("ide", "msvc_version", - "Target version of MS Visual Studio, for example: 1000, 1100, 1200", + "Target version of MS Visual Studio, for example: 1100, 1200, 1400", CArgDescriptions::eInteger); arg_desc->AddOptionalKey("arch", "platform", "Target platform, for example: Win32, x64", @@ -1540,6 +1540,9 @@ void CProjBulderApp::GenerateUnixProjects(CProjectItemsTree& projects_tree) if (!lib3order.empty()) { ofs << "GENERATED_LIB3PARTY_ORDER ="; ITERATE( list, l3, lib3order) { + if (l3->empty()) { + continue; + } ofs << " "; if (m_Frameworks.find(*l3) != m_Frameworks.end()) { ofs << "-framework "; @@ -2267,8 +2270,9 @@ const CMsvc7RegSettings& CProjBulderApp::GetRegSettings(void) m_MsvcRegSettings->m_DllInfo = GetConfig().Get(section, "DllInfo"); - m_MsvcRegSettings->m_Version = - GetConfig().Get(CMsvc7RegSettings::GetMsvcSection(), "Version"); + m_MsvcRegSettings->m_Version = NStr::Replace( + GetConfig().Get(CMsvc7RegSettings::GetMsvcSection(), "Version"), + "\\n", "\n"); m_MsvcRegSettings->m_CompilersSubdir = GetConfig().Get(CMsvc7RegSettings::GetMsvcSection(), "msvc_prj"); @@ -2748,6 +2752,9 @@ void CProjBulderApp::UpdateDepGraph( CProjectTreeBuilder::TFiles& files) ITERATE(list, l, libdep) { list dep_list; string dep(*l); + if (dep.at(0) == '#') { + break; + } if (CSymResolver::IsDefine(dep)) { string resolved; if (CMsvc7RegSettings::GetMsvcPlatform() != CMsvc7RegSettings::eUnix) { @@ -2813,7 +2820,7 @@ bool CProjBulderApp::InsertDep(vector< set >& graph, const string& dep, PTB_ERROR_EX(m_Root, ePTB_ConfigurationError, "Library dependency cycle found: " << NStr::Join(done, " - ")); done.pop_back(); - m_GraphDepPrecedes.erase(*d); + //m_GraphDepPrecedes.erase(*d); return false; } done.push_back(*d); diff --git a/c++/src/build-system/project_tree_builder/proj_tree_builder.cpp b/c++/src/build-system/project_tree_builder/proj_tree_builder.cpp index fa816c36..8088418f 100644 --- a/c++/src/build-system/project_tree_builder/proj_tree_builder.cpp +++ b/c++/src/build-system/project_tree_builder/proj_tree_builder.cpp @@ -1,4 +1,4 @@ -/* $Id: proj_tree_builder.cpp 485908 2015-11-30 14:28:08Z gouriano $ +/* $Id: proj_tree_builder.cpp 500658 2016-05-06 12:34:22Z gouriano $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -890,7 +890,11 @@ void SMakeProjectT::VerifyLibDepends( } if (!wrong.empty()) { fix=true; - warnings.push_back("wrong library order: " + p->Id() + " should precede " + NStr::Join(wrong,",")); +#if 0 + if (find(missing.begin(), missing.end(), p->Id()) == missing.end()) { + warnings.push_back("wrong library order: " + p->Id() + " should precede " + NStr::Join(wrong,",")); + } +#endif } libsofar.insert(p->Id()); if (!obsolete) { @@ -930,9 +934,10 @@ void SMakeProjectT::VerifyLibDepends( for (size_t a= recommend.size(); a!= 0; --a) { advice.insert(advice.end(), recommend[a-1].begin(), recommend[a-1].end()); } +#if 0 warnings.push_back("present library order: " + NStr::Join(original,",")); warnings.push_back("recommended library order: " + NStr::Join(advice,",")); - +#endif list advice_full; ITERATE( list, a, advice) { for(list::const_iterator p = depends_ids.begin(); @@ -946,6 +951,7 @@ void SMakeProjectT::VerifyLibDepends( liborder = advice_full; } } +#if 0 if (!warnings.empty() && expected_3party != nullptr) { if (libs_3party == nullptr) { warnings.push_front("====== Library order warnings (3rd party libs) ======"); @@ -955,6 +961,7 @@ void SMakeProjectT::VerifyLibDepends( PTB_WARNING_EX(mkname,ePTB_InvalidMakefile, NStr::Join(warnings,"\n")); } +#endif #else /* this compares dependency rank, @@ -2395,6 +2402,281 @@ CProjKey SMsvcProjectT::DoCreate(const string& source_base_dir, return proj_key; } //----------------------------------------------------------------------------- + +void s_AnalyzeLibraryOrder( CSymResolver& resolver, const CProjectItemsTree& tree) +{ + CProjBulderApp& app(GetApp()); + CProjectItemsTree::TProjects::const_iterator p; + for (p = tree.m_Projects.begin(); p != tree.m_Projects.end(); ++p) { + if (p->first.Type() != CProjKey::eApp) { + continue; + } + const CProjItem& project = p->second; + + list list_lib; + if (!project.m_DataSource.GetValue("LIB", list_lib)) { + continue; + } + list lib_list_in, lib_list_in0; + for( const string& lib : list_lib) { + if (lib.at(0) == '#') { + break; + } + else if (!CSymResolver::IsDefine(lib) && CSymResolver::HasDefine(lib)) { + string def = FilterDefine(lib); + string val = CSymResolver::StripDefine(def); + list tmp; + if (project.m_DataSource.GetValue(val, tmp)) { + copy(tmp.begin(), tmp.end(), back_inserter(lib_list_in)); + } else { + lib_list_in.push_back(def); + } + } else { + lib_list_in.push_back(lib); + } + } + if (lib_list_in.empty()) { + continue; + } + lib_list_in0 = lib_list_in; + + map< string, set > lib_contents; + map< string, set > lib_dependencies; + + list lib_list_out[2]; + size_t pass=0; + for (pass=0; pass<4; ++pass) { + + if (pass > 1) { + lib_list_out[0] = lib_list_out[1]; + lib_list_out[1].clear(); + } + list& list_in = pass == 0 ? lib_list_in : lib_list_out[0]; + list& list_out = pass == 0 ? lib_list_out[0] : lib_list_out[1]; + + bool failed = false; + for (list::const_iterator l = list_in.begin(); ; ++l) { + +// list_in may change (grow) during the cycle + if (l == list_in.end()) { + break; + } + const string& lib = *l; + if (failed) { + list_out.push_back(lib); + continue; + } + +// this item contents + list resolved; + if (!CSymResolver::IsDefine(lib) || + !project.m_DataSource.GetValue(CSymResolver::StripDefine(lib), resolved)) { + resolver.Resolve(lib, &resolved); + } + for_each(resolved.begin(), resolved.end(), [&lib_contents, &lib](const string& ce) { + string e(ce); + CSymResolver::StripSuffix(e); + if (!e.empty() && e.at(0) != '@') { + lib_contents[lib].insert(e); + }}); + +// this item dependencies + set alldepends; + set allflags; + for( const string& lib_item : lib_contents[lib]) { + s_CollectAllLeaves( app.m_GraphDepPrecedes, app.m_GraphDepFlags, lib_item, alldepends, allflags); + } + for_each(alldepends.begin(), alldepends.end(), [&lib_dependencies, &lib](const string& ce){ + string e(ce); + CSymResolver::StripSuffix(e); + if (!e.empty() && e.at(0) != '@') { + lib_dependencies[lib].insert(e); + }}); + + list::iterator iout = list_out.begin(); + bool do_append = true; + +// check that this item dependencies do not contain items in 'out' list + for (; iout != list_out.end(); ++iout) { + for( const string& lib_dep : lib_dependencies[lib]) { + if (lib_contents[*iout].find(lib_dep) != lib_contents[*iout].end()) { + do_append = false; + break; + } + } + if (!do_append) { + break; + } + } + + // good to append + if (do_append) { + list_out.push_back(lib); + continue; + } + + list::const_iterator i = iout; + set already_there; + bool do_replace = false; + +// maybe we could drop item at iout, because new one includes it +// compare lib_contents[*iout] with the contents of the new item + already_there.clear(); + for( const string& lib_item : lib_contents[*iout]) { + if (lib_contents[lib].find(lib_item) != lib_contents[lib].end()) { + already_there.insert(lib_item); + } + } + if (already_there.size() == lib_contents[*iout].size() && + already_there.size() != lib_contents[lib].size()) { + // it seems that the new item can replace old one + // make a note to check that it indeed may be inserted here + do_replace = true; + } + +// is there a need to add this item? +// compare this item contents with what is already there + already_there.clear(); + for (i = iout; i != list_out.end(); ++i) { + for( const string& lib_item : lib_contents[lib]) { + if (lib_contents[*i].find(lib_item) != lib_contents[*i].end()) { + already_there.insert(lib_item); + } + } + } + if (already_there.size() == lib_contents[lib].size()) { + // this is a duplicate which is already included + continue; + } + // if this item adds only few new libraries, maybe we would better + // add them expicitely instead + if (//!do_replace && + already_there.size() != 0 && + already_there.size() >= (lib_contents[lib].size() * 3)/4) { + for( const string& lib_item : lib_contents[lib]) { + if (already_there.find(lib_item) == already_there.end()) { + list_in.push_back(lib_item); + } + } + continue; + } + +// if we insert it at iout, check that items that follow do not depend on it + do_append = false; + bool do_insert = true; + i = iout; + if (do_replace) { + ++i; + } + for (; i != list_out.end(); ++i) { + for( const string& lib_dep : lib_dependencies[*i]) { + if (lib_contents[lib].find(lib_dep) != lib_contents[lib].end()) { +// maybe both include the same library. +// if so, that is acceptable + if (lib_contents[*i].find(lib_dep) != lib_contents[*i].end()) { + do_append = true; + continue; + } + do_insert = false; + break; + } + } + if (!do_insert) { + break; + } + } + +// good to insert + if (do_insert) { + i = iout; + if (do_append && ++i == list_out.end()) { + list_out.push_back(lib); + } else { + if (do_replace) { + iout = list_out.erase(iout); + } + list_out.insert(iout, lib); + } + continue; + } + +// once again, try to append, allowing identical libraries in both + do_append = true; +// check that this item dependencies do not contain items in 'out' list + for (i=iout; i != list_out.end(); ++i) { + for( const string& lib_dep : lib_dependencies[lib]) { + if (lib_contents[*i].find(lib_dep) != lib_contents[*i].end()) { + if (lib_contents[lib].find(lib_dep) != lib_contents[lib].end()) { + continue; + } + do_append = false; + break; + } + } + if (!do_append) { + break; + } + } + + // not sure about this one + if (do_replace) { + list_out.erase(iout); + for( const string& lib_item : already_there) { + list_out.remove(lib_item); + } + } + // good to append + if (do_append) { + list_out.push_back(lib); + continue; + } +// Do not know what to do +// keep it as is, in a hope that it will work +// failed = true; + list_out.push_back(lib); + } + + if (list_in.size() == list_out.size() && + equal(list_in.begin(), list_in.end(), list_out.begin())) { + break; + } + } + if (pass != 0) { + list warnings; + warnings.push_back("====== Library order warnings (toolkit libs) ======"); + warnings.push_back("present library order: " + NStr::Join(lib_list_in0," ")); + if (lib_list_out[0].size() == lib_list_out[1].size() && + equal(lib_list_out[0].begin(), lib_list_out[0].end(), lib_list_out[1].begin())) { + warnings.push_back("recommended library order: " + NStr::Join(lib_list_out[0]," ")); + + set all_libs, all_deps; + for(const string& lib_item: lib_list_out[0]) { + all_libs.insert( lib_contents[lib_item].begin(),lib_contents[lib_item].end()); + all_deps.insert( lib_dependencies[lib_item].begin(),lib_dependencies[lib_item].end()); + } + set all_missing; + for(const string& lib_item: all_deps) { + if (all_libs.find(lib_item) == all_libs.end()) { + all_missing.insert(lib_item); + } + } + if (!all_missing.empty()) { + warnings.push_back("missing libraries: " + NStr::Join(all_missing," ")); + } + } else { + warnings.push_back("Failed to identify recommended library order"); + if (pass >= 2) { + warnings.push_back("candidate1: " + NStr::Join(lib_list_out[0]," ")); + warnings.push_back("candidate2: " + NStr::Join(lib_list_out[1]," ")); + } + } + PTB_WARNING_EX(project.m_DataSource.GetFileName(),ePTB_InvalidMakefile, NStr::Join(warnings,"\n")); + } + } +} +//----------------------------------------------------------------------------- + + void CProjectTreeBuilder::BuildOneProjectTree(const IProjectFilter* filter, const string& root_src_path, @@ -2446,6 +2728,10 @@ CProjectTreeBuilder::BuildOneProjectTree(const IProjectFilter* filter, subtree_makefiles.m_Dll, subtree_makefiles.m_App, subtree_makefiles.m_User, tree); + + if (!GetApp().IsScanningWholeTree()) { + s_AnalyzeLibraryOrder(resolver, *tree); + } } diff --git a/c++/src/build-system/ptb_version.txt b/c++/src/build-system/ptb_version.txt index 4d0dcda0..b1cbc1fc 100644 --- a/c++/src/build-system/ptb_version.txt +++ b/c++/src/build-system/ptb_version.txt @@ -1 +1 @@ -4.1.2 +4.1.5 diff --git a/c++/src/build-system/relocate.sh.in b/c++/src/build-system/relocate.sh.in index a1039bb7..18fe9366 100644 --- a/c++/src/build-system/relocate.sh.in +++ b/c++/src/build-system/relocate.sh.in @@ -1,6 +1,6 @@ @script_shell@ -# $Id: relocate.sh.in 500620 2016-05-05 19:16:05Z blastadm $ +# $Id: relocate.sh.in 521320 2016-12-07 19:38:29Z blastadm $ # Author: Denis Vakatov, NCBI # # Adjust paths to this build tree and the relevant source tree diff --git a/c++/src/cgi/cgiapp.cpp b/c++/src/cgi/cgiapp.cpp index cd6cff4e..2f5e1aee 100644 --- a/c++/src/cgi/cgiapp.cpp +++ b/c++/src/cgi/cgiapp.cpp @@ -1,4 +1,4 @@ -/* $Id: cgiapp.cpp 492273 2016-02-16 15:26:05Z ivanov $ +/* $Id: cgiapp.cpp 510827 2016-08-16 15:21:28Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -115,7 +115,7 @@ public: virtual ERW_Result Read(void* buf, size_t count, size_t* bytes_read = 0); - virtual ERW_Result PendingCount(size_t* count) + virtual ERW_Result PendingCount(size_t* /*count*/) { return eRW_NotImplemented; } protected: @@ -714,9 +714,11 @@ void CCgiApplication::LogRequest(void) const // Add target url string target_url = ctx.GetRequest().GetProperty(eCgi_ScriptName); if ( !target_url.empty() ) { - string host = "http://" + GetDiagContext().GetHost(); + bool secure = AStrEquiv(ctx.GetRequest().GetRandomProperty("HTTPS", + false), "on", PNocase()); + string host = (secure ? "https://" : "http://") + GetDiagContext().GetHost(); string port = ctx.GetRequest().GetProperty(eCgi_ServerPort); - if (!port.empty() && port != "80") { + if (!port.empty() && port != (secure ? "443" : "80")) { host += ":" + port; } target_url = host + target_url; @@ -1003,7 +1005,7 @@ int CCgiApplication::OnException(exception& e, CNcbiOstream& os) // Message os << "ERROR: " << status_str << " " HTTP_EOL HTTP_EOL; - os << message; + os << NStr::HtmlEncode(message); if ( dynamic_cast (&e) ) { string ustr; @@ -1020,8 +1022,8 @@ int CCgiApplication::OnException(exception& e, CNcbiOstream& os) return -1; } } - catch (exception& e) { - NCBI_REPORT_EXCEPTION_X(14, "(CGI) CCgiApplication::Run", e); + catch (exception& ex) { + NCBI_REPORT_EXCEPTION_X(14, "(CGI) CCgiApplication::Run", ex); } return 0; } @@ -1370,7 +1372,7 @@ CCgiApplication::GetSessionStorage(CCgiSessionParameters&) const } -bool CCgiApplication::IsCachingNeeded(const CCgiRequest& request) const +bool CCgiApplication::IsCachingNeeded(const CCgiRequest& /*request*/) const { return true; } diff --git a/c++/src/cgi/cgictx.cpp b/c++/src/cgi/cgictx.cpp index 306cfc9d..577ec2f3 100644 --- a/c++/src/cgi/cgictx.cpp +++ b/c++/src/cgi/cgictx.cpp @@ -1,4 +1,4 @@ -/* $Id: cgictx.cpp 492269 2016-02-16 15:24:58Z ivanov $ +/* $Id: cgictx.cpp 509509 2016-08-05 19:12:20Z fukanchi $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -308,8 +308,13 @@ const string& CCgiContext::GetSelfURL(void) const return kEmptyStr; } - bool secure = AStrEquiv(GetRequest().GetRandomProperty("HTTPS", - false), "on", PNocase()); + bool secure + = AStrEquiv + (GetRequest().GetRandomProperty("HTTPS", false), "on", + PNocase()) + || AStrEquiv + (GetRequest().GetRandomProperty("X_FORWARDED_PROTO"), "https", + PNocase()); m_SecureMode = secure ? eSecure_On : eSecure_Off; m_SelfURL = secure ? "https://" : "http://"; m_SelfURL += server; @@ -345,7 +350,13 @@ const string& CCgiContext::GetSelfURL(void) const bool CCgiContext::IsSecure(void) const { if (m_SecureMode == eSecure_NotSet) { - m_SecureMode = NStr::EqualNocase(CTempStringEx(GetSelfURL(), 5), "https") + m_SecureMode + = NStr::EqualNocase + (CTempStringEx(GetSelfURL(), 0, 8), "https://") + || NStr::EqualNocase + (GetRequest().GetRandomProperty("HTTPS", false), "on") + || NStr::EqualNocase + (GetRequest().GetRandomProperty("X_FORWARDED_PROTO"), "https") ? eSecure_On : eSecure_Off; } return m_SecureMode == eSecure_On; @@ -750,11 +761,11 @@ bool CCgiContext::ProcessCORSRequest(const CCgiRequest& request, // Is this a preflight CORS request? if (method == CCgiRequest::eMethod_OPTIONS) { - const string& method = request.GetRandomProperty + const string& method_str = request.GetRandomProperty (s_HeaderToHttp(kAC_RequestMethod)); const string& headers = request.GetRandomProperty (s_HeaderToHttp(kAC_RequestHeaders)); - if (!s_IsAllowedMethod(method) || !s_IsAllowedHeaderList(headers)) { + if (!s_IsAllowedMethod(method_str) || !s_IsAllowedHeaderList(headers)) { // This is CORS request, but the method or headers are not allowed. response.DisableTrackingCookie(); response.SetStatus(CRequestStatus::e403_Forbidden); diff --git a/c++/src/cgi/fcgi_run.cpp b/c++/src/cgi/fcgi_run.cpp index 7eeaad3a..9597d7f8 100644 --- a/c++/src/cgi/fcgi_run.cpp +++ b/c++/src/cgi/fcgi_run.cpp @@ -1,4 +1,4 @@ -/* $Id: fcgi_run.cpp 497377 2016-04-06 13:21:42Z ivanov $ +/* $Id: fcgi_run.cpp 500790 2016-05-09 11:30:33Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -652,9 +652,9 @@ bool CCgiApplication::x_RunFastCGI(int* result, unsigned int def_iter) if(caching_needed) SaveResultToCache(m_Context->GetRequest(), result_copy); else { - unique_ptr request(GetSavedRequest(m_RID)); - if (request.get()) - SaveResultToCache(*request, result_copy); + unique_ptr saved_request(GetSavedRequest(m_RID)); + if (saved_request.get()) + SaveResultToCache(*saved_request, result_copy); } } else if (caching_needed) { SaveRequest(m_RID, m_Context->GetRequest()); diff --git a/c++/src/cgi/ncbicgi.cpp b/c++/src/cgi/ncbicgi.cpp index bbe0271d..8682c3a8 100644 --- a/c++/src/cgi/ncbicgi.cpp +++ b/c++/src/cgi/ncbicgi.cpp @@ -1,4 +1,4 @@ -/* $Id: ncbicgi.cpp 497377 2016-04-06 13:21:42Z ivanov $ +/* $Id: ncbicgi.cpp 497034 2016-04-04 12:46:26Z dicuccio $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/cgi/ncbicgir.cpp b/c++/src/cgi/ncbicgir.cpp index f6ce191a..d2d6a1a3 100644 --- a/c++/src/cgi/ncbicgir.cpp +++ b/c++/src/cgi/ncbicgir.cpp @@ -1,4 +1,4 @@ -/* $Id: ncbicgir.cpp 492273 2016-02-16 15:26:05Z ivanov $ +/* $Id: ncbicgir.cpp 506589 2016-07-08 18:45:26Z grichenk $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -220,12 +220,12 @@ void CCgiResponse::x_RestoreOutputExceptions(void) } -void CCgiResponse::SetOutput(CNcbiOstream* out, int fd) +void CCgiResponse::SetOutput(CNcbiOstream* output, int fd) { x_RestoreOutputExceptions(); m_HeaderWritten = false; - m_Output = out; + m_Output = output; m_OutputFD = fd; // Make the output stream to throw on write if it's in a bad state @@ -341,8 +341,8 @@ CNcbiOstream& CCgiResponse::WriteHeader(CNcbiOstream& os) const self->m_Cookies.Add(*m_TrackingCookie); self->SetHeaderValue(TCGI_TrackingTagName::GetDefault(), m_TrackingCookie->GetValue()); - self->SetHeaderValue("NCBI-PHID", - GetDiagContext().GetRequestContext().GetHitID()); + CRequestContext& rctx = GetDiagContext().GetRequestContext(); + self->SetHeaderValue("NCBI-PHID", rctx.GetNextSubHitID("m_")); // Prevent storing the page in public caches. string cc = GetHeaderValue(sm_CacheControl); if ( cc.empty() ) { diff --git a/c++/src/cgi/user_agent.cpp b/c++/src/cgi/user_agent.cpp index f5c4af90..e98b637d 100644 --- a/c++/src/cgi/user_agent.cpp +++ b/c++/src/cgi/user_agent.cpp @@ -1,4 +1,4 @@ -/* $Id: user_agent.cpp 485509 2015-11-23 14:51:37Z ivanov $ +/* $Id: user_agent.cpp 514811 2016-09-26 15:28:21Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -123,6 +123,7 @@ bool CCgiUserAgent::IsBrowser(void) const case eiCab: case eKonqueror: case eLynx: + case ePapers: case eOregano: case eOpera: case eW3m: @@ -512,6 +513,8 @@ const SBrowser s_Browsers[] = { { CCgiUserAgent::eCrawler, "BDFetch", "BDFetch", CCgiUserAgent::eEngine_Bot, CCgiUserAgent::ePlatform_Unknown, fAppProduct }, { CCgiUserAgent::eCrawler, "BecomeBot", "www.become.com", CCgiUserAgent::eEngine_Bot, CCgiUserAgent::ePlatform_Unknown, fAppComment }, { CCgiUserAgent::eCrawler, "Bimbot", "Bimbot", CCgiUserAgent::eEngine_Bot, CCgiUserAgent::ePlatform_Unknown, fApp }, + { CCgiUserAgent::eCrawler, "Bingbot", "www.bing.com", CCgiUserAgent::eEngine_Bot, CCgiUserAgent::ePlatform_Unknown, fAny }, + { CCgiUserAgent::eCrawler, "BingPreview", "BingPreview", CCgiUserAgent::eEngine_Bot, CCgiUserAgent::ePlatform_Unknown, fVendor }, { CCgiUserAgent::eCrawler, "BlitzBOT", "B-l-i-t-z-B-O-T", CCgiUserAgent::eEngine_Bot, CCgiUserAgent::ePlatform_Unknown, fAny }, { CCgiUserAgent::eCrawler, "BlitzBOT", "BlitzBot", CCgiUserAgent::eEngine_Bot, CCgiUserAgent::ePlatform_Unknown, fAny }, { CCgiUserAgent::eCrawler, "BlitzBOT", "BlitzBOT", CCgiUserAgent::eEngine_Bot, CCgiUserAgent::ePlatform_Unknown, fAny }, @@ -577,6 +580,7 @@ const SBrowser s_Browsers[] = { { CCgiUserAgent::eCrawler, "MojeekBot", "www.mojeek.com", CCgiUserAgent::eEngine_Bot, CCgiUserAgent::ePlatform_Unknown, fAppComment }, { CCgiUserAgent::eCrawler, "Morning Paper", "Morning Paper", CCgiUserAgent::eEngine_Bot, CCgiUserAgent::ePlatform_Unknown, fAppProduct }, { CCgiUserAgent::eCrawler, "MSNBot", "msnbot", CCgiUserAgent::eEngine_Bot, CCgiUserAgent::ePlatform_Unknown, fApp }, + { CCgiUserAgent::eCrawler, "MSNBot-Media", "msnbot-media", CCgiUserAgent::eEngine_Bot, CCgiUserAgent::ePlatform_Unknown, fApp }, { CCgiUserAgent::eCrawler, "MS Sharepoint Portal Server","MS Search", CCgiUserAgent::eEngine_Bot, CCgiUserAgent::ePlatform_Unknown, fApp }, { CCgiUserAgent::eCrawler, "MSIECrawler", "MSIECrawler", CCgiUserAgent::eEngine_Bot, CCgiUserAgent::ePlatform_Unknown, fAppComment }, { CCgiUserAgent::eCrawler, "MSRBOT", "MSRBOT", CCgiUserAgent::eEngine_Bot, CCgiUserAgent::ePlatform_Unknown, fAppProduct }, @@ -796,12 +800,15 @@ const SBrowser s_Browsers[] = { // Other { CCgiUserAgent::eiCab, "iCab", "iCab", CCgiUserAgent::eEngine_Unknown, CCgiUserAgent::ePlatform_Unknown, fApp }, + { CCgiUserAgent::ePapers, "Papers", "Papers", CCgiUserAgent::eEngine_Unknown, CCgiUserAgent::ePlatform_Unknown, fAppProduct }, { CCgiUserAgent::eKonqueror, "Konqueror", "Konqueror", CCgiUserAgent::eEngine_Unknown, CCgiUserAgent::ePlatform_Unknown, fAny }, { CCgiUserAgent::eLynx, "Lynx", "Lynx", CCgiUserAgent::eEngine_Unknown, CCgiUserAgent::ePlatform_Unknown, fAppProduct }, { CCgiUserAgent::eLynx, "ELynx", /* Linx based */ "ELynx", CCgiUserAgent::eEngine_Unknown, CCgiUserAgent::ePlatform_Unknown, fAppProduct }, { CCgiUserAgent::eOregano, "Oregano", "Oregano2", CCgiUserAgent::eEngine_Unknown, CCgiUserAgent::ePlatform_Unknown, fAppComment }, { CCgiUserAgent::eOregano, "Oregano", "Oregano", CCgiUserAgent::eEngine_Unknown, CCgiUserAgent::ePlatform_Unknown, fAppComment }, { CCgiUserAgent::eOpera, "Opera", "Opera", CCgiUserAgent::eEngine_Unknown, CCgiUserAgent::ePlatform_Unknown, fAny }, + { CCgiUserAgent::eUCBrowser, "UC Browser", "UCBrowser", CCgiUserAgent::eEngine_Unknown, CCgiUserAgent::ePlatform_Unknown, fVendorProduct }, + { CCgiUserAgent::eUCBrowser, "UC Browser", "UCWEB", CCgiUserAgent::eEngine_Unknown, CCgiUserAgent::ePlatform_Unknown, fApp }, { CCgiUserAgent::eW3m, "w3m", "w3m", CCgiUserAgent::eEngine_Unknown, CCgiUserAgent::ePlatform_Unknown, fAppProduct }, { CCgiUserAgent::eNagios, "check_http (nagios-plugins)","check_http", CCgiUserAgent::eEngine_Bot, CCgiUserAgent::ePlatform_Unknown, fAppProduct } @@ -1166,6 +1173,8 @@ void CCgiUserAgent::x_Parse(const string& user_agent) m_UserAgent.find(USTR("NetBSD")) != NPOS || m_UserAgent.find(USTR("OpenBSD")) != NPOS || m_UserAgent.find(USTR("IRIX")) != NPOS || + // ??? could be iOS as well + //m_UserAgent.find(USTR("Darwin")) != NPOS || m_UserAgent.find(USTR("nagios-plugins")) != NPOS) { m_Platform = ePlatform_Unix; } else diff --git a/c++/src/connect/Makefile.connect.lib b/c++/src/connect/Makefile.connect.lib index f943b2e2..c703d3d3 100644 --- a/c++/src/connect/Makefile.connect.lib +++ b/c++/src/connect/Makefile.connect.lib @@ -1,4 +1,4 @@ -# $Id: Makefile.connect.lib 472369 2015-07-09 14:09:43Z elisovdn $ +# $Id: Makefile.connect.lib 503166 2016-06-01 19:40:51Z lavr $ SRC_C = ncbi_ansi_ext ncbi_buffer ncbi_types ncbi_priv ncbi_core ncbi_util \ ncbi_socket ncbi_connutil ncbi_connection ncbi_connector \ @@ -6,7 +6,7 @@ SRC_C = ncbi_ansi_ext ncbi_buffer ncbi_types ncbi_priv ncbi_core ncbi_util \ ncbi_memory_connector ncbi_heapmgr ncbi_server_info ncbi_service \ ncbi_host_info ncbi_dispd ncbi_service_connector ncbi_sendmail \ ncbi_ftp_connector ncbi_lb ncbi_local ncbi_base64 ncbi_version \ - ncbi_lbos + ncbi_lbos parson SRC = $(SRC_C) UNIX_SRC = $(LOCAL_LBSM) @@ -16,6 +16,4 @@ PROJ_TAG = core mod_loadinfo LIBS = $(NETWORK_LIBS) $(ORIG_C_LIBS) -USES_LIBRARIES = $(NETWORK_LIBS) $(ORIG_LIBS) - WATCHERS = lavr elisovdn diff --git a/c++/src/connect/Makefile.connect.lib.unix b/c++/src/connect/Makefile.connect.lib.unix index 5183a511..add7ef6f 100644 --- a/c++/src/connect/Makefile.connect.lib.unix +++ b/c++/src/connect/Makefile.connect.lib.unix @@ -1,4 +1,4 @@ -# $Id: Makefile.connect.lib.unix 486618 2015-12-08 03:51:15Z ucko $ +# $Id: Makefile.connect.lib.unix 503212 2016-06-01 21:36:53Z ucko $ # Adjust ICC flags to avoid problematic references to # __intel_sse2_str* functions (as of ICC [20]13) @@ -26,4 +26,5 @@ ifeq "$(COMPILER)-$(DEBUG_SFX)$(DLL)" "icc-Release" ncbi_util.o: CFLAGS += -fno-builtin-strncmp ncbi_version.o: CFLAGS += -fno-builtin-strcpy -fno-builtin-strcspn \ -fno-builtin-strspn + parson.o: CFLAGS += -fno-builtin-strncmp endif diff --git a/c++/src/connect/Makefile.connssl.lib b/c++/src/connect/Makefile.connssl.lib index 54128cd4..1491b412 100644 --- a/c++/src/connect/Makefile.connssl.lib +++ b/c++/src/connect/Makefile.connssl.lib @@ -1,12 +1,8 @@ -# $Id: Makefile.connssl.lib 466059 2015-04-28 18:03:44Z lavr $ - -SRC = ncbi_gnutls -LIB = connssl +# $Id: Makefile.connssl.lib 503166 2016-06-01 19:40:51Z lavr $ CPPFLAGS = $(GNUTLS_INCLUDE) $(ORIG_CPPFLAGS) -LIBS = $(GNUTLS_LIBS) $(ORIG_LIBS) - -USES_LIBRARIES = $(GCRYPT_LIBS) $(GNUTLS_LIBS) connect +SRC = ncbi_gnutls +LIB = connssl WATCHERS = lavr diff --git a/c++/src/connect/Makefile.xconnect.lib b/c++/src/connect/Makefile.xconnect.lib index 07f6f97e..1d6a4404 100644 --- a/c++/src/connect/Makefile.xconnect.lib +++ b/c++/src/connect/Makefile.xconnect.lib @@ -1,4 +1,4 @@ -# $Id: Makefile.xconnect.lib 472369 2015-07-09 14:09:43Z elisovdn $ +# $Id: Makefile.xconnect.lib 503166 2016-06-01 19:40:51Z lavr $ # # XCONNECT -- includes: # CONNECT API (C-only, sources shared with the C Toolkit), plus @@ -17,7 +17,3 @@ PROJ_TAG = core LIBS = $(NETWORK_LIBS) $(ORIG_LIBS) WATCHERS = lavr elisovdn - - -USES_LIBRARIES = \ - $(NETWORK_LIBS) $(ORIG_LIBS) xncbi diff --git a/c++/src/connect/Makefile.xthrserv.lib b/c++/src/connect/Makefile.xthrserv.lib index fb432e83..34524ca1 100644 --- a/c++/src/connect/Makefile.xthrserv.lib +++ b/c++/src/connect/Makefile.xthrserv.lib @@ -1,4 +1,4 @@ -# $Id: Makefile.xthrserv.lib 427428 2014-02-20 13:41:02Z gouriano $ +# $Id: Makefile.xthrserv.lib 503166 2016-06-01 19:40:51Z lavr $ SRC = threaded_server server server_monitor connection_pool LIB = xthrserv @@ -7,7 +7,3 @@ LIBS = $(NETWORK_LIBS) DLL_LIB = xutil xconnect WATCHERS = vakatov - - -USES_LIBRARIES = \ - xconnect xutil diff --git a/c++/src/connect/Makefile.xxconnect.lib b/c++/src/connect/Makefile.xxconnect.lib index 372ee845..220ccc3d 100644 --- a/c++/src/connect/Makefile.xxconnect.lib +++ b/c++/src/connect/Makefile.xxconnect.lib @@ -1,12 +1,15 @@ -# $Id: Makefile.xxconnect.lib 478813 2015-09-14 15:54:56Z elisovdn $ +# $Id: Makefile.xxconnect.lib 503166 2016-06-01 19:40:51Z lavr $ # # XXCONNECT -- includes C++-only part of connection library +CPPFLAGS = $(GNUTLS_INCLUDE) $(ORIG_CPPFLAGS) + SRC_CXX = ncbi_socket_cxx ncbi_core_cxx email_diag_handler \ ncbi_conn_streambuf ncbi_conn_stream ncbi_conn_test \ ncbi_misc ncbi_namedpipe ncbi_namedpipe_connector \ ncbi_pipe ncbi_pipe_connector ncbi_conn_reader_writer \ - ncbi_userhost ncbi_http_session ncbi_lbos_cxx + ncbi_userhost ncbi_http_session ncbi_lbos_cxx ncbi_monkey \ + ncbi_gnutls SRC = $(SRC_CXX) @@ -16,7 +19,3 @@ PROJ_TAG = core LIBS = $(NETWORK_LIBS) $(ORIG_LIBS) WATCHERS = lavr elisovdn - - -USES_LIBRARIES = \ - $(NCBI_C_ncbi) xncbi diff --git a/c++/src/connect/connection_pool.cpp b/c++/src/connect/connection_pool.cpp index cbec6e1f..4d1a77af 100644 --- a/c++/src/connect/connection_pool.cpp +++ b/c++/src/connect/connection_pool.cpp @@ -1,4 +1,4 @@ -/* $Id: connection_pool.cpp 462064 2015-03-16 14:27:31Z satskyse $ +/* $Id: connection_pool.cpp 506707 2016-07-11 15:26:50Z satskyse $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -56,43 +56,9 @@ std::string g_ServerConnTypeToString(enum EServerConnType conn_type) } -// CServer_ControlConnection -CStdRequest* CServer_ControlConnection::CreateRequest( - EServIO_Event event, - CServer_ConnectionPool& connPool, - const STimeout* timeout) -{ - char buf[4096]; - Read(buf, sizeof(buf)); - return NULL; -} - -static void CheckIOStatus(EIO_Status io_status, const char* step) -{ - if (io_status != eIO_Success) { - NCBI_THROW_FMT(CConnException, eConn, - "Cannot create signaling socket for internal use: " << - step << ": " << IO_StatusStr(io_status)); - } -} - CServer_ConnectionPool::CServer_ConnectionPool(unsigned max_connections) : - m_MaxConnections(max_connections) -{ - // Create internal signaling connection from m_ControlSocket to - // m_ControlSocketForPoll - CListeningSocket listener; - static const STimeout kTimeout = { 10, 500000 }; // 10.5s // DEBUG - CheckIOStatus(listener.Listen(0, 5, fSOCK_BindLocal), "Listen/Bind"); - CheckIOStatus(m_ControlSocket.Connect("127.0.0.1", - listener.GetPort(eNH_HostByteOrder)), "Connect"); - m_ControlSocket.DisableOSSendDelay(); - // Set a (modest) timeout to prevent SetConnType from blocking forever - // with m_Mutex held, which could deadlock the whole server. - CheckIOStatus(m_ControlSocket.SetTimeout(eIO_Write, - &kTimeout), "SetTimeout"); - CheckIOStatus(listener.Accept(m_ControlSocketForPoll), "Accept"); -} + m_MaxConnections(max_connections), m_ListeningStarted(false) +{} CServer_ConnectionPool::~CServer_ConnectionPool() { @@ -148,6 +114,13 @@ bool CServer_ConnectionPool::Add(TConnBase* conn, EServerConnType type) m_Data.insert(conn); }} + if (type == eListener) + if (m_ListeningStarted) + // That's a new listener which should be activated right away + // because the StartListening() had already been called earlier + // (e.g. in CServer::Run()) + conn->Activate(); + PingControlConnection(); return true; } @@ -159,6 +132,50 @@ void CServer_ConnectionPool::Remove(TConnBase* conn) } +bool CServer_ConnectionPool::RemoveListener(unsigned short port) +{ + bool found = false; + + {{ + CMutexGuard guard(m_Mutex); + + if (std::find(m_ListenerPortsToStop.begin(), + m_ListenerPortsToStop.end(), port) != + m_ListenerPortsToStop.end()) { + ERR_POST(Warning << "Removing listener on port " << port << + " which has already been requested for removal"); + return false; + } + + ITERATE (TData, it, m_Data) { + TConnBase * conn_base = *it; + + conn_base->type_lock.Lock(); // To be on the safe side + if (conn_base->type == eListener) { + CServer_Listener * listener = dynamic_cast( + conn_base); + if (listener) { + if (listener->GetPort() == port) { + m_ListenerPortsToStop.push_back(port); + conn_base->type_lock.Unlock(); + + found = true; + break; + } + } + } + conn_base->type_lock.Unlock(); + } + }} + + if (found) + PingControlConnection(); + else + ERR_POST(Warning << "No listener on port " << port << " found"); + return found; +} + + void CServer_ConnectionPool::SetConnType(TConnBase* conn, EServerConnType type) { conn->type_lock.Lock(); @@ -184,11 +201,10 @@ void CServer_ConnectionPool::SetConnType(TConnBase* conn, EServerConnType type) void CServer_ConnectionPool::PingControlConnection(void) { - CFastMutexGuard guard(m_ControlMutex); - EIO_Status status = m_ControlSocket.Write("", 1, NULL, eIO_WritePlain); + EIO_Status status = m_ControlTrigger.Set(); if (status != eIO_Success) { ERR_POST_X(4, Warning - << "PingControlConnection: failed to write to control socket: " + << "PingControlConnection: failed to set control trigger: " << IO_StatusStr(status)); } } @@ -228,15 +244,16 @@ bool CServer_ConnectionPool::GetPollAndTimerVec( to_close_conns.clear(); to_delete_conns.clear(); - CMutexGuard guard(m_Mutex); - // Control socket goes here as well - polls.reserve(m_Data.size()+1); - polls.push_back(CSocketAPI::SPoll( - dynamic_cast(&m_ControlSocketForPoll), eIO_Read)); - CTime current_time(CTime::eEmpty); - const CTime* alarm_time = NULL; - const CTime* min_alarm_time = NULL; - bool alarm_time_defined = false; + const CTime * alarm_time = NULL; + const CTime * min_alarm_time = NULL; + bool alarm_time_defined = false; + CTime current_time(CTime::eEmpty); + + CMutexGuard guard(m_Mutex); + + // Control trigger goes here as well + polls.push_back(CSocketAPI::SPoll(&m_ControlTrigger, eIO_Read)); + ERASE_ITERATE(TData, it, m_Data) { // Check that socket is not processing packet - safeguards against // out-of-order packet processing by effectively pulling socket from @@ -246,6 +263,28 @@ bool CServer_ConnectionPool::GetPollAndTimerVec( TConnBase* conn_base = *it; conn_base->type_lock.Lock(); EServerConnType conn_type = conn_base->type; + + // There might be a request to delete a listener + if (conn_type == eListener) { + CServer_Listener * listener = dynamic_cast( + conn_base); + if (listener) { + unsigned short port = listener->GetPort(); + + vector::iterator port_it = + std::find(m_ListenerPortsToStop.begin(), + m_ListenerPortsToStop.end(), port); + if (port_it != m_ListenerPortsToStop.end()) { + conn_base->type_lock.Unlock(); + m_ListenerPortsToStop.erase(port_it); + delete conn_base; + m_Data.erase(it); + continue; + } + } + } + + if (conn_type == eClosedSocket || (conn_type == eInactiveSocket && !conn_base->IsOpen())) { @@ -322,11 +361,15 @@ bool CServer_ConnectionPool::GetPollAndTimerVec( void CServer_ConnectionPool::SetAllActive(const vector& polls) { ITERATE(vector, it, polls) { - if (!it->m_REvent) continue; + if (!it->m_REvent) + continue; + + CTrigger * trigger = dynamic_cast(it->m_Pollable); + if (trigger) + continue; + IServer_ConnectionBase* conn_base = dynamic_cast(it->m_Pollable); - if (conn_base == &m_ControlSocketForPoll) - continue; conn_base->type_lock.Lock(); if (conn_base->type == eInactiveSocket) @@ -356,6 +399,7 @@ void CServer_ConnectionPool::StartListening(void) ITERATE (TData, it, m_Data) { (*it)->Activate(); } + m_ListeningStarted = true; } @@ -367,4 +411,32 @@ void CServer_ConnectionPool::StopListening(void) } } + +vector CServer_ConnectionPool::GetListenerPorts(void) +{ + vector ports; + + CMutexGuard guard(m_Mutex); + ITERATE (TData, it, m_Data) { + TConnBase * conn_base = *it; + + conn_base->type_lock.Lock(); // To be on the safe side + if (conn_base->type == eListener) { + CServer_Listener * listener = dynamic_cast( + conn_base); + if (listener) { + unsigned short port = listener->GetPort(); + + if (std::find(m_ListenerPortsToStop.begin(), + m_ListenerPortsToStop.end(), port) == + m_ListenerPortsToStop.end()) + ports.push_back(listener->GetPort()); + } + } + conn_base->type_lock.Unlock(); + } + + return ports; +} + END_NCBI_SCOPE diff --git a/c++/src/connect/connection_pool.hpp b/c++/src/connect/connection_pool.hpp index cba97cd2..a320046b 100644 --- a/c++/src/connect/connection_pool.hpp +++ b/c++/src/connect/connection_pool.hpp @@ -1,7 +1,7 @@ #ifndef CONNECT___CONNECTION_POOL__HPP #define CONNECT___CONNECTION_POOL__HPP -/* $Id: connection_pool.hpp 354749 2012-02-29 17:24:19Z ivanovp $ +/* $Id: connection_pool.hpp 506707 2016-07-11 15:26:50Z satskyse $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -46,16 +46,6 @@ BEGIN_NCBI_SCOPE -class CServer_ControlConnection : public CSocket, - public IServer_ConnectionBase -{ -public: - virtual CStdRequest* CreateRequest(EServIO_Event event, - CServer_ConnectionPool& connPool, - const STimeout* timeout); -}; - - class CServer_ConnectionPool { public: @@ -72,6 +62,7 @@ public: bool Add(TConnBase* conn, EServerConnType type); void Remove(TConnBase* conn); + bool RemoveListener(unsigned short port); void PingControlConnection(void); /// Guard connection from out-of-order packet processing by @@ -97,18 +88,30 @@ public: void StartListening(void); void StopListening(void); + /// Provides a list of ports on which the server is listening + /// @return + /// currently listened ports + vector GetListenerPorts(void); + private: void x_UpdateExpiration(TConnBase* conn); typedef set TData; - TData m_Data; - mutable CMutex m_Mutex; - unsigned int m_MaxConnections; - CSocket m_ControlSocket; - mutable CServer_ControlConnection m_ControlSocketForPoll; - CFastMutex m_ControlMutex; + TData m_Data; + mutable CMutex m_Mutex; + unsigned int m_MaxConnections; + mutable CTrigger m_ControlTrigger; + +private: + // A list of ports on which the listeners should be stopped. + // A storage for the ports is needed because the listener deletion could + // not be done synchronously - the listener needs to be taken out of a poll + // vector. + // The access to the container is protected with m_Mutex + vector m_ListenerPortsToStop; + bool m_ListeningStarted; }; diff --git a/c++/src/connect/ncbi_buffer.c b/c++/src/connect/ncbi_buffer.c index 4c7161d7..eaa6b74f 100644 --- a/c++/src/connect/ncbi_buffer.c +++ b/c++/src/connect/ncbi_buffer.c @@ -1,4 +1,4 @@ -/* $Id: ncbi_buffer.c 471594 2015-06-29 17:51:13Z lavr $ +/* $Id: ncbi_buffer.c 494167 2016-03-04 01:39:52Z lavr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -89,11 +89,13 @@ extern size_t BUF_Size(BUF buf) if (!buf) return 0; + assert(!buf->size == !(buf->list || buf->last)); for (size = 0, chunk = buf->list; chunk; chunk = chunk->next) { /* NB: no empty chunks allowed within the list */ assert(chunk->size > chunk->skip); size += chunk->size - chunk->skip; + assert(chunk != buf->last || !chunk->next); } assert(size == buf->size); return size; @@ -336,8 +338,11 @@ extern size_t BUF_PeekAtCB(BUF buf, size_t todo; SBufChunk* chunk; - if (!size || !buf || !buf->size || !buf->list) + assert(!buf || !buf->size == !(buf->list || buf->last)); + + if (!size || !buf || !buf->size) return 0; + assert(buf->list && buf->last); /* special treatment for NULL callback */ if (!callback) { @@ -347,26 +352,31 @@ extern size_t BUF_PeekAtCB(BUF buf, return todo < size ? todo : size; } - /* skip "pos" bytes */ - for (chunk = buf->list; chunk; chunk = chunk->next) { - size_t avail = chunk->size - chunk->skip; - assert(chunk->size > chunk->skip); - if (avail > pos) - break; - pos -= avail; - } + /* skip "pos" bytes, first fast tracking for last chunk if possible */ + chunk = buf->last; + assert(chunk->size > chunk->skip /*i.e. chunk->size > 0*/); + if (pos + (todo = chunk->size - chunk->skip) < buf->size) { + for (chunk = buf->list; chunk; chunk = chunk->next) { + todo = chunk->size - chunk->skip; + assert(chunk->size > chunk->skip /*i.e. chunk->size > 0*/); + if (todo > pos) + break; + pos -= todo; + } + assert(chunk != buf->last); + } else + pos -= buf->size - todo; /* process the peeked data */ for (todo = size; todo && chunk; chunk = chunk->next, pos = 0) { size_t skip = chunk->skip + pos; size_t copy = chunk->size - skip; - assert(chunk->size > skip); + assert(chunk->size > skip /*i.e. chunk->size > 0*/); if (copy > todo) copy = todo; - + assert(copy); skip = callback(cbdata, (const char*) chunk->data + skip, copy); - if (skip > copy) - skip = copy; + assert(skip <= copy); todo -= skip; if (skip < copy) break; @@ -403,16 +413,19 @@ extern size_t BUF_Read(BUF buf, void* dst, size_t size) { size_t todo; + assert(!buf || !buf->size == !(buf->list || buf->last)); + /* peek to the callers data buffer, if non-NULL */ if (dst) size = BUF_Peek(buf, dst, size); - else if (!buf || !buf->size || !buf->list) + else if (!buf || !buf->size) return 0; if (!size) return 0; /* remove the read data from the buffer */ todo = size; + do { SBufChunk* head = buf->list; size_t avail = head->size - head->skip; @@ -433,6 +446,7 @@ extern size_t BUF_Read(BUF buf, void* dst, size_t size) todo -= avail; } while (todo && buf->list); + assert(!buf->size == !(buf->list || buf->last)); assert(size >= todo); return size - todo; } diff --git a/c++/src/connect/ncbi_comm.h b/c++/src/connect/ncbi_comm.h index 2b0bd977..ba4db432 100644 --- a/c++/src/connect/ncbi_comm.h +++ b/c++/src/connect/ncbi_comm.h @@ -1,7 +1,7 @@ #ifndef CONNECT___NCBI_COMM__H #define CONNECT___NCBI_COMM__H -/* $Id: ncbi_comm.h 436802 2014-05-30 18:49:16Z lavr $ +/* $Id: ncbi_comm.h 516330 2016-10-12 17:20:46Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -34,22 +34,28 @@ * */ -#define NCBID_WEBPATH "/Service/ncbid.cgi" -#define NCBI_DISP_VERSION "1.2" -#define HTTP_CONNECTION_INFO "Connection-Info:" -#define HTTP_DISP_FAILURES "Dispatcher-Failures:" -#define HTTP_DISP_MESSAGES "Dispatcher-Messages:" -#define HTTP_NCBI_MESSAGE "NCBI-Message:" -#define HTTP_NCBI_SID "NCBI-SID:" -#define HTTP_NCBI_PHID "NCBI-PHID:" -#define LBSM_DEFAULT_TIME 30 /* Default expiration time, in seconds */ -#define LBSM_DEFAULT_RATE 1000.0 /* For SLBSM_Service::info::rate */ -#define LBSM_STANDBY_THRESHOLD 0.01 -#define DISPATCHER_CFGPATH "/etc/lbsmd/" -#define DISPATCHER_CFGFILE "servrc.cfg" -#define DISPATCHER_MSGFILE ".dispd.msg" -#define CONN_FWD_PORT_MIN 5860 -#define CONN_FWD_PORT_MAX 5870 +#define NCBID_WEBPATH "/Service/ncbid.cgi" +#define NCBI_DISP_VERSION "1.2" +#define HTTP_CONNECTION_INFO "Connection-Info:" +#define HTTP_DISP_FAILURES "Dispatcher-Failures:" +#define HTTP_DISP_MESSAGES "Dispatcher-Messages:" +#define HTTP_NCBI_MESSAGE "NCBI-Message:" +#define HTTP_NCBI_SID "NCBI-SID:" +#define HTTP_NCBI_PHID "NCBI-PHID:" +#define LBSM_DEFAULT_TIME 30 /* Default expiration time, seconds */ +#define LBSM_DEFAULT_RATE 1000.0 /* For SLBSM_Service::info::rate */ +#define LBSM_STANDBY_THRESHOLD 0.01 +#define DISPATCHER_CFGPATH "/etc/lbsmd/" +#define DISPATCHER_CFGFILE "servrc.cfg" +#define DISPATCHER_MSGFILE ".dispd.msg" +#define CONN_FWD_PORT_MIN 5860 +#define CONN_FWD_PORT_MAX 5870 +#define CONN_FWD_BASE \ + "https://www.ncbi.nlm.nih.gov/IEB/ToolBox/NETWORK" +#define CONN_FWD_LINK CONN_FWD_BASE "/dispatcher.html#Firewalling" +#define CONN_FWD_URL CONN_FWD_BASE "/firewall.html#Settings" +#define NCBI_EXTERNAL "NCBI-External" + #ifdef __cplusplus extern "C" { diff --git a/c++/src/connect/ncbi_conn_stream.cpp b/c++/src/connect/ncbi_conn_stream.cpp index 428b6fe3..93319bb2 100644 --- a/c++/src/connect/ncbi_conn_stream.cpp +++ b/c++/src/connect/ncbi_conn_stream.cpp @@ -1,4 +1,4 @@ -/* $Id: ncbi_conn_stream.cpp 500356 2016-05-04 09:48:20Z ivanov $ +/* $Id: ncbi_conn_stream.cpp 507385 2016-07-18 22:38:48Z lavr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -186,10 +186,10 @@ EIO_Status CConn_IOStream::SetCanceledCallback(const ICanceled* canceled) CONN_SetCallback(conn, eCONN_OnWrite, &cb, isset ? 0 : &m_CB[2]); CONN_SetCallback(conn, eCONN_OnFlush, &cb, isset ? 0 : &m_CB[3]); } else if (isset) { - CONN_SetCallback(conn, eCONN_OnFlush, &m_CB[3], 0); - CONN_SetCallback(conn, eCONN_OnWrite, &m_CB[2], 0); - CONN_SetCallback(conn, eCONN_OnRead, &m_CB[1], 0); - CONN_SetCallback(conn, eCONN_OnOpen, &m_CB[0], 0); + CONN_SetCallback(conn, eCONN_OnFlush, &m_CB[3], 0); + CONN_SetCallback(conn, eCONN_OnWrite, &m_CB[2], 0); + CONN_SetCallback(conn, eCONN_OnRead, &m_CB[1], 0); + CONN_SetCallback(conn, eCONN_OnOpen, &m_CB[0], 0); m_Canceled = 0; } @@ -427,7 +427,7 @@ s_HttpConnectorBuilder(const SConnNetInfo* net_info, const STimeout* timeout) { size_t len; - AutoPtr > + AutoPtr x_net_info(net_info ? ConnNetInfo_Clone(net_info) : ConnNetInfo_Create(0)); if (!x_net_info.get()) { @@ -710,7 +710,7 @@ s_ServiceConnectorBuilder(const char* service, FSERVICE_GetNextInfo get_next_info, const STimeout* timeout) { - AutoPtr > + AutoPtr x_net_info(net_info ? ConnNetInfo_Clone(net_info) : ConnNetInfo_Create(service)); if (!x_net_info.get()) { @@ -1269,7 +1269,7 @@ CConn_IOStream* NcbiOpenURL(const string& url, size_t buf_size) } bool svc = s_IsIdentifier(url); - AutoPtr > net_info + AutoPtr net_info (ConnNetInfo_Create(svc ? url.c_str() : 0)); if (svc) diff --git a/c++/src/connect/ncbi_conn_test.cpp b/c++/src/connect/ncbi_conn_test.cpp index 6f0131b3..df065c73 100644 --- a/c++/src/connect/ncbi_conn_test.cpp +++ b/c++/src/connect/ncbi_conn_test.cpp @@ -1,4 +1,4 @@ -/* $Id: ncbi_conn_test.cpp 484889 2015-11-16 21:56:43Z lavr $ +/* $Id: ncbi_conn_test.cpp 516329 2016-10-12 17:20:25Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -47,8 +47,6 @@ #define HELP_EMAIL (m_Email.empty() \ ? string("NCBI Help Desk info@ncbi.nlm.nih.gov") \ : m_Email) -#define NCBI_FWDOC_URL \ - "http://www.ncbi.nlm.nih.gov/IEB/ToolBox/NETWORK/firewall.html#Settings" #define NCBI_FWD_BEMD "130.14.29.112" #define NCBI_FWD_STVA "165.112.7.12" @@ -266,20 +264,28 @@ EIO_Status CConnTest::ExtraCheckOnFailure(void) static const STimeout kTimeout = { 5, 0 }; static const STimeout kTimeSlice = { 0, 100000 }; static const struct { + EURLScheme scheme; const char* host; const char* vhost; } kTests[] = { // 0. NCBI default - { "", 0 }, // NCBI + { eURL_Http, + "", 0 }, // NCBI // 1. External server(s) - { "www.google.com", 0 }, - // NB: Google's public DNS (also @8.8.8.8), responds at :80 as well - { "8.8.4.4", "www.google.com" }, + { eURL_Https, + "www.google.com", 0 }, + // NB: Google's public DNS (@8.8.4.4/8.8), responds at :80 as well + { eURL_Http, + 0, "www.google.com" }, // 2. NCBI servers, explicitly - { "www.be-md.ncbi.nlm.nih.gov", "www.ncbi.nlm.nih.gov" }, // NCBI main - { "www.st-va.ncbi.nlm.nih.gov", "www.ncbi.nlm.nih.gov" }, // NCBI colo - { "130.14.29.110", "www.ncbi.nlm.nih.gov" }, // NCBI main - { "165.112.7.20", "www.ncbi.nlm.nih.gov" } // NCBI colo + { eURL_Https, + "www.be-md.ncbi.nlm.nih.gov", "www.ncbi.nlm.nih.gov" }, // NCBI main + { eURL_Https, + "www.st-va.ncbi.nlm.nih.gov", "www.ncbi.nlm.nih.gov" }, // NCBI colo + { eURL_Https, + "130.14.29.110", "www.ncbi.nlm.nih.gov" }, // NCBI main + { eURL_Https, + "165.112.7.20", "www.ncbi.nlm.nih.gov" } // NCBI colo }; m_CheckPoint.clear(); @@ -307,19 +313,26 @@ EIO_Status CConnTest::ExtraCheckOnFailure(void) vector< AutoPtr > http; for (size_t n = 0; n < sizeof(kTests) / sizeof(kTests[0]); ++n) { char user_header[80]; - _ASSERT(::strlen(kTests[n].host) < sizeof(net_info->host) - 1); - if (kTests[n].host[0]) - ::strcpy(net_info->host, kTests[n].host); + net_info->scheme = kTests[n].scheme; + const char* host = kTests[n].host; + if (!host) + host = rand() & 1 ? "8.8.4.4" : "8.8.8.8"; + if (*host) { + _ASSERT(::strlen(host) < sizeof(net_info->host) - 1); + ::strcpy(net_info->host, host); + } if (kTests[n].vhost) { _ASSERT(::strlen(kTests[n].vhost) + 6 < sizeof(user_header) - 1); ::sprintf(user_header, "Host: %s", kTests[n].vhost); } else *user_header = '\0'; SAuxData* auxdata = new SAuxData(m_Canceled, 0); - http.push_back(new CConn_HttpStream(net_info, user_header, s_AnyHeader, + http.push_back(new CConn_HttpStream(net_info, + user_header, s_AnyHeader, auxdata, s_Adjust, s_Cleanup)); http.back()->SetCanceledCallback(m_Canceled); } + ConnNetInfo_Destroy(net_info); EIO_Status status = eIO_Success; do { @@ -360,6 +373,7 @@ EIO_Status CConnTest::HttpOkay(string* reason) { SConnNetInfo* net_info = ConnNetInfo_Create(0, m_DebugPrintout); if (net_info) { + net_info->scheme = eURL_Https; if (net_info->http_proxy_host[0] && net_info->http_proxy_port) m_HttpProxy = true; // Make sure there are no extras @@ -368,7 +382,7 @@ EIO_Status CConnTest::HttpOkay(string* reason) } PreCheck(eHttp, 0/*main*/, - "Checking whether NCBI is HTTP accessible"); + "Checking whether NCBI is HTTP(S) accessible"); string host(net_info ? net_info->host : DEF_CONN_HOST); string port(net_info && net_info->port @@ -443,6 +457,8 @@ EIO_Status CConnTest::HttpOkay(string* reason) " appear in your configuration -- NCBI services neither" " require nor use them\n"; } + if (net_info && status == eIO_NotSupported) + temp += "Your application may also need to have SSL support on\n"; } PostCheck(eHttp, 0/*main*/, status, temp); @@ -457,7 +473,8 @@ EIO_Status CConnTest::HttpOkay(string* reason) EIO_Status CConnTest::DispatcherOkay(string* reason) { SConnNetInfo* net_info = ConnNetInfo_Create(0, m_DebugPrintout); - ConnNetInfo_SetupStandardArgs(net_info, kTest); + if (ConnNetInfo_SetupStandardArgs(net_info, kTest)) + net_info->scheme = eURL_Https; PreCheck(eDispatcher, 0/*main*/, "Checking whether NCBI dispatcher is okay"); @@ -496,6 +513,8 @@ EIO_Status CConnTest::DispatcherOkay(string* reason) temp += "Check with your network administrator that your network" " neither filters out nor blocks non-standard HTTP headers\n"; } + if (net_info && status == eIO_NotSupported) + temp += "NCBI network dispatcher must be accessed via HTTPS\n"; } PostCheck(eDispatcher, 0/*main*/, status, temp); @@ -653,8 +672,9 @@ EIO_Status CConnTest::x_GetFirewallConfiguration(const SConnNetInfo* net_info) EIO_Status CConnTest::GetFWConnections(string* reason) { SConnNetInfo* net_info = ConnNetInfo_Create(0, m_DebugPrintout); - if (net_info) { + if (ConnNetInfo_SetupStandardArgs(net_info, 0/*w/o service*/)) { const char* user_header; + net_info->scheme = eURL_Https; net_info->req_method = eReqMethod_Post; if (net_info->firewall) { user_header = "NCBI-RELAY: FALSE"; @@ -664,7 +684,6 @@ EIO_Status CConnTest::GetFWConnections(string* reason) if (net_info->stateless) m_Stateless = true; ConnNetInfo_OverrideUserHeader(net_info, user_header); - ConnNetInfo_SetupStandardArgs(net_info, 0/*w/o service*/); } string temp(m_Firewall ? "FIREWALL" : "RELAY (legacy)"); @@ -677,7 +696,7 @@ EIO_Status CConnTest::GetFWConnections(string* reason) NCBI_FWD_BEMD " and " NCBI_FWD_STVA ".\n" "To set that up correctly, please have your network administrator" " read the following (if they have not already done so):" - " " NCBI_FWDOC_URL "\n"; + " " CONN_FWD_URL "\n"; } else { temp += "This is an obsolescent mode that requires keeping a wide port" " range [4444..4544] (inclusive) open to let through connections" @@ -1038,7 +1057,7 @@ EIO_Status CConnTest::CheckFWConnections(string* reason) temp += n ? "fallback" : "non-conventional"; temp += " ports; please see your network administrator"; if (!url) { - temp += " and let them read: " NCBI_FWDOC_URL; + temp += " and let them read: " CONN_FWD_URL; url = true; } temp += '\n'; @@ -1049,7 +1068,7 @@ EIO_Status CConnTest::CheckFWConnections(string* reason) temp += " please see your network administrator"; if (!url) { temp += " and have them read the following: " - NCBI_FWDOC_URL; + CONN_FWD_URL; url = true; } temp += '\n'; @@ -1058,7 +1077,7 @@ EIO_Status CConnTest::CheckFWConnections(string* reason) " configuration to use a more narrow" " port range"; if (!url) { - temp += " per: " NCBI_FWDOC_URL; + temp += " per: " CONN_FWD_URL; url = true; } temp += '\n'; @@ -1103,7 +1122,7 @@ EIO_Status CConnTest::CheckFWConnections(string* reason) } if (note && status != eIO_Interrupt) { temp += "\nYou may want to read this link for more information: " - NCBI_FWDOC_URL; + CONN_FWD_URL; } } else { temp = "All " + string(m_Firewall diff --git a/c++/src/connect/ncbi_connection.c b/c++/src/connect/ncbi_connection.c index 3c1a31e8..a81caf22 100644 --- a/c++/src/connect/ncbi_connection.c +++ b/c++/src/connect/ncbi_connection.c @@ -1,4 +1,4 @@ -/* $Id: ncbi_connection.c 480536 2015-10-01 15:22:53Z lavr $ +/* $Id: ncbi_connection.c 513293 2016-09-09 11:36:15Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -235,6 +235,7 @@ static EIO_Status x_Flush(CONN conn, const STimeout* timeout) if (conn->meta.flush) { if (timeout == kDefaultTimeout) timeout = conn->meta.default_timeout; + assert(timeout != kDefaultTimeout); for (;;) { status = conn->meta.flush(conn->meta.c_flush, timeout); if (status == eIO_Success) @@ -288,10 +289,11 @@ static EIO_Status x_ReInit(CONN conn, CONNECTOR connector, int/*bool*/ close) /* call current connector's "CLOSE" method */ if (conn->meta.close) { EIO_Status closed; - closed = conn->meta.close(conn->meta.c_close, - conn->c_timeout == kDefaultTimeout - ? conn->meta.default_timeout - : conn->c_timeout); + const STimeout* timeout = (conn->c_timeout == kDefaultTimeout + ? conn->meta.default_timeout + : conn->c_timeout); + assert(timeout != kDefaultTimeout); + closed = conn->meta.close(conn->meta.c_close, timeout); if (closed != eIO_Success) status = closed; } @@ -325,7 +327,7 @@ static EIO_Status x_ReInit(CONN conn, CONNECTOR connector, int/*bool*/ close) if (!x_conn && connector) { assert(conn->state == eCONN_Unusable); /* setup the new connector */ - if ((status = METACONN_Add(&conn->meta, connector)) != eIO_Success) + if ((status = METACONN_Insert(&conn->meta, connector)) != eIO_Success) return status; assert(conn->meta.list); conn->state = eCONN_Closed; @@ -362,6 +364,7 @@ static EIO_Status s_Open(CONN conn) timeout = (conn->o_timeout == kDefaultTimeout ? conn->meta.default_timeout : conn->o_timeout); + assert(timeout != kDefaultTimeout); status = conn->meta.open(conn->meta.c_open, timeout); /* OnTimeout gets called only if OnOpen was there */ if (status == eIO_Timeout && !nocb) { @@ -423,6 +426,7 @@ extern EIO_Status CONN_CreateEx CONN_LOG(2, Create, eLOG_Error, "NULL connector"); } + assert(!conn == (status != eIO_Success)); CONN_CALLTRACE(Create); *connection = conn; return status; @@ -670,8 +674,10 @@ static EIO_Status s_CONN_Write timeout = (conn->w_timeout == kDefaultTimeout ? conn->meta.default_timeout : conn->w_timeout); + assert(timeout != kDefaultTimeout); status = conn->meta.write(conn->meta.c_write, buf, size, n_written, timeout); + assert(status != eIO_Success || *n_written || !size); assert(*n_written <= size); if (*n_written) { @@ -809,6 +815,7 @@ extern EIO_Status CONN_Flush : (conn->w_timeout == kDefaultTimeout ? conn->meta.default_timeout : conn->w_timeout); + assert(timeout != kDefaultTimeout); CONN_LOG(21, Flush, eLOG_Warning, "Failed to flush"); } if (conn->meta.flush) @@ -864,8 +871,10 @@ static EIO_Status s_CONN_Read timeout = (conn->r_timeout == kDefaultTimeout ? conn->meta.default_timeout : conn->r_timeout); + assert(timeout != kDefaultTimeout); status = conn->meta.read(conn->meta.c_read, buf, size - *n_read, &x_read, timeout); + assert(status != eIO_Success || x_read || !size); assert(x_read <= size - *n_read); if (x_read) { diff --git a/c++/src/connect/ncbi_connector.c b/c++/src/connect/ncbi_connector.c index 3552838f..166fbabc 100644 --- a/c++/src/connect/ncbi_connector.c +++ b/c++/src/connect/ncbi_connector.c @@ -1,4 +1,4 @@ -/* $Id: ncbi_connector.c 362029 2012-05-07 15:36:34Z lavr $ +/* $Id: ncbi_connector.c 513293 2016-09-09 11:36:15Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -36,25 +36,24 @@ #define NCBI_USE_ERRCODE_X Connect_Conn -/* Standard logging message - */ -#define METACONN_LOG(subcode, level, message) \ - CORE_LOGF_X(subcode, level, \ - ("%s (connector \"%s\", error \"%s\")", message, \ - meta->get_type \ - ? meta->get_type(meta->c_get_type) \ - : "UNDEF", IO_StatusStr(status))) +/* Standardized logging message */ +#define METACONN_LOG(subcode, level, message) \ + CORE_LOGF_X(subcode, level, \ + ("%s (connector \"%s\", error \"%s\")", message, \ + meta->get_type \ + ? meta->get_type(meta->c_get_type) \ + : "UNDEF", IO_StatusStr(status))) extern EIO_Status METACONN_Remove (SMetaConnector* meta, CONNECTOR connector) { + CONNECTOR x_conn; + assert(meta); if (connector) { - CONNECTOR x_conn; - for (x_conn = meta->list; x_conn; x_conn = x_conn->next) { if (x_conn == connector) break; @@ -68,20 +67,21 @@ extern EIO_Status METACONN_Remove } while (meta->list) { - CONNECTOR victim = meta->list; - meta->list = victim->next; - victim->meta = 0; - victim->next = 0; - if (victim->destroy) - victim->destroy(victim); - if (victim == connector) + x_conn = meta->list; + meta->list = x_conn->next; + x_conn->meta = 0; + x_conn->next = 0; + if (x_conn->destroy) + x_conn->destroy(x_conn); + if (x_conn == connector) break; } + return eIO_Success; } -extern EIO_Status METACONN_Add +extern EIO_Status METACONN_Insert (SMetaConnector* meta, CONNECTOR connector) { @@ -90,7 +90,7 @@ extern EIO_Status METACONN_Add if (connector->next || !connector->setup) { EIO_Status status = eIO_Unknown; METACONN_LOG(33, eLOG_Error, - "[METACONN_Add] Connector is in use/uninitable"); + "[METACONN_Insert] Connector is in use/uninitable"); return status; } @@ -98,5 +98,6 @@ extern EIO_Status METACONN_Add connector->setup(connector); connector->next = meta->list; meta->list = connector; + return eIO_Success; } diff --git a/c++/src/connect/ncbi_connutil.c b/c++/src/connect/ncbi_connutil.c index 17875b14..e0f3516c 100644 --- a/c++/src/connect/ncbi_connutil.c +++ b/c++/src/connect/ncbi_connutil.c @@ -1,4 +1,4 @@ -/* $Id: ncbi_connutil.c 488578 2016-01-01 00:35:35Z lavr $ +/* $Id: ncbi_connutil.c 513930 2016-09-16 15:08:47Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -43,6 +43,8 @@ #define NCBI_USE_ERRCODE_X Connect_Util +#define CONN_NET_INFO_MAGIC 0x600DF00D + #define SizeOf(arr) (sizeof(arr) / sizeof((arr)[0])) @@ -283,6 +285,13 @@ static EFWMode x_ParseFirewall(const char* str, int/*bool*/ generic) } +static int/*bool*/ s_InfoIsValid(const SConnNetInfo* info) +{ + assert(info->magic == CONN_NET_INFO_MAGIC); + return info->magic == CONN_NET_INFO_MAGIC ? 1/*true*/ : 0/*false*/; +} + + /**************************************************************************** * ConnNetInfo API */ @@ -304,11 +313,14 @@ extern SConnNetInfo* ConnNetInfo_Create(const char* service) len = service ? strlen(service) : 0; - /* NB: *NOT* cleared up with all 0s */ + /* NB: created *NOT* cleared up with all 0s */ if (!(info = (SConnNetInfo*) malloc(sizeof(*info) + len))) return 0/*failure*/; info->reserved = 0/*MBZ*/; + /* store the service name, which this structure has been created for */ + memcpy((char*) info->svc, service ? service : "", ++len); + /* client host: default */ info->client_host[0] = '\0'; @@ -328,6 +340,10 @@ extern SConnNetInfo* ConnNetInfo_Create(const char* service) /* compatibility */ info->version = 0; + /* external mode */ + REG_VALUE(REG_CONN_EXTERNAL, str, DEF_CONN_EXTERNAL); + info->external = ConnNetInfo_Boolean(str); + /* firewall mode */ REG_VALUE(REG_CONN_FIREWALL, str, DEF_CONN_FIREWALL); info->firewall = x_ParseFirewall(str, generic); @@ -437,8 +453,8 @@ extern SConnNetInfo* ConnNetInfo_Create(const char* service) /* credentials */ info->credentials = 0; - /* store the service name, which this structure has been created for */ - strcpy((char*) info->svc, service ? service : ""); + /* magic */ + info->magic = CONN_NET_INFO_MAGIC; /* done */ return info; @@ -451,14 +467,15 @@ extern int/*bool*/ ConnNetInfo_ParseURL(SConnNetInfo* info, const char* url) /* URL elements and their parsed lengths as passed */ const char *user, *pass, *host, *path, *args; size_t userlen, passlen, hostlen, pathlen, argslen; - unsigned short port; EURLScheme scheme; const char* s; size_t len; + long port; char* p; - if (!url) + if (!s_InfoIsValid(info) || !url) return 0/*failure*/; + if (!*url) return 1/*success*/; @@ -470,12 +487,13 @@ extern int/*bool*/ ConnNetInfo_ParseURL(SConnNetInfo* info, const char* url) if (len >= sizeof(info->host)) return 0/*failure*/; if (s) { - long i; errno = 0; - i = strtol(++s, &p, 10); - if (errno || s == p || !i || i ^ (i & 0xFFFF) || *p) + port = strtol(++s, &p, 10); + if (errno || s == p || *p) + return 0/*failure*/; + if (!port || port ^ (port & 0xFFFF)) return 0/*failure*/; - info->port = (unsigned short) i; + info->port = port; } if (len) { memcpy(info->host, url, len); @@ -484,9 +502,10 @@ extern int/*bool*/ ConnNetInfo_ParseURL(SConnNetInfo* info, const char* url) return 1/*success*/; } - /* "user:pass@host:port" first [any optional] */ + port = -1/*unassigned*/; + + /* "scheme://user:pass@host:port" first [any optional] */ if ((s = strstr(url, "//")) != 0) { - /* scheme is now optional, too */ if (s > url) { if (s[-1] != ':') return 0/*failure*/; @@ -501,11 +520,8 @@ extern int/*bool*/ ConnNetInfo_ParseURL(SConnNetInfo* info, const char* url) /* username:password */ if (!hostlen) { - if (scheme != eURL_File) - return 0/*failure*/; - user = pass = host = ""; + user = pass = host = scheme == eURL_File ? "" : 0; userlen = passlen = 0; - port = 0/*none*/; } else { if (!(s = (const char*) memrchr(host, '@', hostlen))) { user = pass = ""; @@ -515,6 +531,8 @@ extern int/*bool*/ ConnNetInfo_ParseURL(SConnNetInfo* info, const char* url) userlen = (size_t)(s - user); host = ++s; hostlen = (size_t)(path - s); + if (!hostlen) + return 0/*failure*/; if (!(s = (const char*) memchr(user, ':', userlen))) { pass = ""; passlen = 0; @@ -527,13 +545,14 @@ extern int/*bool*/ ConnNetInfo_ParseURL(SConnNetInfo* info, const char* url) /* port, if any */ if ((s = (const char*) memchr(host, ':', hostlen)) != 0) { - long i; - hostlen = (size_t)(s - host); + if (!(hostlen = (size_t)(s - host))) + return 0/*failure*/; errno = 0; - i = strtol(++s, &p, 10); - if (errno || s == p || !i || i ^ (i & 0xFFFF) || p != path) + port = strtol(++s, &p, 10); + if (errno || s == p || p != path) + return 0/*failure*/; + if (!port || port ^ (port & 0xFFFF)) return 0/*failure*/; - port = (unsigned short) i; } else port = 0/*default*/; @@ -548,7 +567,6 @@ extern int/*bool*/ ConnNetInfo_ParseURL(SConnNetInfo* info, const char* url) user = pass = host = 0; userlen = passlen = hostlen = 0; path = url; - port = 0; } pathlen = (scheme == eURL_Https || scheme == eURL_Http @@ -625,10 +643,11 @@ extern int/*bool*/ ConnNetInfo_ParseURL(SConnNetInfo* info, const char* url) memcpy(info->pass, pass, passlen); info->pass[passlen] = '\0'; } + if (port >= 0 || scheme == eURL_File) + info->port = port < 0 ? 0 : port; if (host) { memcpy(info->host, host, hostlen); info->host[hostlen] = '\0'; - info->port = port; } info->scheme = scheme; return 1/*success*/; @@ -638,6 +657,9 @@ extern int/*bool*/ ConnNetInfo_ParseURL(SConnNetInfo* info, const char* url) extern int/*bool*/ ConnNetInfo_SetUserHeader(SConnNetInfo* info, const char* user_header) { + if (!s_InfoIsValid(info)) + return 0/*failure*/; + if (info->http_user_header) free((void*) info->http_user_header); if (!user_header || !*user_header) @@ -653,6 +675,9 @@ extern int/*bool*/ ConnNetInfo_AppendUserHeader(SConnNetInfo* info, { char* new_header; + if (!s_InfoIsValid(info)) + return 0/*failure*/; + if (!info->http_user_header || !*info->http_user_header) return ConnNetInfo_SetUserHeader(info, user_header); @@ -712,6 +737,9 @@ static int/*bool*/ s_ModifyUserHeader(SConnNetInfo* info, size_t hdrlen; char* hdr; + if (!s_InfoIsValid(info)) + return 0/*failure*/; + if (!user_header || !(newhdrlen = strlen(user_header))) return 1/*success*/; @@ -899,7 +927,10 @@ extern int/*bool*/ ConnNetInfo_AppendArg(SConnNetInfo* info, { size_t len, used; - if (!arg || !*arg) + if (!s_InfoIsValid(info)) + return 0/*failure*/; + + if (!arg || !*arg) return 1/*success*/; used = strlen(info->args); @@ -913,7 +944,7 @@ extern int/*bool*/ ConnNetInfo_AppendArg(SConnNetInfo* info, if (used) info->args[used++] = '&'; strcpy(info->args + used, arg); - if (val && *val) { + if (val && *val) { used += len; info->args[used++] = '='; strcpy(info->args + used, val); @@ -928,7 +959,10 @@ extern int/*bool*/ ConnNetInfo_PrependArg(SConnNetInfo* info, { size_t len, off, used; - if (!arg || !*arg) + if (!s_InfoIsValid(info)) + return 0/*failure*/; + + if (!arg || !*arg) return 1/*success*/; used = strlen(info->args); @@ -959,8 +993,9 @@ extern int/*bool*/ ConnNetInfo_DeleteArg(SConnNetInfo* info, size_t arglen; char* a; - if (!arg || !(argnamelen = strcspn(arg, "=&"))) + if (!s_InfoIsValid(info) || !arg || !(argnamelen = strcspn(arg, "=&"))) return 0/*false*/; + deleted = 0/*false*/; for (a = info->args; *a; a += arglen) { if (*a == '&') @@ -989,8 +1024,9 @@ extern int/*bool*/ ConnNetInfo_DeleteArg(SConnNetInfo* info, extern void ConnNetInfo_DeleteAllArgs(SConnNetInfo* info, const char* args) { - if (!args) + if (!s_InfoIsValid(info) || !args) return; + while (*args) { const char* a = strchr(args, '&'); if (!a) @@ -1007,8 +1043,12 @@ extern int/*bool*/ ConnNetInfo_PreOverrideArg(SConnNetInfo* info, const char* arg, const char* val) { - if (!arg || !*arg) + if (!s_InfoIsValid(info)) + return 0/*failure*/; + + if (!arg || !*arg) return 1/*success*/; + ConnNetInfo_DeleteAllArgs(info, arg); return ConnNetInfo_PrependArg(info, arg, val); } @@ -1018,8 +1058,12 @@ extern int/*bool*/ ConnNetInfo_PostOverrideArg(SConnNetInfo* info, const char* arg, const char* val) { - if (!arg || !*arg) + if (!s_InfoIsValid(info)) + return 0/*failure*/; + + if (!arg || !*arg) return 1/*success*/; + ConnNetInfo_DeleteAllArgs(info, arg); return ConnNetInfo_AppendArg(info, arg, val); } @@ -1060,8 +1104,7 @@ static const char* x_ClientAddress(const char* client_host, sprintf(s, "%s(%s)", client_host, addr); if (client_host != c) free((void*) client_host); - client_host = s; - for (; *s; ++s) { + for (client_host = s; *s; ++s) { if (*s == ' ') *s = '+'; } @@ -1078,7 +1121,7 @@ extern int/*bool*/ ConnNetInfo_SetupStandardArgs(SConnNetInfo* info, int/*bool*/ local_host; const char* s; - if (!info) + if (!info || !s_InfoIsValid(info)) return 0/*failed*/; s = CORE_GetAppName(); @@ -1122,20 +1165,39 @@ extern SConnNetInfo* ConnNetInfo_Clone(const SConnNetInfo* info) { SConnNetInfo* x_info; - if (!info) + if (!info || !s_InfoIsValid(info)) return 0; if (!(x_info = (SConnNetInfo*) malloc(sizeof(*info) + strlen(info->svc)))) return 0; - memcpy(x_info, info, sizeof(*x_info)); - x_info->http_user_header = 0; - x_info->http_referer = 0; + strcpy(x_info->client_host, info->client_host); + x_info->scheme = info->scheme; + x_info->req_method = info->req_method; + x_info->version = info->version; + x_info->external = info->external; + x_info->firewall = info->firewall; + x_info->stateless = info->stateless; + x_info->lb_disable = info->lb_disable; + x_info->debug_printout = info->debug_printout; + x_info->http_push_auth = info->http_push_auth; + x_info->http_proxy_leak = info->http_proxy_leak; + x_info->reserved = info->reserved; + strcpy(x_info->user, info->user); + strcpy(x_info->pass, info->pass); + strcpy(x_info->host, info->host); + x_info->port = info->port; + strcpy(x_info->path, info->path); + strcpy(x_info->args, info->args); + strcpy(x_info->http_proxy_host, info->http_proxy_host); + x_info->http_proxy_port = info->http_proxy_port; + strcpy(x_info->http_proxy_user, info->http_proxy_user); + strcpy(x_info->http_proxy_pass, info->http_proxy_pass); + x_info->max_try = info->max_try; + x_info->http_user_header = 0; + x_info->http_referer = 0; + x_info->credentials = info->credentials; - if (info->timeout) { - x_info->tmo = *info->timeout; - x_info->timeout = &x_info->tmo; - } if (info->http_user_header && *info->http_user_header && !(x_info->http_user_header = strdup(info->http_user_header))) { ConnNetInfo_Destroy(x_info); @@ -1146,11 +1208,24 @@ extern SConnNetInfo* ConnNetInfo_Clone(const SConnNetInfo* info) ConnNetInfo_Destroy(x_info); return 0; } - strcpy((char*) x_info->svc, info->svc); + + x_info->tmo = info->timeout ? *info->timeout : info->tmo; + x_info->timeout = info->timeout ? &x_info->tmo : 0; + strcpy((char*) x_info->svc, info->svc); + + x_info->magic = CONN_NET_INFO_MAGIC; return x_info; } +static const char* x_BadMagic(unsigned int magic, char buf[]) +{ + sprintf(buf, "0x%08lX (INVALID != 0x%08lX)", + (unsigned long) magic, (unsigned long) CONN_NET_INFO_MAGIC); + return buf; +} + + static const char* x_Port(unsigned short port, char buf[]) { assert(port); @@ -1273,6 +1348,7 @@ static void s_SaveUserHeader(char* s, const char* name, memcpy(s, "NULL\n", 6); } + extern void ConnNetInfo_Log(const SConnNetInfo* info, ELOG_Level sev, LOG lg) { char buf[80]; @@ -1282,7 +1358,7 @@ extern void ConnNetInfo_Log(const SConnNetInfo* info, ELOG_Level sev, LOG lg) if (!info) { LOG_Write(lg, NCBI_C_ERRCODE_X, 10, sev, 0, 0, 0, 0, - "ConnNetInfo_Log: NULL info", 0, 0); + "ConnNetInfo_Log: NULL", 0, 0); return; } @@ -1302,6 +1378,8 @@ extern void ConnNetInfo_Log(const SConnNetInfo* info, ELOG_Level sev, LOG lg) strcpy(s, "ConnNetInfo_Log\n" "#################### [BEGIN] SConnNetInfo:\n"); + if (!s_InfoIsValid(info)) + s_SaveKeyval(s, "magic", x_BadMagic(info->magic, buf)); if (*info->svc) s_SaveString(s, "service", info->svc); else @@ -1357,6 +1435,7 @@ extern void ConnNetInfo_Log(const SConnNetInfo* info, ELOG_Level sev, LOG lg) s_SaveULong (s, "timeout(usec)", info->timeout->usec); } else s_SaveKeyval(s, "timeout", "INFINITE"); + s_SaveBool (s, "external", info->external); s_SaveKeyval (s, "firewall", x_Firewall(info->firewall)); s_SaveBool (s, "stateless", info->stateless); s_SaveBool (s, "lb_disable", info->lb_disable); @@ -1394,7 +1473,7 @@ extern char* ConnNetInfo_URL(const SConnNetInfo* info) char* url; char buf[40]; - if (!info) + if (!info || !s_InfoIsValid(info)) return 0/*failed*/; req_method = info->req_method & ~eReqMethod_v1; @@ -1440,7 +1519,7 @@ extern char* ConnNetInfo_URL(const SConnNetInfo* info) extern int/*bool*/ ConnNetInfo_SetTimeout(SConnNetInfo* info, const STimeout* timeout) { - if (!info || timeout == kDefaultTimeout) + if (!s_InfoIsValid(info) || timeout == kDefaultTimeout) return 0/*failed*/; if (timeout) { info->tmo = *timeout; @@ -1551,8 +1630,8 @@ extern EIO_Status URL_ConnectEx /* select request method and its verbal representation */ if (x_req_meth == eReqMethod_Any) x_req_meth = content_length ? eReqMethod_Post : eReqMethod_Get; - else if (content_length && (x_req_meth == eReqMethod_Get || - x_req_meth == eReqMethod_Head)) { + else if (content_length && (x_req_meth == eReqMethod_Head || + x_req_meth == eReqMethod_Get)) { CORE_LOGF_X(3, eLOG_Warning, ("[URL_Connect; http%s://%s:%hu%s%s] " " Content-Length (%lu) is ignored with request method %s", diff --git a/c++/src/connect/ncbi_core.c b/c++/src/connect/ncbi_core.c index 05697a50..a5301014 100644 --- a/c++/src/connect/ncbi_core.c +++ b/c++/src/connect/ncbi_core.c @@ -1,4 +1,4 @@ -/* $Id: ncbi_core.c 491622 2016-02-08 14:51:50Z ivanov $ +/* $Id: ncbi_core.c 507875 2016-07-21 21:24:44Z lavr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -96,7 +96,7 @@ struct MT_LOCK_tag { FMT_LOCK_Cleanup cleanup; /* cleanup function */ unsigned int magic_number; /* used internally to make sure it's init'd */ }; -#define kMT_LOCK_magic_number 0x7A96283F +#define kMT_LOCK_magic_number 0x7A96283F #ifndef NCBI_NO_THREADS @@ -132,7 +132,7 @@ static int/*bool*/ s_CORE_MT_Lock_default_handler(void* unused, InitializeCriticalSection(&sx_Crit); sx_Inited = 1; /*go*/ } else while (!sx_Inited) - Sleep(10/*ms*/); /*spin*/ + Sleep(1/*ms*/); /*spin*/ switch (action) { case eMT_Lock: @@ -255,7 +255,7 @@ struct LOG_tag { MT_LOCK mt_lock; unsigned int magic_number; /* used internally, to make sure it's init'd */ }; -#define kLOG_magic_number 0x3FB97156 +#define kLOG_magic_number 0x3FB97156 extern const char* LOG_LevelStr(ELOG_Level level) @@ -445,7 +445,7 @@ struct REG_tag { MT_LOCK mt_lock; unsigned int magic_number; /* used internally, to make sure it's init'd */ }; -#define kREG_magic_number 0xA921BC08 +#define kREG_magic_number 0xA921BC08 extern REG REG_Create diff --git a/c++/src/connect/ncbi_core_cxx.cpp b/c++/src/connect/ncbi_core_cxx.cpp index 0022b906..bb1cb323 100644 --- a/c++/src/connect/ncbi_core_cxx.cpp +++ b/c++/src/connect/ncbi_core_cxx.cpp @@ -1,4 +1,4 @@ -/* $Id: ncbi_core_cxx.cpp 488838 2016-01-06 13:45:11Z elisovdn $ +/* $Id: ncbi_core_cxx.cpp 507875 2016-07-21 21:24:44Z lavr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -34,12 +34,14 @@ */ #include -#include "ncbi_ansi_ext.h" -#include "ncbi_priv.h" #include #include #include #include +#include +#include +#include "ncbi_ansi_ext.h" +#include "ncbi_priv.h" #include #define NCBI_USE_ERRCODE_X Connect_Core @@ -48,6 +50,9 @@ BEGIN_NCBI_SCOPE +static TCORE_Set s_CORE_Set = 0; + + /*********************************************************************** * Registry * ***********************************************************************/ @@ -150,8 +155,9 @@ static void s_LOG_Handler(void* /*user_data*/, level = eDiag_Fatal; break; } - if (!IsVisibleDiagPostLevel(level)) + if (!IsVisibleDiagPostLevel(level)) { return; + } CDiagCompileInfo info(call_data->file, call_data->line, @@ -244,20 +250,6 @@ extern MT_LOCK MT_LOCK_cxx2c(CRWLock* lock, bool pass_ownership) } -/*********************************************************************** - * Fini * - ***********************************************************************/ - -extern "C" { -static void s_Fini(void) THROWS_NONE -{ - CORE_SetREG(0); - CORE_SetLOG(0); - CORE_SetLOCK(0); -} -} - - /*********************************************************************** * App Name * ***********************************************************************/ @@ -311,67 +303,182 @@ static const char* s_GetRequestDTab(void) /*********************************************************************** - * Init * + * CRAZY MONKEY CALLS * ***********************************************************************/ -DEFINE_STATIC_FAST_MUTEX(s_ConnectInitMutex); +#ifdef NCBI_MONKEY +extern "C" { + static MONKEY_RETTYPE + MONKEY_STDCALL s_MonkeySend(MONKEY_SOCKTYPE sock, + const MONKEY_DATATYPE data, + MONKEY_LENTYPE size, + int flags, + void* /* SOCK* */ sock_ptr) + { + return CMonkey::Instance()->Send(sock, data, size, flags, + (SOCK*)sock_ptr); + } + + static MONKEY_RETTYPE + MONKEY_STDCALL s_MonkeyRecv(MONKEY_SOCKTYPE sock, + MONKEY_DATATYPE buf, + MONKEY_LENTYPE size, + int flags, + void* /* SOCK* */ sock_ptr) + { + return CMonkey::Instance()->Recv(sock, buf, size, flags, + (SOCK*) sock_ptr); + } + + + static int MONKEY_STDCALL s_MonkeyConnect(MONKEY_SOCKTYPE sock, + const struct sockaddr* name, + MONKEY_SOCKLENTYPE namelen) + { + return CMonkey::Instance()->Connect(sock, name, namelen); + } + + + static int /*bool*/ s_MonkeyPoll(size_t* n, + void* /* SSOCK_Poll** */ polls, + EIO_Status* return_status) + { + return CMonkey::Instance()-> + Poll(n, (SSOCK_Poll**) polls, return_status) ? 1 : 0; + } + + + static void s_MonkeyClose(SOCKET sock) + { + CMonkey::Instance()->Close(sock); + } +} + + +static int s_MONKEY_Poll_dummy(size_t* n, + void* polls, + EIO_Status* return_status) +{ + return 0; /* call was not intercepted by Monkey*/ +} + + +static void s_MONKEY_Close_dummy(SOCKET sock) +{ + return; /* call was not intercepted by Monkey*/ +} + + +/* Chaos Monkey hooks for Connect library*/ +static void s_SetMonkeyHooks(EMonkeyHookSwitch hook_switch) +{ + switch (hook_switch) + { + case eMonkeyHookSwitch_Disabled: + g_MONKEY_Send = 0; + g_MONKEY_Recv = 0; + g_MONKEY_Connect = 0; + g_MONKEY_Poll = 0; + g_MONKEY_Close = 0; + break; + case eMonkeyHookSwitch_Enabled: + g_MONKEY_Send = s_MonkeySend; + g_MONKEY_Recv = s_MonkeyRecv; + g_MONKEY_Connect = s_MonkeyConnect; + g_MONKEY_Poll = s_MonkeyPoll; + g_MONKEY_Close = s_MonkeyClose; + break; + default: + break; + } +} +#endif //NCBI_MONKEY + static enum EConnectInit { - eConnectInit_Weak = -1, - eConnectInit_Intact = 0, - eConnectInit_Explicit = 1 + eConnectInit_Weak = -1, ///< CConn_Initer + eConnectInit_Intact = 0, ///< Not yet visited + eConnectInit_Strong = 1, ///< User init detected + eConnectInit_Explicit = 2 ///< CONNECT_Init() called } s_ConnectInit = eConnectInit_Intact; + +/*********************************************************************** + * Fini * + ***********************************************************************/ + +extern "C" { +static void s_Fini(void) THROWS_NONE +{ + s_CORE_Set &= ~g_CORE_Set; + if (s_CORE_Set & eCORE_SetSSL) + SOCK_SetupSSL(0); + if (s_CORE_Set & eCORE_SetREG) + CORE_SetREG(0); + if (s_CORE_Set & eCORE_SetLOG) + CORE_SetLOG(0); + if (s_CORE_Set & eCORE_SetLOCK) + CORE_SetLOCK(0); + g_CORE_Set &= ~s_CORE_Set; + s_CORE_Set = 0; +} +} + + +/*********************************************************************** + * Init * + ***********************************************************************/ + +DEFINE_STATIC_FAST_MUTEX(s_ConnectInitMutex); + /* NB: gets called under a lock */ static void s_Init(IRWRegistry* reg = 0, + FSSLSetup ssl = 0, CRWLock* lock = 0, TConnectInitFlags flag = 0, EConnectInit how = eConnectInit_Weak) { _ASSERT(how != eConnectInit_Intact); - if (g_NCBI_ConnectRandomSeed == 0) { - g_NCBI_ConnectRandomSeed = (int) time(0) ^ NCBI_CONNECT_SRAND_ADDEND; - srand(g_NCBI_ConnectRandomSeed); + + TCORE_Set set = 0; + if (!(g_CORE_Set & eCORE_SetLOCK)) { + CORE_SetLOCK(MT_LOCK_cxx2c(lock, flag & eConnectInit_OwnLock)); + set |= eCORE_SetLOCK; + } + if (!(g_CORE_Set & eCORE_SetLOG)) { + CORE_SetLOG(LOG_cxx2c()); + set |= eCORE_SetLOG; + } + if (!(g_CORE_Set & eCORE_SetREG)) { + CORE_SetREG(REG_cxx2c(reg, flag & eConnectInit_OwnRegistry)); + set |= eCORE_SetREG; } - CORE_SetLOCK(MT_LOCK_cxx2c(lock, - flag & eConnectInit_OwnLock ? true : false)); - CORE_SetLOG(LOG_cxx2c()); - CORE_SetREG(REG_cxx2c(reg, flag & eConnectInit_OwnRegistry)); + if (!(g_CORE_Set & eCORE_SetSSL)) { + SOCK_SetupSSL(ssl); + set |= ssl ? eCORE_SetSSL : 0; + } + g_CORE_Set &= ~set; + s_CORE_Set |= set; + if (s_ConnectInit == eConnectInit_Intact) { + g_NCBI_ConnectRandomSeed = (int) time(0) ^ NCBI_CONNECT_SRAND_ADDEND; + srand(g_NCBI_ConnectRandomSeed); atexit(s_Fini); } - /* setup request ID retrieval callback */ - g_CORE_GetRequestID = s_GetRequestID; - - /* setup app name retrieval callback */ - g_CORE_GetAppName = s_GetAppName; - - /* setup DTab-Local retrieval */ + g_CORE_GetAppName = s_GetAppName; + g_CORE_GetRequestID = s_GetRequestID; g_CORE_GetRequestDtab = s_GetRequestDTab; - - /* done! */ - s_ConnectInit = how; -} +#ifdef NCBI_MONKEY + /* Allow CMonkey to switch hooks to Connect library */ + CMonkey::MonkeyHookSwitchSet(s_SetMonkeyHooks); + /* Create CMonkey instance. It loads config and sets hooks */ + CMonkey::Instance(); +#endif //NCBI_MONKEY -static void s_InitInternal(void) -{ - CFastMutexGuard guard(s_ConnectInitMutex); - if (!g_CORE_Registry && !g_CORE_Log - && g_CORE_MT_Lock == &g_CORE_MT_Lock_default) { - try { - if (s_ConnectInit == eConnectInit_Intact) { - CMutexGuard guard(CNcbiApplication::GetInstanceMutex()); - CNcbiApplication* app = CNcbiApplication::Instance(); - s_Init(app ? &app->GetConfig() : 0); - } - } - NCBI_CATCH_ALL_X(7, "CONNECT_InitInternal() failed"); - } else { - s_ConnectInit = eConnectInit_Explicit; - } + s_ConnectInit = g_CORE_Set ? how : eConnectInit_Strong; } @@ -382,7 +489,9 @@ extern void CONNECT_Init(IRWRegistry* reg, { CFastMutexGuard guard(s_ConnectInitMutex); try { - s_Init(reg, lock, flag, eConnectInit_Explicit); + g_CORE_Set = 0; + s_Init(reg, flag & eConnectInit_NoSSL ? 0 : NcbiSetupGnuTls, + lock, flag, eConnectInit_Explicit); } NCBI_CATCH_ALL_X(8, "CONNECT_Init() failed"); } @@ -390,9 +499,17 @@ extern void CONNECT_Init(IRWRegistry* reg, CConnIniter::CConnIniter(void) { - if (s_ConnectInit == eConnectInit_Intact) { - s_InitInternal(); + if (s_ConnectInit != eConnectInit_Intact) + return; + CFastMutexGuard guard(s_ConnectInitMutex); + try { + if (s_ConnectInit == eConnectInit_Intact) { + CMutexGuard appguard(CNcbiApplication::GetInstanceMutex()); + CNcbiApplication* app = CNcbiApplication::Instance(); + s_Init(app ? &app->GetConfig() : 0, NcbiSetupGnuTls); + } } + NCBI_CATCH_ALL_X(7, "CConn_Initer::CConn_Initer() failed"); } diff --git a/c++/src/connect/ncbi_dispd.c b/c++/src/connect/ncbi_dispd.c index f8c01fee..fa059b1e 100644 --- a/c++/src/connect/ncbi_dispd.c +++ b/c++/src/connect/ncbi_dispd.c @@ -1,4 +1,4 @@ -/* $Id: ncbi_dispd.c 482179 2015-10-21 15:02:35Z lavr $ +/* $Id: ncbi_dispd.c 516325 2016-10-12 17:18:28Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -26,8 +26,8 @@ * Author: Anton Lavrentiev * * File Description: - * Low-level API to resolve NCBI service name to the server meta-address - * with the use of NCBI network dispatcher (DISPD). + * Low-level API to resolve an NCBI service name to server meta-addresses + * with the use of the NCBI network dispatcher (DISPD). * */ @@ -407,7 +407,7 @@ const SSERV_VTable* SERV_DISPD_Open(SERV_ITER iter, srand(g_NCBI_ConnectRandomSeed); } - /* Reset request method to be GET ('cause there's no HTTP body to send) */ + data->net_info->scheme = eURL_Https; data->net_info->req_method = eReqMethod_Get; if (iter->stateless) data->net_info->stateless = 1/*true*/; diff --git a/c++/src/connect/ncbi_ftp_connector.c b/c++/src/connect/ncbi_ftp_connector.c index a9ff9918..6eb688a9 100644 --- a/c++/src/connect/ncbi_ftp_connector.c +++ b/c++/src/connect/ncbi_ftp_connector.c @@ -1,4 +1,4 @@ -/* $Id: ncbi_ftp_connector.c 451703 2014-11-10 18:32:44Z lavr $ +/* $Id: ncbi_ftp_connector.c 503173 2016-06-01 19:44:56Z lavr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -110,64 +110,8 @@ static const STimeout kZeroTimeout = { 0, 0 }; static const char kDigits[] = "0123456789"; -typedef EIO_Status (*FFTPReplyParser)(SFTPConnector* xxx, int code, - size_t lineno, const char* line); - - -static EIO_Status x_FTPParseReply(SFTPConnector* xxx, int* code, - char* line, size_t maxlinelen, - FFTPReplyParser parser) -{ - EIO_Status status = eIO_Success; - size_t lineno; - size_t len; - - assert(xxx->cntl); - - for (lineno = 0; ; lineno++) { - EIO_Status rdstat; - const char* msg; - char buf[1024]; - int c, m; - - /* all FTP replies are at least '\n'-terminated, no ending with EOF */ - rdstat = SOCK_ReadLine(xxx->cntl, buf, sizeof(buf), &len); - if (rdstat != eIO_Success) { - status = rdstat; - break; - } - if (len == sizeof(buf)) { - status = eIO_Unknown/*line too long*/; - break; - } - msg = buf; - if (!lineno || isdigit((unsigned char)(*buf))) { - if (sscanf(buf, "%d%n", &c, &m) < 1 || m != 3 || !c - || (buf[m] && buf[m] != ' ' && buf[m] != '-') - || (lineno && c != *code)) { - status = eIO_Unknown; - break; - } - msg += m + 1; - if (buf[m] == '-') - m = 0; - } else { - c = *code; - m = 0; - } - msg += strspn(msg, " \t"); - if (status == eIO_Success && parser) - status = parser(xxx, lineno && m ? 0 : c, lineno, msg); - if (!lineno) { - *code = c; - if (line) - strncpy0(line, msg, maxlinelen); - } - if (m) - break; - } - return status; -} +typedef EIO_Status (*FFTPReplyCB)(SFTPConnector* xxx, int code, + size_t lineno, const char* line); /* Close data connection w/error messages @@ -252,16 +196,72 @@ static EIO_Status x_FTPCloseData(SFTPConnector* xxx, } +static EIO_Status x_FTPParseReply(SFTPConnector* xxx, int* code, + char* line, size_t maxlinelen, + FFTPReplyCB replycb) +{ + EIO_Status status = eIO_Success; + size_t lineno; + size_t len; + + assert(xxx->cntl); + + for (lineno = 0 ; ; lineno++) { + EIO_Status rdstat; + const char* msg; + char buf[1024]; + int c, m; + + /* all FTP replies are at least '\n'-terminated, no ending with EOF */ + rdstat = SOCK_ReadLine(xxx->cntl, buf, sizeof(buf), &len); + if (rdstat != eIO_Success) { + status = rdstat; + break; + } + if (len == sizeof(buf)) { + status = eIO_Unknown/*line too long*/; + break; + } + msg = buf; + if (!lineno || isdigit((unsigned char)(*buf))) { + if (sscanf(buf, "%d%n", &c, &m) < 1 || m != 3 || !c + || (buf[m] && buf[m] != ' ' && buf[m] != '-') + || (lineno && c != *code)) { + status = eIO_Unknown; + break; + } + msg += m + 1; + if (buf[m] == '-') + m = 0; + } else { + c = *code; + m = 0; + } + msg += strspn(msg, " \t"); + if (status == eIO_Success && replycb) + status = replycb(xxx, lineno && m ? 0 : c, lineno, msg); + if (!lineno) { + *code = c; + if (line) + strncpy0(line, msg, maxlinelen); + } + if (m) + break; + } + return status; +} + + static EIO_Status s_FTPReply(SFTPConnector* xxx, int* code, char* line, size_t maxlinelen, - FFTPReplyParser parser) + FFTPReplyCB replycb) { EIO_Status status; int c = 0; if (xxx->cntl) { char reason[40]; - status = x_FTPParseReply(xxx, &c, line, maxlinelen, parser); + status = x_FTPParseReply(xxx, &c, line, maxlinelen, replycb); if (status != eIO_Timeout) xxx->sync = 1/*true*/; if (status == eIO_Success) { @@ -281,7 +281,7 @@ static EIO_Status s_FTPReply(SFTPConnector* xxx, int* code, xxx->cntl = 0; if (status == eIO_Closed) { CORE_LOGF_X(10, eLOG_Error, - ("[FTP%s%s] Lost connection @ %s:%hu (%s)", + ("[FTP%s%s] Lost connection to %s:%hu (%s)", xxx->what ? "; " : "", xxx->what ? xxx->what : "", xxx->info->host, xxx->info->port, reason)); } @@ -379,8 +379,8 @@ static const char* x_4Word(const char* line, const char word[4+1]) } -static EIO_Status x_FTPParseHelp(SFTPConnector* xxx, int code, - size_t lineno, const char* line) +static EIO_Status x_FTPHelpCB(SFTPConnector* xxx, int code, + size_t lineno, const char* line) { if (!lineno) return code == 211 || code == 214 ? eIO_Success : eIO_NotSupported; @@ -466,7 +466,7 @@ static EIO_Status x_FTPHelp(SFTPConnector* xxx) if (status != eIO_Success) return status; feat = xxx->feat; - status = s_FTPReply(xxx, &code, 0, 0, x_FTPParseHelp); + status = s_FTPReply(xxx, &code, 0, 0, x_FTPHelpCB); if (status != eIO_Success || (code != 211 && code != 214)) { xxx->feat = feat; return status != eIO_Success ? status : eIO_NotSupported; @@ -475,8 +475,8 @@ static EIO_Status x_FTPHelp(SFTPConnector* xxx) } -static EIO_Status x_FTPParseFeat(SFTPConnector* xxx, int code, - size_t lineno, const char* line) +static EIO_Status x_FTPFeatCB(SFTPConnector* xxx, int code, + size_t lineno, const char* line) { if (!lineno) return code == 211 ? eIO_Success : eIO_NotSupported; @@ -511,7 +511,7 @@ static EIO_Status x_FTPFeat(SFTPConnector* xxx) if (status != eIO_Success) return status; feat = xxx->feat; - status = s_FTPReply(xxx, &code, 0, 0, x_FTPParseFeat); + status = s_FTPReply(xxx, &code, 0, 0, x_FTPFeatCB); if (status != eIO_Success || code != 211) { xxx->feat = feat; return status != eIO_Success ? status : eIO_NotSupported; @@ -1077,7 +1077,7 @@ static EIO_Status x_FTPOpenData(SFTPConnector* xxx, static EIO_Status x_FTPXfer(SFTPConnector* xxx, const char* cmd, const STimeout* timeout, - FFTPReplyParser parser) + FFTPReplyCB replycb) { int code; LSOCK lsock; @@ -1097,7 +1097,7 @@ static EIO_Status x_FTPXfer(SFTPConnector* xxx, if (status == eIO_Success) status = s_FTPCommand(xxx, cmd, 0); if (status == eIO_Success) - status = s_FTPReply(xxx, &code, 0, 0, parser); + status = s_FTPReply(xxx, &code, 0, 0, replycb); if (status == eIO_Success) { if (code == 125 || code == 150) { if (lsock) { @@ -1109,7 +1109,7 @@ static EIO_Status x_FTPXfer(SFTPConnector* xxx, assert(!xxx->data); CORE_LOGF_X(5, eLOG_Error, ("[FTP; %s] Cannot accept data connection" - " @ :%hu (%s)", xxx->what, + " at :%hu (%s)", xxx->what, LSOCK_GetPort(lsock, eNH_HostByteOrder), IO_StatusStr(status))); /* NB: data conn may have started at the server end */ @@ -1220,6 +1220,7 @@ static EIO_Status s_FTPRename(SFTPConnector* xxx, } +/* [X]CWD, [X]PWD, [X]MKD, [X]RMD, CDUP, XCUP */ static EIO_Status s_FTPDir(SFTPConnector* xxx, const char* cmd, const char* arg) @@ -1247,8 +1248,8 @@ static EIO_Status s_FTPSyst(SFTPConnector* xxx, } -static EIO_Status x_FTPParseStat(SFTPConnector* xxx, int code, - size_t lineno, const char* line) +static EIO_Status x_FTPStatCB(SFTPConnector* xxx, int code, + size_t lineno, const char* line) { if (!lineno && code != 211 && code != 212 && code != 213) return code == 450 ? eIO_Closed : eIO_NotSupported; @@ -1269,7 +1270,7 @@ static EIO_Status s_FTPStat(SFTPConnector* xxx, EIO_Status status = s_FTPCommand(xxx, cmd, 0); if (status != eIO_Success) return status; - return s_FTPReply(xxx, 0, 0, 0, x_FTPParseStat); + return s_FTPReply(xxx, 0, 0, 0, x_FTPStatCB); } @@ -1337,10 +1338,10 @@ static EIO_Status x_FTPParseMdtm(SFTPConnector* xxx, char* timestamp) } else if (len != 14) return eIO_Unknown; /* Can't use strptime() here, per the following reasons: - * 1. Only GNU implementation is documented not to require spaces - * between input format specifiers in the format string (%-based); - * 2. None to any spaces are allowed to match a space in the format, - * whilst an MDTM response must not contain even a single space. */ + * 1. Only GNU implementation is documented not to require spaces between + * input format specifiers in the format string (%-based); + * 2. None to any spaces are allowed to match a space in the format, whilst + * an MDTM response must not contain even a single space. */ for (n = 0; n < 6; n++) { size_t len = n ? 2 : 4/*year*/; if (len != strlen(strncpy0(buf, timestamp, len)) || @@ -1454,8 +1455,8 @@ static EIO_Status s_FTPRestart(SFTPConnector* xxx, } -static EIO_Status x_FTPSzcb(SFTPConnector* xxx, int code, - size_t lineno, const char* line) +static EIO_Status x_FTPRetrieveCB(SFTPConnector* xxx, int code, + size_t lineno, const char* line) { EIO_Status status = eIO_Success; if (!lineno && (code == 125 || code == 150)) { @@ -1495,7 +1496,7 @@ static EIO_Status s_FTPRetrieve(SFTPConnector* xxx, const STimeout* timeout) { xxx->size = 0; - return x_FTPXfer(xxx, cmd, timeout, x_FTPSzcb); + return x_FTPXfer(xxx, cmd, timeout, x_FTPRetrieveCB); } @@ -1527,8 +1528,8 @@ static EIO_Status s_FTPDele(SFTPConnector* xxx, } -static EIO_Status x_FTPMlsd(SFTPConnector* xxx, int code, - size_t lineno, const char* line) +static EIO_Status x_FTPMlsdCB(SFTPConnector* xxx, int code, + size_t lineno, const char* line) { if (!lineno || code != 501) return eIO_Success; @@ -1536,8 +1537,8 @@ static EIO_Status x_FTPMlsd(SFTPConnector* xxx, int code, } -static EIO_Status x_FTPMlst(SFTPConnector* xxx, int code, - size_t lineno, const char* line) +static EIO_Status x_FTPMlstCB(SFTPConnector* xxx, int code, + size_t lineno, const char* line) { if (!lineno) { return code == 250 ? eIO_Success : @@ -1556,26 +1557,27 @@ static EIO_Status x_FTPMlst(SFTPConnector* xxx, int code, /* MLST, MLSD */ -static EIO_Status s_FTPMlsx(SFTPConnector* xxx, +static EIO_Status s_FTPMlsX(SFTPConnector* xxx, const char* cmd, const STimeout* timeout) { - if (cmd[3] == 'T') { /*MLST*/ + if (cmd[3] == 'T') { /* MLST */ EIO_Status status = s_FTPCommand(xxx, cmd, 0); if (status != eIO_Success) return status; - status = s_FTPReply(xxx, 0/*code checked by cb*/, 0, 0, x_FTPMlst); + status = s_FTPReply(xxx, 0/*code checked by cb*/, 0, 0, x_FTPMlstCB); if (status != eIO_Success) BUF_Erase(xxx->rbuf); return status; } + /* MLSD */ xxx->size = 0; /* cf. s_FTPRetrieve() */ - return x_FTPXfer(xxx, cmd, timeout, x_FTPMlsd); + return x_FTPXfer(xxx, cmd, timeout, x_FTPMlsdCB); } -static EIO_Status x_FTPNgcb(SFTPConnector* xxx, int code, - size_t lineno, const char* line) +static EIO_Status x_FTPNegotiateCB(SFTPConnector* xxx, int code, + size_t lineno, const char* line) { if (lineno && code / 100 == 2) { if (*line &&/*NB: RFC2389 3.2 & 4, the leading space has been skipped*/ @@ -1597,12 +1599,12 @@ static EIO_Status s_FTPNegotiate(SFTPConnector* xxx, EIO_Status status = s_FTPCommand(xxx, cmd, 0); if (status != eIO_Success) return status; - status = s_FTPReply(xxx, &code, 0, 0, x_FTPNgcb); + status = s_FTPReply(xxx, &code, 0, 0, x_FTPNegotiateCB); if (status == eIO_Success) { - if (*cmd == 'F') { + if (*cmd == 'F') { /* FEAT */ if (code != 211) status = eIO_Closed; - } else { + } else { /* OPTS */ if (code == 451) status = eIO_Unknown; else if (code != 200) @@ -1630,7 +1632,7 @@ static EIO_Status s_FTPPollCntl(SFTPConnector* xxx, const STimeout* timeout) status = s_FTPReply(xxx, &code, buf, sizeof(buf) - 1, 0); if (status == eIO_Success) { assert(!xxx->data || xxx->send); - CORE_LOGF_X(12, eLOG_Error, + CORE_LOGF_X(12, xxx->data ? eLOG_Error : eLOG_Warning, ("[FTP%s%s] %spurious response %d from server%s%s", xxx->what ? "; " : "", xxx->what ? xxx->what : "", xxx->data ? "Aborting upload due to a s" : "S", code, @@ -1706,7 +1708,7 @@ static EIO_Status s_FTPExecute(SFTPConnector* xxx, const STimeout* timeout) if (size == 3 || size == 4) { SOCK_SetTimeout(xxx->cntl, eIO_ReadWrite, timeout); if (size == 3 && strncasecmp(s, "REN", 3) == 0) { - /* a special-case, non-standard command */ + /* special-case, non-standard command */ status = s_FTPRename(xxx, c + strspn(c, " \t")); } else if ((size == 3 || toupper((unsigned char) c[-4]) == 'X') && (strncasecmp(c - 3, "CWD", 3) == 0 || @@ -1738,7 +1740,7 @@ static EIO_Status s_FTPExecute(SFTPConnector* xxx, const STimeout* timeout) status = s_FTPStore (xxx, s, timeout); } else if (size == 4 && (strncasecmp(s, "MLSD", 4) == 0 || strncasecmp(s, "MLST", 4) == 0)) { - status = s_FTPMlsx (xxx, s, timeout); + status = s_FTPMlsX (xxx, s, timeout); } else if (size == 4 && (strncasecmp(s, "FEAT", 4) == 0 || strncasecmp(s, "OPTS", 4) == 0)) { status = s_FTPNegotiate(xxx, s); diff --git a/c++/src/connect/ncbi_gnutls.c b/c++/src/connect/ncbi_gnutls.c index 2d32bbf3..f1e5a017 100644 --- a/c++/src/connect/ncbi_gnutls.c +++ b/c++/src/connect/ncbi_gnutls.c @@ -1,4 +1,4 @@ -/* $Id: ncbi_gnutls.c 500354 2016-05-04 09:47:08Z ivanov $ +/* $Id: ncbi_gnutls.c 517037 2016-10-20 11:20:25Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -602,7 +602,7 @@ static EIO_Status s_GnuTlsInit(FSSLPull pull, FSSLPush push) CORE_UNLOCK; if (s_GnuTlsLogLevel) { gnutls_global_set_log_function(x_GnuTlsLogger); - if (val != buf) + if (val == buf) gnutls_global_set_log_level(s_GnuTlsLogLevel); CORE_LOGF(eLOG_Note, ("GNUTLS V%s (Loglevel=%d)", version, s_GnuTlsLogLevel)); @@ -681,28 +681,39 @@ static const char* s_GnuTlsError(void* session/*unused*/, int error) } +#else + + +/*ARGSUSED*/ +static EIO_Status s_GnuTlsInit(FSSLPull unused_pull, FSSLPush unused_push) +{ + CORE_LOG(eLOG_Critical, "Unavailable feature GNUTLS"); + return eIO_NotSupported; +} + + #endif /*HAVE_LIBGNUTLS*/ extern SOCKSSL NcbiSetupGnuTls(void) { -#ifdef HAVE_LIBGNUTLS static const struct SOCKSSL_struct kGnuTlsOps = { - s_GnuTlsInit, - s_GnuTlsCreate, - s_GnuTlsOpen, - s_GnuTlsRead, - s_GnuTlsWrite, - s_GnuTlsClose, - s_GnuTlsDelete, - s_GnuTlsExit, - s_GnuTlsError + s_GnuTlsInit +#ifdef HAVE_LIBGNUTLS + , s_GnuTlsCreate + , s_GnuTlsOpen + , s_GnuTlsRead + , s_GnuTlsWrite + , s_GnuTlsClose + , s_GnuTlsDelete + , s_GnuTlsExit + , s_GnuTlsError +#endif /*HAVE_LIBGNUTLS*/ }; +#ifndef HAVE_LIBGNUTLS + CORE_LOG(eLOG_Warning, "Unavailable feature GNUTLS"); +#endif /*!HAVE_LIBGNUTLS*/ return &kGnuTlsOps; -#else - CORE_LOG(eLOG_Critical, "Unavailable feature GNUTLS"); - return 0; -#endif /*HAVE_LIBGNUTLS*/ } diff --git a/c++/src/connect/ncbi_http_connector.c b/c++/src/connect/ncbi_http_connector.c index 69af0b7a..b93f2d28 100644 --- a/c++/src/connect/ncbi_http_connector.c +++ b/c++/src/connect/ncbi_http_connector.c @@ -1,4 +1,4 @@ -/* $Id: ncbi_http_connector.c 500357 2016-05-04 09:48:45Z ivanov $ +/* $Id: ncbi_http_connector.c 505576 2016-06-27 16:34:25Z lavr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -1220,7 +1220,7 @@ static EIO_Status s_ReadHeader(SHttpConnector* uuu, } verify(BUF_Peek(uuu->http, hdr, size) == size); if (memcmp(&hdr[size - 4], "\r\n\r\n", 4) == 0) { - /*full header captured*/ + /* full header captured */ hdr[size] = '\0'; break; } @@ -1580,15 +1580,12 @@ static EIO_Status s_ReadHeader(SHttpConnector* uuu, if (!retry->data) free(hdr); - if (!http_code) { - if (header_parse != eHTTP_HeaderError) { - if (url) - free(url); - return eIO_Success; - } - http_code = -1; + if (http_code == 0) { + if (url) + free(url); + return header_parse == eHTTP_HeaderError ? eIO_Unknown : eIO_Success; } - /*NB: http_code != 0*/ + assert(header_parse != eHTTP_HeaderComplete); if (uuu->net_info->debug_printout || header_parse == eHTTP_HeaderContinue) { @@ -1733,7 +1730,7 @@ static EIO_Status s_PreRead(SHttpConnector* uuu, assert((uuu->conn_state & eCS_ReadBody) && !retry.mode); /* pending output data no longer needed */ BUF_Erase(uuu->w_buf); - return eIO_Success; + break; } assert(status != eIO_Timeout || !retry.mode); @@ -1758,9 +1755,9 @@ static EIO_Status s_PreRead(SHttpConnector* uuu, } } - assert(status != eIO_Success); if (BUF_Size(uuu->http) && !BUF_Splice(&uuu->r_buf, uuu->http)) BUF_Erase(uuu->http); + assert(!BUF_Size(uuu->http)); return status; } @@ -1852,7 +1849,6 @@ static EIO_Status s_Read(SHttpConnector* uuu, void* buf, const char* how = 0; if (uuu->received < uuu->expected) { if (status == eIO_Closed) { - assert(uuu->conn_state == eCS_ReadBody); status = eIO_Unknown; how = "premature EOM in"; } @@ -2092,7 +2088,7 @@ static EIO_Status s_VT_Write } else uuu->w_timeout = kInfiniteTimeout; - /* if trying to write after a request then close the socket, + /* if trying to write after a request then close the socket first, * and so return to "IDLE" */ if (uuu->sock && uuu->conn_state > eCS_WriteRequest) { status = s_Disconnect(uuu, timeout, @@ -2118,8 +2114,8 @@ static EIO_Status s_VT_Write if (status != eIO_Success) return status; } - assert((!uuu->sock || uuu->conn_state == eCS_WriteRequest) - && !uuu->w_len); + assert(!uuu->sock || (uuu->conn_state == eCS_WriteRequest + && !uuu->w_len)); if (size) { char prefix[80]; int n = sprintf(prefix, "%" NCBI_BIGCOUNT_FORMAT_SPEC_HEX "\r\n", @@ -2186,7 +2182,7 @@ static EIO_Status s_VT_Flush } status = x_IsWriteThru(uuu) ? s_ConnectAndSend(uuu, timeout, eEM_Flush) - : s_PreRead (uuu, timeout, eEM_Flush); + : s_PreRead (uuu, timeout, eEM_Flush); return BUF_Size(uuu->r_buf) ? eIO_Success : status; } @@ -2424,6 +2420,7 @@ static EIO_Status s_CreateHttpConnector uuu->http = 0; uuu->r_buf = 0; uuu->w_buf = 0; + uuu->w_len = 0; if (tunnel) s_OpenHttpConnector(uuu, xxx->timeout); diff --git a/c++/src/connect/ncbi_http_session.cpp b/c++/src/connect/ncbi_http_session.cpp index dd3525b8..2e14f097 100644 --- a/c++/src/connect/ncbi_http_session.cpp +++ b/c++/src/connect/ncbi_http_session.cpp @@ -1,4 +1,4 @@ -/* $Id: ncbi_http_session.cpp 493038 2016-02-23 19:24:35Z ivanov $ +/* $Id: ncbi_http_session.cpp 519414 2016-11-15 18:23:40Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -195,8 +195,7 @@ void CHttpHeaders::Merge(const CHttpHeaders& headers) bool CHttpHeaders::x_IsReservedHeader(CTempString name) const { for (size_t i = 0; i < sizeof(kReservedHeaders)/sizeof(kReservedHeaders[0]); ++i) { - THeaders::const_iterator it = m_Headers.find(kReservedHeaders[i]); - if (it != m_Headers.end()) { + if (!NStr::CompareNocase(name, kReservedHeaders[i])) { ERR_POST(kReservedHeaders[i] << " must be set through CRequestContext"); return true; } @@ -552,31 +551,160 @@ CHttpRequest::CHttpRequest(CHttpSession& session, m_Url(url), m_Method(method), m_Headers(new CHttpHeaders), - m_Timeout(CTimeout::eDefault) + m_Timeout(CTimeout::eDefault), + m_Deadline(CTimeout::eDefault), + m_RetryProcessing(ESwitch::eDefault) { } +// Processing logic for 'retry later' response in CHttpRequest::Execute() +struct SRetryProcessing +{ + SRetryProcessing(ESwitch on_off, const CTimeout& deadline, CUrl& url, + EReqMethod& method, CRef& headers, + CRef& form_data); + + bool operator()(const CHttpHeaders& headers); + +private: + // This class is used to restore CHttpRequest members to their original state + template + struct SValueRestorer + { + TMember& value; + + SValueRestorer(TMember& v) : value(v) { Assign(original, value); } + ~SValueRestorer() { Restore(); } + void Restore() { Assign(value, original); } + + private: + TValue original; + }; + + template static void Assign(TTo&, const TFrom&); + + const bool m_Enabled; + CDeadline m_Deadline; + SValueRestorer m_Url; + SValueRestorer m_Method; + SValueRestorer, CHttpHeaders> m_Headers; + SValueRestorer> m_FormData; +}; + + +SRetryProcessing::SRetryProcessing(ESwitch on_off, const CTimeout& deadline, CUrl& url, + EReqMethod& method, CRef& headers, + CRef& form_data) : + m_Enabled(on_off == eOn), + m_Deadline(deadline.IsDefault() ? CTimeout::eInfinite : deadline), + m_Url(url), + m_Method(method), + m_Headers(headers), + m_FormData(form_data) +{ +} + + +bool SRetryProcessing::operator()(const CHttpHeaders& headers) +{ + // Must correspond to CHttpRetryContext (e.g. CCgi2RCgiApp) values + const unsigned long kExecuteDefaultRefreshDelay = 5; + const string kExecuteHeaderRetryURL = "X-NCBI-Retry-URL"; + const string kExecuteHeaderRetryDelay = "X-NCBI-Retry-Delay"; + + if (!m_Enabled) return false; + if (m_Deadline.IsExpired()) return false; + + const auto& retry_url = headers.GetValue(kExecuteHeaderRetryURL); + + // Not a 'retry later' response (e.g. remote CGI has already finished) + if (retry_url.empty()) return false; + + const auto& retry_delay = headers.GetValue(kExecuteHeaderRetryDelay); + unsigned long sleep_ms = kExecuteDefaultRefreshDelay; + + // HTTP header has delay + if (!retry_delay.empty()) { + try { + sleep_ms = NStr::StringToULong(retry_delay) * kMilliSecondsPerSecond; + } + catch (CStringException& ex) { + if (ex.GetErrCode() != CStringException::eConvert) throw; + } + } + + // If the deadline is less than the retry delay, + // sleep for the remaining and check once again + try { + auto remaining = m_Deadline.GetRemainingTime().GetAsMilliSeconds(); + if (remaining < sleep_ms) sleep_ms = remaining; + } + catch (CTimeException& ex) { + if (ex.GetErrCode() != CTimeException::eConvert) throw; + } + + SleepMilliSec(sleep_ms); + + // Make subsequent requests appropriate + m_Url.value = retry_url; + m_Method.value = eReqMethod_Get; + m_Headers.Restore(); + m_FormData.value.Reset(); + + return true; +} + + +template +void SRetryProcessing::Assign(TTo& to, const TFrom& from) +{ + to = from; +} + + +template <> +void SRetryProcessing::Assign(CHttpHeaders& to, const CRef& from) +{ + to.Assign(*from); +} + + +template <> +void SRetryProcessing::Assign(CRef& to, const CHttpHeaders& from) +{ + to->Assign(from); +} + + CHttpResponse CHttpRequest::Execute(void) { - // Connection not open yet. - // Only POST and PUT support sending form data. - bool have_data = m_FormData && !m_FormData.Empty(); - if ( !m_Response ) { - x_InitConnection(have_data); + SRetryProcessing retry_processing(m_RetryProcessing, m_Deadline, m_Url, + m_Method, m_Headers, m_FormData); + CRef ret; + + do { + // Connection not open yet. + // Only POST and PUT support sending form data. + bool have_data = m_FormData && !m_FormData.Empty(); + if ( !m_Response ) { + x_InitConnection(have_data); + } + _ASSERT(m_Response); + _ASSERT(m_Stream && m_Stream->IsInitialized()); + CConn_IOStream& out = m_Stream->GetConnStream(); + if ( have_data ) { + m_FormData->WriteFormData(out); + } + // Send data to the server and close output stream. + out.peek(); + m_Stream.Reset(); + ret = m_Response; + m_Response.Reset(); } - _ASSERT(m_Response); - _ASSERT(m_Stream && m_Stream->IsInitialized()); - CConn_IOStream& out = m_Stream->GetConnStream(); - if ( have_data ) { - m_FormData->WriteFormData(out); - } - // Send data to the server and close output stream. - out.peek(); - m_Stream.Reset(); - CHttpResponse ret = *m_Response; - m_Response.Reset(); - return ret; + while (retry_processing(ret->Headers())); + + return *ret; } @@ -771,6 +899,20 @@ CHttpRequest& CHttpRequest::SetTimeout(unsigned int sec, } +CHttpRequest& CHttpRequest::SetDeadline(const CTimeout& deadline) +{ + m_Deadline = deadline; + return *this; +} + + +CHttpRequest& CHttpRequest::SetRetryProcessing(ESwitch on_off) +{ + m_RetryProcessing = on_off; + return *this; +} + + /////////////////////////////////////////////////////// // CHttpSession:: // diff --git a/c++/src/connect/ncbi_lbos.c b/c++/src/connect/ncbi_lbos.c index feb646f0..5de92597 100644 --- a/c++/src/connect/ncbi_lbos.c +++ b/c++/src/connect/ncbi_lbos.c @@ -24,6 +24,7 @@ * =========================================================================== * * Authors: Dmitriy Elisov + * Credits: Denis Vakatov * @file * File Description: * A client for service discovery API based on LBOS. @@ -38,7 +39,7 @@ #include "ncbi_priv.h" #include /* free, realloc, calloc, malloc */ #include /* isdigit */ - +#include "parson.h" #define kHostportStringLength (16+1+5)/**< strlen("255.255.255.255")+ strlen(":") + @@ -49,20 +50,24 @@ #define NCBI_USE_ERRCODE_X Connect_LBSM /**< Used in CORE_LOG*_X */ +#ifdef NCBI_COMPILER_MSVC +# define LBOS_STRTOK strtok_s +#else +# define LBOS_STRTOK strtok_r +#endif /*///////////////////////////////////////////////////////////////////////////// // STATIC VARIABLES // /////////////////////////////////////////////////////////////////////////////*/ -static const char* kRoleFile = "/etc/ncbi/role"; -static const char* kDomainFile = "/etc/ncbi/domain"; #ifdef NCBI_OS_MSWIN static const char* kLbosresolverFile = "C:\\Apps\\Admin_Installs\\etc" "\\ncbi\\lbosresolver"; #else static const char* kLbosresolverFile = "/etc/ncbi/lbosresolver"; #endif -static const char* kLBOSQuery = "/lbos/text/mlresolve?name="; +static const char* kLBOSQuery = "/lbos/v3/services/" + "?format=json&show=all&q="; /* * LBOS registry section for announcement @@ -73,13 +78,11 @@ static const char* kLBOSVersionVariable = "VERSION"; static const char* kLBOSServerHostVariable = "HOST"; static const char* kLBOSPortVariable = "PORT"; static const char* kLBOSHealthcheckUrlVariable = "HEALTHCHECK"; -static const char* kLBOSDomainVariable = "lbos_domain"; +static const char* kLBOSMetaVariable = "meta"; -static SConnNetInfo* s_EmptyNetInfo = NULL; /* Do.. */ -static char* s_LBOS_CurrentDomain = NULL; /* ..not.. */ -static char* s_LBOS_Lbosresolver = NULL; /* ..change.. */ -static char* s_LBOS_CurrentRole = NULL; /* ..after init */ +static SConnNetInfo* s_EmptyNetInfo = NULL; /* Do not change.. */ +static char* s_LBOS_Lbosresolver = NULL; /* ..after init */ static const int kInitialCandidatesCount = 1; /* For initial memory allocation */ static int s_LBOS_TurnedOn = 1; /* If LBOS cannot @@ -121,9 +124,9 @@ static void s_LBOS_Reset (SERV_ITER iter); static int/*bool*/ s_LBOS_Update (SERV_ITER iter, const char* text, int code); -static const char* s_LBOS_ReadDomain (void); -static const char* s_LBOS_ReadRole (void); +#if defined NCBI_OS_LINUX || defined NCBI_OS_MSWIN static const char* s_LBOS_ReadLbosresolver(void); +#endif /* defined NCBI_OS_LINUX || defined NCBI_OS_MSWIN */ static EHTTP_HeaderParse s_LBOS_ParseHeader (const char* header, void* /* SLBOS_UserData* */ @@ -140,6 +143,7 @@ unsigned short s_LBOS_Announce(const char* service, const char* host, unsigned short port, const char* healthcheck_url, + const char* meta, char** lbos_answer, char** http_status_message); @@ -150,7 +154,6 @@ unsigned short s_LBOS_Announce(const char* service, static SLBOS_Functions s_LBOS_funcs = { s_LBOS_ResolveIPPort ,CONN_Read - ,g_LBOS_ComposeLBOSAddress ,s_LBOS_FillCandidates ,s_LBOS_DestroyData ,s_LBOS_GetNextInfo @@ -347,7 +350,7 @@ static const SSERV_VTable s_lbos_op = { // GLOBAL CONVENIENCE FUNCTIONS // /////////////////////////////////////////////////////////////////////////////*/ /** Check C-string if it is not NULL and contains at least one symbol */ -int/*bool*/ g_LBOS_StringIsNullOrEmpty(const char* const str) +int/*bool*/ g_LBOS_StringIsNullOrEmpty(const char* str) { if ((str == NULL) || (strlen(str) == 0)) { return 1; @@ -402,7 +405,8 @@ const char* g_LBOS_strcasestr(const char* dest, const char* lookup) * g_LBOS_StringConcat(g_LBOS_StringConcat(str,to_app1,&len), to_app2,&len). * Value of data_length on first call should be 0. * @return - * 1 if success, 0 if error happened and dest was not changed */ + * reallocated dest on success, NULL if error happened and dest was + * not changed */ char* g_LBOS_StringConcat(char* dest, const char* to_append, size_t* dest_length) @@ -426,7 +430,8 @@ char* g_LBOS_StringConcat(char* dest, } realloc_result = (char*)realloc(dest, dest_length_local + append_len + 1); if (realloc_result == NULL) { - CORE_LOG(eLOG_Critical, "g_LBOS_StringConcat: No RAM. Returning NULL."); + CORE_LOG_X(eLBOS_MemAlloc, eLOG_Critical, + "g_LBOS_StringConcat: No RAM. Returning NULL."); free(dest); return NULL; } @@ -439,72 +444,8 @@ char* g_LBOS_StringConcat(char* dest, } return dest; } -#if 0 -/* Get "tag: value" pair from HTTP header */ -char* s_LBOS_GetHTTPHeader(const char* tag, const char* headers) -{ - char* tag_lwr = strlwr(strdup(tag)); - char* header_lwr = strlwr(strdup(headers)); - char* tag_start = header_lwr, *tag_end; - while (tag_start != NULL) - { - /* We move bit by bit */ - tag_start = strstr(tag_start, tag_lwr); - /* We want to be sure that found tag is the tag itself, - * not a value as if in "Some-Tag: tag: 2". So we check for - * either \n before tag, or it should be positioned at the very - * beginning of the string - */ - if ( - tag_start != NULL - && - ( - (*(tag_start - 1) == '\n') - || - (tag_start == header_lwr) - ) - ) - { - /* Look for the end of tag: value */ - while () - } - else { - tag_start = - - if (d) - } -} -char* g_LBOS_CombineDTabs(const char* primary_dtab, const char* secondary_dtab) -{ - char* primary_dtab, *primary_dtab_end, *new_dtab; - int length, primary_dtab_length; - primary_dtab += strlen("DTab-Local:"); - if (primary_dtab[1] == ' ') { - primary_dtab++; - } - /* Find end of line */ - primary_dtab_end = strchr(primary_dtab, '\n'); - if (primary_dtab_end[-1] == '\r') { - primary_dtab_end--; - } - /* Create new string that includes first DTabs from registry and then - * DTabs from HTTP requests */ - length = 0; - primary_dtab_length = primary_dtab_end - primary_dtab; - new_dtab = NULL; - new_dtab = g_LBOS_StringNConcat(g_LBOS_StringConcat( - g_LBOS_StringConcat(g_LBOS_StringConcat( - /*dest*/ /*to append*/ /*length*/ /*count*/ - new_dtab, "DTab-local: ", &length), - secondary_dtab, &length), - ";", &length), - primary_dtab, &length, primary_dtab_length); - return new_dtab; -} -#endif - char* g_LBOS_StringNConcat(char* dest, const char* to_append, size_t* dest_length, @@ -514,7 +455,7 @@ char* g_LBOS_StringNConcat(char* dest, char* result; if (buf == NULL) { - CORE_LOG(eLOG_Critical, + CORE_LOG_X(eLBOS_MemAlloc, eLOG_Critical, "g_LBOS_StringConcat: No RAM. Returning NULL."); free(buf); free(dest); @@ -539,7 +480,8 @@ char* g_LBOS_RegGet(const char* section, char* buf = (char*)malloc(totalBufSize * sizeof(char)); if (buf == NULL) { - CORE_LOG(eLOG_Critical, "g_LBOS_RegGet: No RAM. Returning NULL."); + CORE_LOG_X(eLBOS_MemAlloc, eLOG_Critical, + "g_LBOS_RegGet: No RAM. Returning NULL."); return buf; } for (;;) { @@ -552,10 +494,9 @@ char* g_LBOS_RegGet(const char* section, then add space to buffer */ realloc_result = (char*)realloc(buf, sizeof(char)*(totalBufSize * 2)); if (realloc_result == NULL) { - CORE_LOG(eLOG_Warning, "g_LBOS_RegGet: Buffer " - "overflow while reading from " - "registry. Returning string at its " - "maximum size"); + CORE_LOG_X(eLBOS_MemAlloc, eLOG_Warning, + "g_LBOS_RegGet: Buffer overflow while reading from " + "registry. Returning string at its maximum size"); return buf; } else { buf = realloc_result; @@ -566,33 +507,6 @@ char* g_LBOS_RegGet(const char* section, } -/** We compose LBOS hostname based on /etc/ncbi/domain and /etc/ncbi/role. */ -char* g_LBOS_ComposeLBOSAddress(void) -{ - char* site = NULL; - size_t length = 0; - const char *role = s_LBOS_ReadRole(), - *domain = s_LBOS_ReadDomain(); - - if (role == NULL || domain == NULL) { - return NULL; - } - site = g_LBOS_StringConcat(g_LBOS_StringConcat( - g_LBOS_StringConcat(g_LBOS_StringConcat( - /* dest */ /* to append */ /* length */ - site, "lbos.", &length), - role, &length), - ".", &length), - domain, &length); - if (site == NULL) { - CORE_LOG(eLOG_Warning, "s_LBOS_ComposeLBOSAddress: " - "memory allocation failed"); - return NULL; - } - return site; -} - - /** Checks iterator, fact that iterator belongs to this mapper, iterator data. * Only debug function. */ int/*bool*/ g_LBOS_CheckIterator(SERV_ITER iter, @@ -619,53 +533,6 @@ int/*bool*/ g_LBOS_CheckIterator(SERV_ITER iter, } -/** Given address to LBOS instance, check if it resides in the same domain - * (be-md, st-va, ac-va, or-wa) as current machine */ -int/*bool*/ g_LBOS_CheckDomain(const char* lbos_address) -{ - return 1; /* we do not check domain */ - /* Though we cannot be 100% sure that sequence of numbers and dots is IP, - * it is what we hope for */ - int/*bool*/ is_ip = 1; - unsigned short int i; - for (i = 0; i < strlen(lbos_address); i++) { - if (!isdigit(lbos_address[i]) && lbos_address[i] != '.') { - is_ip = 0; - } - } - /* The check now is really simple - it searches for known domains in the - * provided address. If domain is omitted in address - then we deny such - * address, just in case. If address contains - * non-standard domain - check will not work. */ - if ( !is_ip - /* && - ( - (strstr(lbos_address, ".be-md.") != NULL) - || - (strstr(lbos_address, ".st-va.") != NULL) - || - (strstr(lbos_address, ".or-wa.") != NULL) - || - (strstr(lbos_address, ".ac-va.") != NULL) - ) */ - && - ( - !g_LBOS_StringIsNullOrEmpty(s_LBOS_ReadDomain()) - ) - && - ( - strcmp(s_LBOS_ReadDomain(), "*") != 0 - ) - ) - { - /* If we can perform check, we return result of check */ - return (strstr(lbos_address, s_LBOS_ReadDomain()) != NULL); - } - /* If we cannot perform check, we allow any domain */ - return 1; -} - - /** This function is needed to get LBOS hostname in different situations. * @param priority_find_method[in] * The first method to try to find LBOS. If it fails, default order of @@ -676,24 +543,26 @@ int/*bool*/ g_LBOS_CheckDomain(const char* lbos_address) * 3) LBOS for current /etc/ncbi/{role, domain}. * To not specify default method, use eLBOSFindMethod_None. * @param lbos_addr[in] - * If priority_find_method is eLBOSFindMethod_CustomHost, then LBOS is + * If priority_find_method is eLBOS_FindMethod_CustomHost, then LBOS is * first looked for at hostname:port specified in this variable. */ char* g_LBOS_GetLBOSAddressEx (ELBOSFindMethod priority_find_method, const char* lbos_addr) { +#if defined NCBI_OS_LINUX || defined NCBI_OS_MSWIN const char* lbosaddress = NULL; /* for const strings */ +#endif /* defined NCBI_OS_LINUX || defined NCBI_OS_MSWIN */ char* lbosaddress_temp = NULL; /* for non-const strings */ char* address = NULL; /* List of methods used, in their order */ ELBOSFindMethod find_method_order[] = { priority_find_method /* eLBOSFindMethod_None, if not specified*/ - , eLBOSFindMethod_Registry - , eLBOSFindMethod_Lbosresolve + , eLBOS_FindMethod_Registry + , eLBOS_FindMethod_Lbosresolve }; size_t find_method_iter; size_t find_method_count = sizeof(find_method_order) / sizeof(ELBOSFindMethod); - CORE_LOG_X(1, eLOG_Trace, "Getting LBOS addresses..."); + CORE_LOG(eLOG_Trace, "Getting LBOS addresses..."); /* Iterate through methods of finding LBOS address */ for (find_method_iter = 0; find_method_iter < find_method_count; @@ -705,7 +574,7 @@ char* g_LBOS_GetLBOSAddressEx (ELBOSFindMethod priority_find_method, switch (find_method_order[find_method_iter]) { case eLBOSFindMethod_None : break; - case eLBOSFindMethod_CustomHost : + case eLBOS_FindMethod_CustomHost : if (g_LBOS_StringIsNullOrEmpty(lbos_addr)) { CORE_LOG_X(1, eLOG_Warning, "Use of custom LBOS address was " "asked for, but no custom address was supplied. " @@ -718,7 +587,7 @@ char* g_LBOS_GetLBOSAddressEx (ELBOSFindMethod priority_find_method, "LBOS address. Probably insufficient RAM."); } break; - case eLBOSFindMethod_Lbosresolve : + case eLBOS_FindMethod_Lbosresolve : #if defined NCBI_OS_LINUX || defined NCBI_OS_MSWIN lbosaddress = s_LBOS_ReadLbosresolver(); if (g_LBOS_StringIsNullOrEmpty(lbosaddress)) { @@ -727,9 +596,9 @@ char* g_LBOS_GetLBOSAddressEx (ELBOSFindMethod priority_find_method, } else { address = strdup(lbosaddress); } -#endif +#endif /* defined NCBI_OS_LINUX || defined NCBI_OS_MSWIN */ break; - case eLBOSFindMethod_Registry: + case eLBOS_FindMethod_Registry: lbosaddress_temp = g_LBOS_RegGet("CONN", "lbos", NULL); if (g_LBOS_StringIsNullOrEmpty(lbosaddress_temp)) { CORE_LOG_X(1, eLOG_Warning, "Trying to find LBOS in " @@ -758,6 +627,7 @@ char* g_LBOS_GetLBOSAddress(void) /*///////////////////////////////////////////////////////////////////////////// // STATIC CONVENIENCE FUNCTIONS // /////////////////////////////////////////////////////////////////////////////*/ +#if 0 /* deprecated, remove on or after July 9 2016 */ /** Get role of current host. Returned string is read-only, may reside in * 'data' memory area */ static const char* s_LBOS_ReadRole() @@ -829,155 +699,114 @@ static const char* s_LBOS_ReadRole() return s_LBOS_CurrentRole; } +#endif /* 0 */ -/** Get domain of current host. Do not modify or clear the returned string! - * Returned string is read-only, may reside in 'data' memory area */ -static const char* s_LBOS_ReadDomain() -{ - /* - * If no domain has been previously read, fill it - */ - if (s_LBOS_CurrentDomain == NULL) { - char* registry_domain = NULL; /* if registry has domain specified - * for LBOS First, we check registry - * and then if nothing there, we check - * /etc/ncbi/domain */ - registry_domain = g_LBOS_RegGet("CONN", kLBOSDomainVariable, NULL); - CORE_LOCK_WRITE; - if (!g_LBOS_StringIsNullOrEmpty(registry_domain) - && s_LBOS_CurrentDomain == NULL) - { - s_LBOS_CurrentDomain = registry_domain; - } else { - free(registry_domain); - } - CORE_UNLOCK; - if (s_LBOS_CurrentDomain != NULL) - return s_LBOS_CurrentDomain; - -#ifdef NCBI_OS_LINUX - else { /* If nothing found in registry, check /etc/ncbi/domain */ - FILE* domain_file; - size_t len; - char str[kMaxLineSize]; - char* read_result; /* during function will become equal either NULL - or str, do not free() */ - if ((domain_file = fopen(kDomainFile, "r")) == NULL) { - CORE_LOGF(eLOG_Warning, ("s_LBOS_ReadDomain: " - "could not open domain file %s", - kDomainFile)); - return NULL; - } - read_result = fgets(str, sizeof(str), domain_file); - fclose(domain_file); - if (read_result == NULL) { - CORE_LOG(eLOG_Warning, "s_LBOS_ReadDomain: " - "memory allocation failed"); - return NULL; - } - len = strlen(str); - assert(len); - /*We remove unnecessary '/n' and probably '/r' */ - if (str[len - 1] == '\n') { - if (--len && str[len - 1] == '\r') - --len; - str[len] = '\0'; - } - if (g_LBOS_StringIsNullOrEmpty(str)) { - /* No domain recognized */ - CORE_LOGF(eLOG_Warning, - ("s_LBOS_ComposeLBOSAddress: domain file" - "%s is empty, skipping this method", - kDomainFile)); - free(read_result); - return NULL; - } - CORE_LOCK_WRITE; - /* Check one more time that no other thread managed to fill - * static variable ahead of this thread. If this happened, - * release memory */ - if (s_LBOS_CurrentDomain == NULL) - s_LBOS_CurrentDomain = strdup(str); - CORE_UNLOCK; - } -#endif /* #ifdef NCBI_OS_LINUX */ - } - return s_LBOS_CurrentDomain; -} - - -/** Get domain of current host. Do not modify or clear the returned string! - * Returned string is read-only, may reside in 'data' memory area */ +#if defined NCBI_OS_LINUX || defined NCBI_OS_MSWIN +/** Read contents of lbosresolver + * + * @warning + * Do not modify or clear the returned string! Returned string is + * read-only + */ static const char* s_LBOS_ReadLbosresolver(void) { -#ifdef NCBI_OS_LINUX - if (s_LBOS_Lbosresolver == NULL) { - FILE* lbosresolver_file; - size_t len; - char str[kMaxLineSize]; - char* read_result; /* during function will become equal either NULL - or str, do not free() */ - if ((lbosresolver_file = fopen(kLbosresolverFile, "r")) == NULL) { - CORE_LOGF(eLOG_Warning, ("LBOS mapper: " - "could not open lbosresolve file %s", - kLbosresolverFile)); - return NULL; - } - read_result = fgets(str, sizeof(str), lbosresolver_file); - fclose(lbosresolver_file); - if (read_result == NULL) { - CORE_LOG(eLOG_Warning, "s_LBOS_ReadLBOSResolve: " - "memory allocation failed"); - return NULL; - } - len = strlen(str); - assert(len); - /*We remove unnecessary '/n' and probably '/r' */ - if (str[len - 1] == '\n') { - if (--len && str[len - 1] == '\r') - --len; - str[len] = '\0'; - } - if (g_LBOS_StringIsNullOrEmpty(str)) { - /* No domain recognized */ - CORE_LOGF(eLOG_Warning, - ("LBOS mapper: /etc/ncbi/lbosresolve file" - "%s is empty, no LBOS address available", - kLbosresolverFile)); - free(read_result); - return NULL; + if (s_LBOS_Lbosresolver != NULL) { + return s_LBOS_Lbosresolver; + } + + FILE* lbosresolver_file; + size_t len; + char str[kMaxLineSize]; + char* read_result; /* during function will become equal either NULL + or str, do not free() */ + if ((lbosresolver_file = fopen(kLbosresolverFile, "r")) == NULL) { + CORE_LOGF(eLOG_Warning, ("LBOS mapper: " + "could not open file %s", + kLbosresolverFile)); + return NULL; + } + read_result = fgets(str, sizeof(str), lbosresolver_file); + fclose(lbosresolver_file); + if (read_result == NULL) { + CORE_LOG(eLOG_Warning, "s_LBOS_ReadLBOSResolve: " + "memory allocation failed"); + return NULL; + } + len = strlen(str); + assert(len); + if (g_LBOS_StringIsNullOrEmpty(str)) { + /* No domain recognized */ + CORE_LOGF(eLOG_Warning, + ("LBOS mapper: file %s is empty, no LBOS address available", + kLbosresolverFile)); + free(read_result); + return NULL; + } + /*We remove unnecessary '/n' and probably '/r' */ + if (str[len - 1] == '\n') { + if (--len && str[len - 1] == '\r') { + --len; } - CORE_LOCK_WRITE; - /* Check one more time that no other thread managed to fill - * static variable ahead of this thread. If this happened, - * release memory */ - if (s_LBOS_Lbosresolver == NULL) - /* We skip "http://" and "/lbos" */ - str[strlen(str) - strlen("/lbos")] = '\0'; - s_LBOS_Lbosresolver = strdup(str + 7); - CORE_UNLOCK; + str[len] = '\0'; } -#endif /* #ifdef NCBI_OS_LINUX */ + CORE_LOCK_WRITE; + /* Check one more time that no other thread managed to fill + * static variable ahead of this thread. If this happened, + * release memory */ + if (s_LBOS_Lbosresolver == NULL) + /* We skip "http://" and "/lbos" */ + str[strlen(str) - strlen("/lbos")] = '\0'; + s_LBOS_Lbosresolver = strdup(str + 7); + CORE_UNLOCK; + return s_LBOS_Lbosresolver; } +#endif /* defined NCBI_OS_LINUX || defined NCBI_OS_MSWIN */ -/** Takes original string and returns URL-encoded string. Original string - * is untouched. +/** Take original string and return URL-encoded string. + * @attention + * Original string is untouched. Caller is responsible for freeing + * allocated space. */ -char* s_LBOS_URLEncode (const char* to_encode) +static char* s_LBOS_URLEncode (const char* to_encode) { /* If all symbols are escape, our string will take triple space */ size_t encoded_string_buf_size = strlen(to_encode)*3 + 1; char* encoded_string = (char*)calloc(encoded_string_buf_size, sizeof(char)); - size_t src_read, dst_written; /*strange things needed by URL_Encode*/ + size_t src_read, dst_written; /* strange things needed by URL_Encode */ URL_Encode(to_encode, strlen(to_encode), &src_read, encoded_string, encoded_string_buf_size, &dst_written); return encoded_string; } +/** Function to convert legacy service names for LBOS. + * Takes service name and if it does not start with '/', prepends "/Legacy" + * to it. + * @attention + * Original string is untouched. Caller is responsible for freeing + * allocated space. + * @warning + * to_modify MUST be a valid non-empty C-string + */ +char* s_LBOS_ModifyServiceName (const char* to_modify) +{ + /* If all symbols are escape, our string will take triple space */ + static const char* prefix = "/Legacy/"; + if (to_modify[0] == '/') + return strdup(to_modify); + /* We deal with legacy service name. First, get "/Legacy/" prefix, then + * change to_modify to lower register, concatenate them and return */ + char* modified_str = strdup(prefix); + char* service_lwr = strlwr(strdup(to_modify)); + modified_str = g_LBOS_StringConcat(modified_str, service_lwr, NULL); + free(service_lwr); + return modified_str; +} + + /** @brief Just connect and return connection * * Internal function to create connection, which simplifies process @@ -1045,8 +874,9 @@ static char * s_LBOS_UrlReadAll(SConnNetInfo* net_info, size_t totalBufSize; char* realloc_result; - /* Not to handle case when status_code is NULL, we use internal variable, - and only try to set status_code in the end of this function */ + /* Not to handle case when 'status_code' is NULL, we use internal variable, + * and only try to set 'status_code' in the end of this function (and if it + * is NULL, we do not set it) */ user_data.http_response_code = 0; /* The same for status_message */ user_data.http_status_mesage = NULL; @@ -1098,24 +928,7 @@ static char * s_LBOS_UrlReadAll(SConnNetInfo* net_info, totalRead += bytesRead; buf[totalRead] = 0; /* force end of string */ -#if 0 - /* If we have read enough and use PUT or DELETE methods, - * exit this loop */ - if ( - totalRead >= user_data.content_length - /*&& - ( net_info->req_method == eReqMethod_Put - || - net_info->req_method == eReqMethod_Delete - )*/ - ) - { - CONN_Flush(conn); - CONN_SetTimeout(conn, eIO_Close, &kLBOSZeroTimeout); - SOCK_CloseEx(sock, 0/*retain SOCK*/); - break; - } -#endif + /* IF we still have to read - then add space to buffer, if needed */ if ( status == eIO_Success && totalBufSize < totalRead * 2 ) { @@ -1150,7 +963,7 @@ static char * s_LBOS_UrlReadAll(SConnNetInfo* net_info, * Uses LBZK at specified IP and port. */ static SSERV_Info** s_LBOS_ResolveIPPort(const char* lbos_address, - const char* serviceName, + const char* service_name, SConnNetInfo* net_info) { SSERV_Info** infos; @@ -1165,10 +978,6 @@ static SSERV_Info** s_LBOS_ResolveIPPort(const char* lbos_address, size_t user_dtab_length; char* new_dtab = NULL; char* user_dtab_end; - char* token = NULL, *saveptr = NULL, *str = NULL, *opt_param = NULL; -#ifdef _DEBUG - char hostport[kHostportStringLength]; //just for debug -#endif /* Allocate space for answer (will be expanded later, if needed) */ infos = (SSERV_Info**)calloc(2, sizeof(SSERV_Info*)); if (infos == NULL) { @@ -1183,8 +992,7 @@ static SSERV_Info** s_LBOS_ResolveIPPort(const char* lbos_address, /* First, we look if there is DTab-Local already in header*/ char* old_header = net_info->http_user_header ? strdup(net_info->http_user_header) : NULL; - user_dtab = g_LBOS_strcasestr(net_info->http_user_header, - "DTab-local:"); + user_dtab = g_LBOS_strcasestr(net_info->http_user_header, "DTab-local:"); /* If there is an already defined local DTab, we mix it with one from * registry */ if (user_dtab != NULL) @@ -1224,10 +1032,10 @@ static SSERV_Info** s_LBOS_ResolveIPPort(const char* lbos_address, ConnNetInfo_OverrideUserHeader(net_info, new_dtab); free(new_dtab); } - servicename_url_encoded = s_LBOS_URLEncode(serviceName); - /*encode service name to url encoding (change ' ' to %20, '/' to %2f, etc.)*/ - url_length = strlen("http://") + strlen(lbos_address) + - strlen(kLBOSQuery) + strlen(servicename_url_encoded); + servicename_url_encoded = s_LBOS_ModifyServiceName(service_name); + /*encode service name to url encoding (change ' ' to %20, '/' to %2f, etc.)*/ + url_length = strlen("http://") + strlen(lbos_address) + + strlen(kLBOSQuery) + strlen(servicename_url_encoded); url = (char*)malloc(sizeof(char) * url_length + 1); /** to make up LBOS query URI to connect*/ if (url == NULL) @@ -1252,53 +1060,90 @@ static SSERV_Info** s_LBOS_ResolveIPPort(const char* lbos_address, free(infos); return NULL; } - /* - * We read all the answer, find host:port in the answer and fill - * 'hostports', occasionally reallocating array, if needed - */ - for (str = lbos_answer ; ; str = NULL) { - SSERV_Info * info; -#ifdef NCBI_COMPILER_MSVC - token = strtok_s(str, "\n", &saveptr); -#else - token = strtok_r(str, "\n", &saveptr); -#endif - if (token == NULL) { - break; - } - if ((opt_param = strstr(token, " | ")) != NULL) { - *opt_param = 0; + x_JSON_Value *root_value; + x_JSON_Object *root_obj; + x_JSON_Object *services; + x_JSON_Array *serviceEndpoints; + x_JSON_Object *serviceEndpoint; + unsigned int j = 0; + root_value = x_json_parse_string(lbos_answer); + if (x_json_value_get_type(root_value) != JSONObject) { + goto clean_and_exit; + } + root_obj = x_json_value_get_object(root_value); + services = x_json_object_get_object(root_obj, "services"); + /* Get endpoints for the first service name. + * Note: Multiple service resolution is not supported intentionally + * (yet). */ + serviceEndpoints = + x_json_object_get_array(services, x_json_object_get_name(services, 0)); + /* Iterate through endpoints */ + for (j = 0; j < x_json_array_get_count(serviceEndpoints); j++) { + const char *host, *rate, *extra, *type; + char* server_description; + const char* descr_format = "%s %s:%u %s Regular R=%s L=no T=25"; + int port; + serviceEndpoint = x_json_array_get_object(serviceEndpoints, j); + host = x_json_object_dotget_string(serviceEndpoint, + "serviceEndpoint.host"); + if (host == NULL) { + continue; } - info = SERV_ReadInfoEx(token, serviceName, 0); - /* Occasionally, the info returned by LBOS can be invalid. */ + port = (int)x_json_object_dotget_number(serviceEndpoint, + "serviceEndpoint.port"); + /* -------------rate------------- */ + rate = x_json_object_dotget_string(serviceEndpoint, + "meta.rate"); + rate = !g_LBOS_StringIsNullOrEmpty(rate) ? rate : "1"; + /* -------------type------------- */ + type = x_json_object_dotget_string(serviceEndpoint, + "meta.type"); + type = !g_LBOS_StringIsNullOrEmpty(type) ? type : "STANDALONE"; + /* -------------extra------------- */ + extra = x_json_object_dotget_string(serviceEndpoint, + "meta.extra"); + extra = !g_LBOS_StringIsNullOrEmpty(extra) ? extra : ""; + + /* Examples: + HTTP - accn2gi + DNS - alndbasn_lb + STANDALONE - aligndb_dbldd + HTTP_POST - taxservice3test + NCBID - taxservice/mapviewaugust2011*/ + size_t length; /* used to count size to allocate for server_description, + and then for g_LBOS_StringConcat*/ + /* Occasionally, we are not able to allocate memory */ + length = strlen(descr_format) + strlen(type) + strlen(host) + + 5 /*length of port*/ + strlen(extra) + strlen(rate); + server_description = malloc(sizeof(char) * length); + sprintf(server_description, descr_format, type, host, + port, extra, rate); + SSERV_Info * info = SERV_ReadInfoEx(server_description,service_name, 0); + free(server_description); if (info == NULL) { continue; } - /* We check if we have at least two more places: one for current - * info and one for finalizing NULL - */ if (infos_capacity <= infos_count + 1) { - SSERV_Info** realloc_result = (SSERV_Info**)realloc(infos, - sizeof(SSERV_Info*) * (infos_capacity*2 + 1)); + SSERV_Info** realloc_result = + (SSERV_Info**)realloc(infos, sizeof(SSERV_Info*) * + (infos_capacity*2 + 1)); if (realloc_result == NULL) { - /* If error with realloc, return as much as could allocate - * for*/ - infos_count--; /*Will just rewrite last info with NULL to - mark end of array*/ + /* If error with realloc, return as much as could + * allocate for */ + infos_count--; /* Will just rewrite last info with NULL + * to mark end of array*/ + free(info); break; - } else { /*If realloc successful */ + } else { /* If realloc successful */ infos = realloc_result; infos_capacity = infos_capacity*2 + 1; } } infos[infos_count++] = info; -#ifdef _DEBUG - SOCK_HostPortToString(info->host, info->port, hostport, - kHostportStringLength); - /*Copy IP from stream to the result char array*/ - CORE_LOGF(eLOG_Note, ("Resolved [%s] to [%s]", serviceName, hostport)); -#endif } + +clean_and_exit: + x_json_value_free(root_value); free(lbos_answer); /* Shuffle list with Durstenfeld's shuffle algorithm * (also credits go to Fisher and Yates, and Knuth) */ @@ -1406,6 +1251,11 @@ static int s_LBOS_CheckAnnounceArgs(const char* service, if (!g_LBOS_StringIsNullOrEmpty(host)) { for (i = 0; i < strlen(host); i++) { if (!isalnum(host[i]) && (host[i] != '.')) { + CORE_LOG(eLOG_Critical, "Error with announcement, " + "ip has incorrect format " + "(only digits and dots are allowed). " + "Please provide resolved IP to " + "avoid this error"); return 0; } } @@ -1433,9 +1283,9 @@ static int s_LBOS_CheckAnnounceArgs(const char* service, } -static int s_LBOS_CheckDeannounceArgs(const char* service, - const char* version, - const char* host, +static int s_LBOS_CheckDeannounceArgs(const char* service, + const char* version, + const char* host, unsigned short port) { if (!g_LBOS_StringIsNullOrEmpty(host) && strstr(host, ":") != NULL) { @@ -1485,30 +1335,18 @@ static unsigned short s_LBOS_PerformRequest(const char* request, * return error code. If we receive nothing (LBOS is not present), then * we save nothing. */ - net_info = ConnNetInfo_Clone(s_EmptyNetInfo); - net_info->req_method = req_method; - buf = NULL; - status_code = 0; - lbos_address = s_LBOS_Instance; - /* We deny foreign de-announcement*/ - /* Compare local domain and LBOS domain */ - if (!g_LBOS_CheckDomain(lbos_address)) { - CORE_LOGF_X(1, eLOG_Error, - ("Could not verify that [%s] is in local domain [%s]. " - "Announcement in foreign domain is not allowed. " - "If you omitted [%s] in the LBOS address - please, " - "provide it.", - lbos_address, s_LBOS_ReadDomain(), s_LBOS_ReadDomain())); - } - else { /* domain is good */ - query = g_LBOS_StringConcat(g_LBOS_StringConcat( - strdup("http://"), lbos_address, &length), - request, &length); - length = strlen(query); - buf = s_LBOS_UrlReadAll(net_info, query, &status_code, - &status_message); - free(query); - } + net_info = ConnNetInfo_Clone(s_EmptyNetInfo); + net_info->req_method = req_method; + buf = NULL; + status_code = 0; + lbos_address = s_LBOS_Instance; + query = g_LBOS_StringConcat(g_LBOS_StringConcat( + strdup("http://"), lbos_address, &length), + request, &length); + length = strlen(query); + buf = s_LBOS_UrlReadAll(net_info, query, &status_code, + &status_message); + free(query); if (lbos_answer != NULL && !g_LBOS_StringIsNullOrEmpty(buf)) { *lbos_answer = strdup(buf); } @@ -1519,14 +1357,18 @@ static unsigned short s_LBOS_PerformRequest(const char* request, free(status_message); if (status_code == 0) { - status_code = kLBOSNoLBOS; + status_code = eLBOS_LbosNotFound; } /* Cleanup */ ConnNetInfo_Destroy(net_info); return status_code; } - +/** Find "0.0.0.0" in healthcheck_url and replace it with IP of current host + * @attention + * Original string is untouched. Caller is responsible for freeing + * allocated space. + */ static char* s_LBOS_Replace0000WithIP(const char* healthcheck_url) { size_t chars_to_copy; @@ -1535,6 +1377,7 @@ static char* s_LBOS_Replace0000WithIP(const char* healthcheck_url) size_t length; /* new url with replaced "0.0.0.0" (if needed) */ char* my_healthcheck_url; + unsigned int local_host_ip; const char* replace_pos; /* to check if there is 0.0.0.0 */ if (healthcheck_url == NULL) return NULL; @@ -1553,8 +1396,7 @@ static char* s_LBOS_Replace0000WithIP(const char* healthcheck_url) } chars_to_copy = replace_pos - healthcheck_url; query = replace_pos + strlen("0.0.0.0"); - unsigned int local_host_ip = - g_LBOS_UnitTesting_GetLBOSFuncs()->LocalHostAddr(eDefault); + local_host_ip = g_LBOS_UnitTesting_GetLBOSFuncs()->LocalHostAddr(eDefault); if (local_host_ip == 0) { CORE_LOG(eLOG_Warning, "Error with announcement, cannot find local IP."); @@ -1562,7 +1404,7 @@ static char* s_LBOS_Replace0000WithIP(const char* healthcheck_url) return NULL; } SOCK_HostPortToString(local_host_ip, 0, hostname, kMaxLineSize - 1); - if (hostname == NULL) { + if (strlen(hostname) == 0) { CORE_LOG(eLOG_Warning, "Error with announcement, cannot find local IP."); free(my_healthcheck_url); @@ -1579,6 +1421,17 @@ static char* s_LBOS_Replace0000WithIP(const char* healthcheck_url) } +static int s_TurnOn() +{ + if (s_LBOS_Init == 0) { + s_LBOS_funcs.Initialize(); + } + if (s_LBOS_TurnedOn == 0) { + return 0; + } + return 1; +} + /*///////////////////////////////////////////////////////////////////////////// // UNIT TESTING // /////////////////////////////////////////////////////////////////////////////*/ @@ -1620,26 +1473,6 @@ char** g_LBOS_UnitTesting_Instance(void) } -/** Pointer to s_LBOS_CurrentDomain - * @return - * address of static variable s_LBOS_CurrentDomain. - * @see */ -char** g_LBOS_UnitTesting_CurrentDomain(void) -{ - return &s_LBOS_CurrentDomain; -} - - -/** Pointer to s_LBOS_CurrentRole - * @return - * address of static variable s_LBOS_CurrentRole. - * @see */ -char** g_LBOS_UnitTesting_CurrentRole(void) -{ - return &s_LBOS_CurrentRole; -} - - /** Pointer to s_LBOS_CurrentRole * @return * address of static variable s_LBOS_CurrentRole. @@ -1661,29 +1494,20 @@ int/*bool*/ g_LBOS_UnitTesting_SetLBOSFindMethod (SERV_ITER iter, } -int/*bool*/ g_LBOS_UnitTesting_SetLBOSRoleDomainResolverFile - (const char* roleFile, - const char* domainFile, - const char* lbosresolverfile) +int/*bool*/ g_LBOS_UnitTesting_SetLBOSResolverFile(const char* resolverfile) { - if (roleFile != NULL) { - kRoleFile = roleFile; - } - if (domainFile != NULL) { - kDomainFile = domainFile; - } - if (lbosresolverfile != NULL) { - kLbosresolverFile = lbosresolverfile; + if (resolverfile != NULL) { + kLbosresolverFile = resolverfile; + return 1; } - return 1; + return 0; } -/* UNIT TESTING*/ -/** Set custom address for LBOS. Can be both hostname:port and IP:port. - * Intended mostly for testing. - * @param[in] iter - * Where to set address for LBOS. The settings is made for only one iterator*/ +/** Set custom address for LBOS. Can be either hostname:port or IP:port. + * Intended mostly for testing. + * @param[in] iter + * Where to set address for LBOS. Change is made only for this iterator */ int/*bool*/ g_LBOS_UnitTesting_SetLBOSaddress (SERV_ITER iter, char* address) { SLBOS_Data* data; assert(g_LBOS_CheckIterator(iter, ELBOSIteratorCheckType_MustHaveData)); @@ -2052,10 +1876,7 @@ const SSERV_VTable* SERV_LBOS_Open( SERV_ITER iter, SLBOS_Data* data; char* new_name = NULL; /* if we need to add dbaf */ const char* orig_serv_name = iter->name; /* we may modify name with dbaf */ - if (s_LBOS_Init == 0) { - s_LBOS_funcs.Initialize(); - } - if (s_LBOS_TurnedOn == 0) { + if (!s_TurnOn()) { return NULL; } /* @@ -2169,6 +1990,9 @@ unsigned short s_LBOS_Announce(const char* service, const char* host, unsigned short port, const char* healthcheck_url, +#ifdef LBOS_METADATA + const char* meta_args, +#endif /* LBOS_METADATA */ /* lbos_answer is never NULL */ char** lbos_answer, char** http_status_message) @@ -2182,122 +2006,116 @@ unsigned short s_LBOS_Announce(const char* service, const char* query_format = NULL; char* buf = NULL; /* for answer from LBOS */ int parsed_symbols = 0; - size_t length; + assert(!g_LBOS_StringIsNullOrEmpty(host)); + + if (!s_TurnOn()) + return eLBOS_Disabled; - if (s_LBOS_Init == 0) { - s_LBOS_funcs.Initialize(); - } - if (s_LBOS_TurnedOn == 0) { - return kLBOSOff; - } lbos_address = s_LBOS_Instance; status_code = 0; status_message = NULL; net_info = ConnNetInfo_Clone(s_EmptyNetInfo); - net_info->req_method = eReqMethod_Post; - query_format = "http://%s/lbos/json/announce?name=%s&" - "version=%s&port=%hu&check=%s"; + net_info->req_method = eReqMethod_Put; + /* Format for announcement request. "ip" parameter is optional and + * will be added separately, if provided */ + query_format = "http://%s/lbos/v3/services%s?version=%s&" + "port=%hu&" + "check=%s&" + "ip=%s&" + "format=json"; /* * Let's try announce */ char* query; - /* We deny foreign announcement*/ - /* Compare local domain and LBOS domain */ - if (!g_LBOS_CheckDomain(lbos_address)) { - CORE_LOGF_X(1, eLOG_Warning, - ("[%s] is not from local domain [%s]. " - "Announcement in foreign domain is not allowed.", - lbos_address, s_LBOS_ReadDomain())); - } else { - query = (char*)calloc(strlen(query_format) + - strlen(lbos_address) + - strlen(service) + strlen(version) + - 5/* port */ + strlen(healthcheck_url), - sizeof(char)); - sprintf(query, - query_format, - lbos_address, service, version, port, healthcheck_url); - length = strlen(query); - /* If host was provided, we append it to query */ - if (!g_LBOS_StringIsNullOrEmpty(host)) { - query = g_LBOS_StringConcat(g_LBOS_StringConcat( - query, "&ip=", &length), - host, &length); - } - buf = s_LBOS_UrlReadAll(net_info, query, &status_code, - &status_message); - free(query); + /* We do not count extra 1 byte for \0 because we still have extra + * bytes because of %s placeholders in query_format */ + query = (char*)calloc(strlen(query_format) + + strlen(lbos_address) + + strlen(service) + strlen(version) + + 5/* port */ + strlen(healthcheck_url) + + strlen(host), + sizeof(char)); + sprintf(query, query_format, + lbos_address, service, version, port, healthcheck_url, host); + if (!g_LBOS_StringIsNullOrEmpty(meta_args)) { + query = g_LBOS_StringConcat(g_LBOS_StringConcat( + query, "&", NULL), + meta_args, NULL); } + buf = s_LBOS_UrlReadAll(net_info, query, &status_code, &status_message); + free(query); if (!g_LBOS_StringIsNullOrEmpty(buf)) { + /* If this function is not able to parse LBOS output, original LBOS + * response will be available to the caller. Otherwise, content of + * lbos_answer will be replaced with parsed IP address of LBOS watcher + * a bit later */ *lbos_answer = strdup(buf); } if (http_status_message != NULL && status_message != NULL) { *http_status_message = strdup(status_message); } free(status_message); - /* If no LBOS found */ - if (status_code == 0) { + switch (status_code) { + case 0: + /* If no LBOS found */ CORE_LOG(eLOG_Warning, "Announce failed. No LBOS found."); - status_code = kLBOSNoLBOS; - goto clear_and_exit; - } - /* If announced server has broken healthcheck */ - if (status_code == kLBOSNotFound || status_code == kLBOSBadRequest - || status_code == kLBOSServerError) - { + status_code = eLBOS_LbosNotFound; + break; + case eLBOS_NotFound: case eLBOS_BadRequest: case eLBOS_Server: + /* If announced server has a broken healthcheck */ CORE_LOGF(eLOG_Warning, ("Announce failed. " "LBOS returned error code %d.", status_code)); - goto clear_and_exit; - } - /* If we could not announce, it is really bad */ - if (status_code != 200) { + break; + case eLBOS_Success: + /* If we announced successfully and status_code is 200, + * let's extract LBOS address */ + lbos_addr = (char*)calloc(kMaxLineSize, sizeof(char)); /* will not be + * free()'d */ + if (lbos_addr == NULL) { + CORE_LOG(eLOG_Warning, "Failed memory allocation. Most likely, " + "not enough RAM."); + status_code = eLBOS_MemAlloc; + break; + } + if (buf != NULL) { + parsed_symbols = sscanf(buf, "{\"watcher\":\"%[^\"]\"}", + lbos_addr); + } + if (parsed_symbols != 1) { + CORE_LOG(eLOG_Warning, "g_LBOS_Announce: LBOS answered 200 OK, but " + "output could not be parsed"); + free(lbos_addr); + status_code = eLBOS_Protocol; + break; + } + /* If announce finished with success, we parsed it to extract LBOS + * ip:port. We free() original output and replace it with ip:port */ + free(*lbos_answer); + *lbos_answer = lbos_addr; + /* If we could not announce, it is really bad */ + break; + default: CORE_LOGF(eLOG_Warning, ("Announce failed. " "LBOS returned error code %d. " "LBOS answer: %s.", status_code, buf)); - goto clear_and_exit; - } - /* If we announced successfully and status_code is 200, - * let's extract LBOS address */ - lbos_addr = (char*)calloc(kMaxLineSize, sizeof(char)); /* will not be - * free()'d */ - if (lbos_addr == NULL) { - CORE_LOG(eLOG_Warning, "Failed memory allocation. Most likely, " - "not enough RAM."); - status_code = kLBOSMemAllocError; - goto clear_and_exit; - } - if (buf != NULL) { - parsed_symbols = sscanf(buf, "{\"watcher\":\"%[^\"]\"}", - lbos_addr); - } - if (parsed_symbols != 1) { - CORE_LOG(eLOG_Warning, "g_LBOS_Announce: LBOS answered 200 OK, but " - "output could not be parsed"); - free(lbos_addr); - status_code = kLBOSCorruptOutput; - goto clear_and_exit; - } else { - /* If announce finished with success, we parsed it to extract LBOS ip:port. - * We free() original output and replace it with ip:port */ - free(*lbos_answer); - *lbos_answer = lbos_addr; } - /* Cleanup */ - clear_and_exit: - free(buf); - ConnNetInfo_Destroy(net_info); + free(buf); + ConnNetInfo_Destroy(net_info); return status_code; } -unsigned short LBOS_Announce(const char* service, - const char* version, - const char* host, - unsigned short port, - const char* healthcheck_url, - char** lbos_answer, - char** http_status_message) +unsigned short LBOS_Announce(const char* service, + const char* version, + const char* host, + unsigned short port, + const char* healthcheck_url, +#ifdef LBOS_METADATA + const char* meta_args, +#endif /* LBOS_METADATA */ + char** lbos_answer, + char** http_status_message) { char* my_healthcheck_url = NULL; char* healthcheck_encoded = NULL; @@ -2312,7 +2130,7 @@ unsigned short LBOS_Announce(const char* service, if (s_LBOS_CheckAnnounceArgs(service, version, host, port, healthcheck_url, lbos_answer) == 0) { - return kLBOSInvalidArgs; + return eLBOS_InvalidArgs; } /* * Pre-assign variables @@ -2323,15 +2141,37 @@ unsigned short LBOS_Announce(const char* service, /*my_healthcheck_url = strdup(healthcheck_url); */ if (my_healthcheck_url == NULL) { - result = kLBOSDNSResolveError; + result = eLBOS_DNSResolve; goto clean_and_exit; } /* If host provided separately from healthcheck URL, check if we need to * replace 0.0.0.0 with local IP, and do it if needed */ - my_host = s_LBOS_Replace0000WithIP(host); + if (!g_LBOS_StringIsNullOrEmpty(host)) { + my_host = s_LBOS_Replace0000WithIP(host); + } + else { /* If host was NOT provided, we append local IP to query, + * just in case */ + SConnNetInfo * healthcheck_info; + healthcheck_info = ConnNetInfo_Clone(s_EmptyNetInfo); + healthcheck_info->host[0] = '\0'; /* to be sure that it will be + * overridden */ + /* Save info about host */ + ConnNetInfo_ParseURL(healthcheck_info, my_healthcheck_url); + my_host = strdup(healthcheck_info->host); + /* If we could not parse healthcheck URL, throw "Invalid Arguments" */ + if (g_LBOS_StringIsNullOrEmpty(my_host)) { + ConnNetInfo_Destroy(healthcheck_info); + CORE_LOG_X(eLBOS_InvalidArgs, eLOG_Critical, + "Could not parse host from healthcheck URL. Please set " + "ip of the announced server explicitly."); + result = eLBOS_InvalidArgs; + goto clean_and_exit; + } + ConnNetInfo_Destroy(healthcheck_info); + } healthcheck_encoded = s_LBOS_URLEncode(my_healthcheck_url); - service_encoded = s_LBOS_URLEncode(service); + service_encoded = s_LBOS_ModifyServiceName(service); version_encoded = s_LBOS_URLEncode(version); /* Announce */ @@ -2341,9 +2181,10 @@ unsigned short LBOS_Announce(const char* service, my_host, port, healthcheck_encoded, + meta_args, lbos_answer, http_status_message); - if (result == kLBOSSuccess) { + if (result == eLBOS_Success) { CORE_LOCK_WRITE; s_LBOS_AddAnnouncedServer(service, version, port, healthcheck_url); CORE_UNLOCK; @@ -2364,7 +2205,7 @@ unsigned short LBOS_AnnounceFromRegistry(const char* registry_section, char** lbos_answer, char** http_status_message) { - unsigned short result = kLBOSSuccess; + unsigned short result = eLBOS_Success; size_t i = 0; unsigned int port; char* srvc; @@ -2372,6 +2213,7 @@ unsigned short LBOS_AnnounceFromRegistry(const char* registry_section, char* port_str; char* hlth; char* host; + char* meta; if (g_LBOS_StringIsNullOrEmpty(registry_section)) { registry_section = kLBOSAnnouncementSection; @@ -2382,25 +2224,30 @@ unsigned short LBOS_AnnounceFromRegistry(const char* registry_section, host = g_LBOS_RegGet(registry_section, kLBOSServerHostVariable, NULL); hlth = g_LBOS_RegGet(registry_section, kLBOSHealthcheckUrlVariable, NULL); + meta = g_LBOS_RegGet(registry_section, kLBOSMetaVariable, + NULL); /* Check port that it is a number of max 5 digits and no other symbols */ for (i = 0; i < strlen(port_str); i++) { if (!isdigit(port_str[i])) { - result = kLBOSInvalidArgs; + CORE_LOGF_X(eLBOS_InvalidArgs, eLOG_Warning, + ("Port \"%s\" in section %s is invalid", port_str, + registry_section)); + result = eLBOS_InvalidArgs; goto clean_and_exit; } } if (strlen(port_str) > 5 || (sscanf(port_str, "%d", &port) != 1) || port < 1 || port > 65535) { - result = kLBOSInvalidArgs; + result = eLBOS_InvalidArgs; goto clean_and_exit; } /* Announce */ - result = LBOS_Announce(srvc, vers, host, (unsigned short)port, hlth, + result = LBOS_Announce(srvc, vers, host, (unsigned short)port, hlth, meta, lbos_answer, http_status_message); - if (result == kLBOSSuccess) { + if (result == eLBOS_Success) { CORE_LOCK_WRITE; s_LBOS_AddAnnouncedServer(srvc, vers, port, hlth); CORE_UNLOCK; @@ -2413,10 +2260,12 @@ clean_and_exit: free(port_str); free(hlth); free(host); + free(meta); return result; } - +/* Separated from LBOS_Deannounce to easier control memory allocated for + * variables */ unsigned short s_LBOS_Deannounce(const char* service, const char* version, const char* host, @@ -2433,45 +2282,26 @@ unsigned short s_LBOS_Deannounce(const char* service, lbos_address = s_LBOS_Instance; status_code = 0; buf = NULL; - query_format = "http://%s/lbos/json/conceal?name=%s&version=%s&port=%hu"; + /* ip */ + query_format = "http://%s/lbos/v3/services%s?version=%s&" + "port=%hu&" + "ip=%s"; /* * Try deannounce */ char* query; - size_t length; - /* We deny foreign de-announcement*/ - /* Compare local domain and LBOS domain */ - if (!g_LBOS_CheckDomain(lbos_address)) { - CORE_LOGF_X(1, eLOG_Warning, - ("[%s] is not from local domain [%s]. " - "Announcement in foreign domain is not allowed.", - lbos_address, s_LBOS_ReadDomain())); - } - else { - query = (char*)calloc(strlen(query_format) + - strlen(lbos_address) + strlen(service) + - strlen(version) + 5/*port*/, - sizeof(char)); - sprintf(query, query_format, lbos_address, service, version, port); - length = strlen(query); - /* If host was provided, we append it to query */ - if (!g_LBOS_StringIsNullOrEmpty(host)) { - query = g_LBOS_StringConcat(g_LBOS_StringConcat( - query, "&ip=", &length), - host, &length); - } - else { /* If host was NOT provided, we append local IP to query, - * just in case */ - char* local_ip = s_LBOS_Replace0000WithIP("0.0.0.0"); - query = g_LBOS_StringConcat(g_LBOS_StringConcat( - query, "&ip=", &length), - local_ip, &length); - free(local_ip); - } - buf = s_LBOS_UrlReadAll(net_info, query, &status_code, - &status_message); - free(query); - } + assert(!g_LBOS_StringIsNullOrEmpty(host)); + /* We do not count extra 1 byte for \0 because we still have extra + * bytes because of %s placeholders */ + query = (char*)calloc(strlen(query_format) + + strlen(lbos_address) + strlen(service) + + strlen(version) + 5/*port*/ + strlen(host), + sizeof(char)); + sprintf(query, query_format, + lbos_address, service, version, port, host); + buf = s_LBOS_UrlReadAll(net_info, query, &status_code, + &status_message); + free(query); if (lbos_answer != NULL && !g_LBOS_StringIsNullOrEmpty(buf)) { *lbos_answer = strdup(buf); } @@ -2482,7 +2312,7 @@ unsigned short s_LBOS_Deannounce(const char* service, free(status_message); if (status_code == 0) { - status_code = kLBOSNoLBOS; + status_code = eLBOS_LbosNotFound; } return status_code; } @@ -2504,16 +2334,13 @@ unsigned short LBOS_Deannounce(const char* service, * First we check input arguments */ if (s_LBOS_CheckDeannounceArgs(service, version, host, port) == 0) { - return kLBOSInvalidArgs; + return eLBOS_InvalidArgs; } /* * Check if LBOS is ON */ - if (s_LBOS_Init == 0) { - s_LBOS_funcs.Initialize(); - } - if (s_LBOS_TurnedOn == 0) { - return kLBOSOff; + if (!s_TurnOn()) { + return eLBOS_Disabled; } /* * If we are here, arguments are good! @@ -2524,19 +2351,25 @@ unsigned short LBOS_Deannounce(const char* service, else { /* If host was NOT provided, we append local IP to query, * just in case */ my_host = s_LBOS_Replace0000WithIP("0.0.0.0"); + if (g_LBOS_StringIsNullOrEmpty(my_host)){ + CORE_LOG_X(eLBOS_DNSResolve, eLOG_Critical, + "Did not manage to get local IP address."); + free(my_host); + return eLBOS_DNSResolve; + } } net_info = ConnNetInfo_Clone(s_EmptyNetInfo); - net_info->req_method = eReqMethod_Post; - service_encoded = s_LBOS_URLEncode(service); + net_info->req_method = eReqMethod_Delete; + service_encoded = s_LBOS_ModifyServiceName(service); version_encoded = s_LBOS_URLEncode(version); retval = s_LBOS_Deannounce(service_encoded, version_encoded, my_host, port, lbos_answer, http_status_message, net_info); - /* If kLBOSNotFound or kLBOSSuccess - we delete server from local storage + /* If eLBOS_NotFound or eLBOS_Success - we delete server from local storage * as no longer existing */ - if (retval == kLBOSNotFound || retval == kLBOSSuccess) { + if (retval == eLBOS_NotFound || retval == eLBOS_Success) { CORE_LOCK_WRITE; s_LBOS_RemoveAnnouncedServer(service, version, port, host); CORE_UNLOCK; @@ -2577,7 +2410,8 @@ void LBOS_DeannounceAll() local_arr = (struct SLBOS_AnnounceHandle_Tag*)calloc(servers, sizeof(**arr)); if (local_arr == NULL) { - CORE_LOG_X(1, eLOG_Warning, "RAM error. Cancelling deannounce all."); + CORE_LOG_X(eLBOS_MemAlloc, eLOG_Warning, + "RAM error. Cancelling deannounce all."); CORE_UNLOCK; return; } @@ -2624,6 +2458,27 @@ void LBOS_DeannounceAll() /*///////////////////////////////////////////////////////////////////////////// // LBOS CONFIGURATION // /////////////////////////////////////////////////////////////////////////////*/ +static int s_LBOS_CheckConfArgs(const char* service, const char** lbos_answer) +{ + unsigned int i; + if (g_LBOS_StringIsNullOrEmpty(service) || lbos_answer == NULL) { + CORE_LOG_X(eLBOS_InvalidArgs, eLOG_Warning, + "s_LBOS_CheckConfArgs: service is NULL or lbos_answer " + "is NULL"); + return 0; + } + for (i = 0; i < strlen(service); i++) { + if (isspace(service[i])) { + CORE_LOGF_X(eLBOS_InvalidArgs, eLOG_Warning, + ("s_LBOS_CheckConfArgs: service " + "\"%s\" contains invalid character", service)); + return 0; + } + } + return 1; +} + + /** This request will show currently used version for a requested service. * Current and previous version will be the same. * @param service[in] @@ -2646,23 +2501,21 @@ unsigned short LBOS_ServiceVersionGet(const char* service, /* * First we check input arguments */ - if (g_LBOS_StringIsNullOrEmpty(service) || lbos_answer == NULL) { - return kLBOSInvalidArgs; + if (!s_LBOS_CheckConfArgs(service, (const char**)lbos_answer)) { + return eLBOS_InvalidArgs; } /* * Check if LBOS is ON */ - if (s_LBOS_Init == 0) { - s_LBOS_funcs.Initialize(); - } - if (s_LBOS_TurnedOn == 0) { - return kLBOSOff; + if (!s_TurnOn()) { + return eLBOS_Disabled; } + /* * Arguments are good! Let's do the request */ - service_encoded = s_LBOS_URLEncode(service); - query_format = "/lbos/xml/configuration?name=%s"; + service_encoded = s_LBOS_ModifyServiceName(service); + query_format = "/lbos/v3/conf%s?format=xml"; query = (char*)calloc(strlen(query_format) + strlen(service_encoded), sizeof(char)); @@ -2704,24 +2557,27 @@ unsigned short LBOS_ServiceVersionSet(const char* service, /* * First we check input arguments */ - if (g_LBOS_StringIsNullOrEmpty(service) || lbos_answer == NULL - || g_LBOS_StringIsNullOrEmpty(new_version)) { - return kLBOSInvalidArgs; + if (!s_LBOS_CheckConfArgs(service, (const char**)lbos_answer)) { + return eLBOS_InvalidArgs; + } + if (g_LBOS_StringIsNullOrEmpty(new_version)) { + CORE_LOG_X(eLBOS_InvalidArgs, eLOG_Warning, + "LBOS_ServiceVersionSet: new_version is empty. " + "If you want to delete service config, use " + "LBOS_ServiceVersionDelete"); + return eLBOS_InvalidArgs; } /* * Check if LBOS is ON */ - if (s_LBOS_Init == 0) { - s_LBOS_funcs.Initialize(); - } - if (s_LBOS_TurnedOn == 0) { - return kLBOSOff; + if (!s_TurnOn()) { + return eLBOS_Disabled; } /* * Arguments are good! Let's do the request */ - service_encoded = s_LBOS_URLEncode(service); - query_format = "/lbos/xml/configuration?name=%s&version=%s"; + service_encoded = s_LBOS_ModifyServiceName(service); + query_format = "/lbos/v3/conf%s?version=%s&format=xml"; query = (char*)calloc(strlen(query_format) + strlen(service_encoded) + strlen(new_version), @@ -2754,23 +2610,20 @@ unsigned short LBOS_ServiceVersionDelete(const char* service, /* * First we check input arguments */ - if (g_LBOS_StringIsNullOrEmpty(service) || lbos_answer == NULL) { - return kLBOSInvalidArgs; + if (!s_LBOS_CheckConfArgs(service, (const char**)lbos_answer)) { + return eLBOS_InvalidArgs; } /* * Check if LBOS is ON */ - if (s_LBOS_Init == 0) { - s_LBOS_funcs.Initialize(); - } - if (s_LBOS_TurnedOn == 0) { - return kLBOSOff; + if (!s_TurnOn()) { + return eLBOS_Disabled; } /* * Arguments are good! Let's do the request */ - service_encoded = s_LBOS_URLEncode(service); - query_format = "/lbos/xml/configuration?name=%s"; + service_encoded = s_LBOS_ModifyServiceName(service); + query_format = "/lbos/v3/conf%s?format=xml"; query = (char*)calloc(strlen(query_format) + strlen(service_encoded), sizeof(char)); diff --git a/c++/src/connect/ncbi_lbos.h b/c++/src/connect/ncbi_lbos.h old mode 100755 new mode 100644 index a3c512f3..05bd4de0 --- a/c++/src/connect/ncbi_lbos.h +++ b/c++/src/connect/ncbi_lbos.h @@ -26,6 +26,7 @@ * =========================================================================== * * Authors: Dmitriy Elisov +* Credits: Denis Vakatov * @file * File Description: * Possibly public interface to LBOS client if someone ever needs a C version @@ -40,7 +41,10 @@ extern "C" { #endif /*__cplusplus*/ - + +#define LBOS_METADATA + + /** Announce server. * * @attention @@ -66,6 +70,8 @@ extern "C" { * announces it (i.e., if server announces itself), you can write * "0.0.0.0" for IP (this is convention with lbos). You still have to * provide port, even if you write "0.0.0.0". +* @param [out] meta_args +* Array of meta arguments in form { "name1", "val1", "name2", "val2", NULL } * @param [out] lbos_answer * This variable will be assigned a pointer to C-string with exact body of * lbos' response (or NULL, if no lbos was reached). @@ -89,6 +95,9 @@ unsigned short LBOS_Announce(const char* service, const char* host, unsigned short port, const char* healthcheck_url, +#ifdef LBOS_METADATA + const char* meta_args, +#endif /* LBOS_METADATA */ char** lbos_answer, char** http_status_message); diff --git a/c++/src/connect/ncbi_lbos_cxx.cpp b/c++/src/connect/ncbi_lbos_cxx.cpp old mode 100755 new mode 100644 index b3537b40..836e5932 --- a/c++/src/connect/ncbi_lbos_cxx.cpp +++ b/c++/src/connect/ncbi_lbos_cxx.cpp @@ -24,6 +24,7 @@ * =========================================================================== * * Authors: Dmitriy Elisov + * Credits: Denis Vakatov * @file * File Description: * C++ Wrapper for the LBOS mapper written in C @@ -42,13 +43,14 @@ BEGIN_NCBI_SCOPE -DEFINE_STATIC_FAST_MUTEX(s_GlobalLock); -static const char* kLBOSAnnounceRegistrySection("LBOS_ANNOUNCEMENT"); -static const char* kLBOSServiceVariable("SERVICE"); -static const char* kLBOSVersionVariable("VERSION"); -static const char* kLBOSServerHostVariable("HOST"); -static const char* kLBOSPortVariable("PORT"); -static const char* kLBOSHealthcheckUrlVariable("HEALTHCHECK"); +DEFINE_STATIC_FAST_MUTEX(s_IPCacheLock); +const string kLBOSAnnounceRegistrySection = "LBOS_ANNOUNCEMENT"; +const string kLBOSServiceVariable = "SERVICE"; +const string kLBOSVersionVariable = "VERSION"; +const string kLBOSServerHostVariable = "HOST"; +const string kLBOSPortVariable = "PORT"; +const string kLBOSHealthcheckUrlVariable = "HEALTHCHECK"; +const string kLBOSMetaVariable = "META"; const SConnNetInfo* kEmptyNetInfo = ConnNetInfo_Create(NULL); @@ -73,6 +75,10 @@ struct SLbosConfigure string current_version; }; + +CSafeStatic< map< CLBOSIpCacheKey, string > > CLBOSIpCache::sm_IpCache; + + bool CLBOSIpCacheKey::operator==(const CLBOSIpCacheKey& rh) const { return x_Service == rh.x_Service && @@ -82,7 +88,10 @@ bool CLBOSIpCacheKey::operator==(const CLBOSIpCacheKey& rh) const } -CLBOSIpCacheKey::CLBOSIpCacheKey(string service, string hostname, string version, unsigned short port) : +CLBOSIpCacheKey::CLBOSIpCacheKey(const string& service, + const string& hostname, + const string& version, + unsigned short port) : x_Service(service), x_Hostname(hostname), x_Version(version), x_Port(port) { @@ -109,77 +118,94 @@ bool CLBOSIpCacheKey::operator>(const CLBOSIpCacheKey& rh) const } -std::string CLBOSIpCache::HostnameTryFind(string service, string hostname, - string version, unsigned short port) +std::string CLBOSIpCache::HostnameTryFind(const string& service, + const string& hostname_in, + const string& version, + unsigned short port) { - if (hostname == "") - hostname = CSocketAPI::GetLocalHostAddress(); + string hostname = hostname_in; + if (hostname.empty()) + hostname = CSocketAPI::HostPortToString( + CSocketAPI::GetLocalHostAddress(), 0); map::iterator pos; CLBOSIpCacheKey key(service, hostname, version, port); - pos = x_IpCache->find(key); - if (pos != x_IpCache->end()) - return pos->second; - else return hostname; + {{ + CFastMutexGuard spawn_guard(s_IPCacheLock); + pos = sm_IpCache->find(key); + if (pos != sm_IpCache->end()) + return pos->second; + else return hostname; + }} } -std::string CLBOSIpCache::HostnameResolve(string service, string hostname, - string version, unsigned short port) +std::string CLBOSIpCache::HostnameResolve(const string& service, + const string& hostname, + const string& version, + unsigned short port) { - /* LBOS behavior - if DNS could not resolve hostname, throw 400 Bad Request. - * Here we emulate LBOS behavior. - * Here we try to resolve hostname before - * sending it to LBOS, so we should return the same answer as LBOS would - * do.*/ - if (hostname == "") { + /* Hostname should not be empty in any case */ + if (hostname.empty()) { throw CLBOSException(CDiagCompileInfo(__FILE__, __LINE__), NULL, - CLBOSException::EErrCode::e_LBOSBadRequest, "400 Bad Request", - kLBOSBadRequest); + CLBOSException::eUnknown, + "Internal error in LBOS Client IP Cache. Please contact developer", + eLBOS_BadRequest); } map::iterator pos; CLBOSIpCacheKey key(service, hostname, version, port); - pos = x_IpCache->find(key); - /* If hostname is already in the cache, return previously resolved IP */ - if (pos != x_IpCache->end()) - return pos->second; + {{ + CFastMutexGuard spawn_guard(s_IPCacheLock); + pos = sm_IpCache->find(key); + /* If hostname is already in the cache, return previously resolved IP */ + if (pos != sm_IpCache->end()) + return pos->second; + + }} /* We did not find IP in the cache. Then we resolve the hostname to IP and - save it to the cache. To make sure that our changes do not interfere - with changes from another thread, we use 'insert' instead of '[]' (not - to rewrite) */ + save it to the cache. To make sure that our changes do not interfere + with changes from another thread, we use 'insert' instead of '[]' (not + to rewrite) */ string host = CSocketAPI::HostPortToString(CSocketAPI::gethostbyname(hostname), 0); /* If gethostbyname() could not resolve the hostname, it will return ":0". - In this case we go back to the original hostname, so that LBOS can try - to resolve it itself. */ + In this case we go back to the original hostname, so that LBOS can try + to resolve it itself. */ if (host == ":0") { host = hostname; } - /* Save pair */ - std::pair::iterator, bool> res = - x_IpCache->insert(std::pair(key, host)); - return res.first->second; + {{ + CFastMutexGuard spawn_guard(s_IPCacheLock); + /* Save pair */ + std::pair::iterator, bool> res = + sm_IpCache->insert(std::pair(key, host)); + return res.first->second; + }} } -void CLBOSIpCache::HostnameDelete(string service, string hostname, - string version, unsigned short port) +void CLBOSIpCache::HostnameDelete(const string& service, + const string& hostname_in, + const string& version, + unsigned short port) { - if (hostname == "") - hostname = CSocketAPI::GetLocalHostAddress(); + string hostname = hostname_in; + if (hostname.empty()) + hostname = CSocketAPI::HostPortToString( + CSocketAPI::GetLocalHostAddress(), 0); map::iterator pos; CLBOSIpCacheKey key(service, hostname, version, port); - pos = x_IpCache->find(key); - if (pos != x_IpCache->end()) - x_IpCache->erase(pos); + {{ + CFastMutexGuard spawn_guard(s_IPCacheLock); + pos = sm_IpCache->find(key); + if (pos != sm_IpCache->end()) + sm_IpCache->erase(pos); + }} } -CSafeStatic< map< CLBOSIpCacheKey, string > > CLBOSIpCache::x_IpCache; - - static void s_ProcessResult(unsigned short result, const char* lbos_answer, const char* status_message) { - if (result == kLBOSSuccess) + if (result == eLBOS_Success) return; stringstream message; @@ -197,9 +223,12 @@ static void s_ProcessResult(unsigned short result, } -void LBOS::Announce(const string& service, const string& version, - const string& host, unsigned short port, - const string& healthcheck_url) +void LBOS::Announce(const string& service, + const string& version, + const string& host, + unsigned short port, + const string& healthcheck_url, + const string& metadata) { char* body_str = NULL, *status_message_str = NULL; AutoPtr< char*, Free > body_aptr(&body_str), @@ -207,7 +236,7 @@ void LBOS::Announce(const string& service, const string& version, string cur_host = host, ip; /* If host is empty, it means that host is the same as in healthcheck * (by convention). We have to parse healthcheck and get host */ - if (cur_host == "") + if (cur_host.empty()) { SConnNetInfo * healthcheck_info; healthcheck_info = ConnNetInfo_Clone(kEmptyNetInfo); @@ -217,46 +246,60 @@ void LBOS::Announce(const string& service, const string& version, ConnNetInfo_ParseURL(healthcheck_info, healthcheck_url.c_str()); cur_host = healthcheck_info->host; /* If we could not parse healthcheck URL, throw "Invalid Arguments" */ - if (cur_host == "") { + if (cur_host.empty()) { ConnNetInfo_Destroy(healthcheck_info); throw CLBOSException(CDiagCompileInfo(__FILE__, __LINE__), NULL, - CLBOSException::EErrCode::e_LBOSInvalidArgs, - NStr::IntToString(kLBOSInvalidArgs), - kLBOSInvalidArgs); + CLBOSException::eInvalidArgs, + NStr::IntToString(eLBOS_InvalidArgs), + eLBOS_InvalidArgs); } ConnNetInfo_Destroy(healthcheck_info); } if (cur_host == "0.0.0.0") { ip = cur_host; } else { - /* We make a guard here because CLBOSIpCache saves resolution results - to its static storage */ - CFastMutexGuard spawn_guard(s_GlobalLock); ip = CLBOSIpCache::HostnameResolve(service, cur_host, version, port); } /* If healthcheck is on the same host as server, we try to replace hostname * with IP in healthcheck URL, too */ string temp_healthcheck = NStr::Replace(healthcheck_url, cur_host, ip); - unsigned short result = LBOS_Announce(service.c_str(), version.c_str(), - ip.c_str(), port, + unsigned short result = LBOS_Announce(service.c_str(), + version.c_str(), + ip.c_str(), + port, temp_healthcheck.c_str(), - &*body_aptr, &*status_message_aptr); + metadata.c_str(), + &*body_aptr, + &*status_message_aptr); s_ProcessResult(result, *body_aptr, *status_message_aptr); } -void LBOS::AnnounceFromRegistry(string reg_section) +void LBOS::Announce(const string& service, + const string& version, + const string& host, + unsigned short port, + const string& healthcheck_url, + const CMetaData& metadata) +{ + Announce(service, version, host, port, healthcheck_url, + metadata.GetMetaString()); +} + + +void LBOS::AnnounceFromRegistry(const string& reg_sec) { + /* If "reg_section" is empty, we use default section. */ + const string& reg_section = reg_sec.empty() ? kLBOSAnnounceRegistrySection + : reg_sec; + LOG_POST(Error << "Registry section is " << reg_section); CNcbiRegistry& config = CNcbiApplication::Instance()->GetConfig(); - /* If "registry_section" is empty, we use default section. */ - if (reg_section == "") { - reg_section = kLBOSAnnounceRegistrySection; - } string host = config.Get(reg_section, kLBOSServerHostVariable); string service = config.Get(reg_section, kLBOSServiceVariable); string version = config.Get(reg_section, kLBOSVersionVariable); string port_str = config.Get(reg_section, kLBOSPortVariable); string health = config.Get(reg_section, kLBOSHealthcheckUrlVariable); + string meta = config.Get(reg_section, kLBOSMetaVariable); /* Check that port is a number between 1 and 65535 */ int port_int = 0; @@ -265,19 +308,21 @@ void LBOS::AnnounceFromRegistry(string reg_section) } catch (...) { throw CLBOSException(CDiagCompileInfo(__FILE__, __LINE__), NULL, - CLBOSException::EErrCode::e_LBOSInvalidArgs, - NStr::IntToString(kLBOSInvalidArgs), - kLBOSInvalidArgs); + CLBOSException::eInvalidArgs, + "Could not parse port \"" + port_str + + "\" in section \"" + reg_section + "\"", + eLBOS_InvalidArgs); } if (port_int < 1 || port_int > 65535) { throw CLBOSException(CDiagCompileInfo(__FILE__, __LINE__), NULL, - CLBOSException::EErrCode::e_LBOSInvalidArgs, - NStr::IntToString(kLBOSInvalidArgs), - kLBOSInvalidArgs); + CLBOSException::eInvalidArgs, + "Invalid server port \"" + port_str + + "\" in section \"" + reg_section + "\"", + eLBOS_InvalidArgs); } unsigned short port = static_cast(port_int); - Announce(service, version, host, port, health); + Announce(service, version, host, port, health, meta); } @@ -294,10 +339,9 @@ void LBOS::Deannounce(const string& service, { char* body_str = NULL, *status_message_str = NULL; string ip; - if (host == "" || host == "0.0.0.0") { + if (host.empty() || host == "0.0.0.0") { ip = host; } else { - CFastMutexGuard spawn_guard(s_GlobalLock); ip = CLBOSIpCache::HostnameTryFind(service, host, version, port); } AutoPtr< char*, Free > body_aptr(&body_str), @@ -310,7 +354,6 @@ void LBOS::Deannounce(const string& service, /* Then remove resolution result from cache */ if (host != "" /* invalid input */ && host != "0.0.0.0" /* not handled by cache */) { - CFastMutexGuard spawn_guard(s_GlobalLock); CLBOSIpCache::HostnameDelete(service, host, version, port); } } @@ -369,13 +412,14 @@ SLbosConfigure ParseLbosConfigureAnswer(const char* lbos_answer) } -string LBOS::ServiceVersionGet(const string& service, - bool* exists) +string LBOSPrivate::GetServiceVersion(const string& service, + bool* exists) { char* body_str = NULL, *status_message_str = NULL; AutoPtr< char*, Free > body_aptr(&body_str), status_message_aptr(&status_message_str); - unsigned short result = LBOS_ServiceVersionGet(service.c_str(), &*body_aptr, + unsigned short result = LBOS_ServiceVersionGet(service.c_str(), + &*body_aptr, &*status_message_aptr); s_ProcessResult(result, *body_aptr, *status_message_aptr); SLbosConfigure res = ParseLbosConfigureAnswer(*body_aptr); @@ -386,9 +430,9 @@ string LBOS::ServiceVersionGet(const string& service, } -string LBOS::ServiceVersionSet(const string& service, - const string& new_version, - bool* existed) +string LBOSPrivate::SetServiceVersion(const string& service, + const string& new_version, + bool* existed) { char* body_str = NULL, *status_message_str = NULL; AutoPtr< char*, Free > body_aptr(&body_str), @@ -406,8 +450,8 @@ string LBOS::ServiceVersionSet(const string& service, } -string LBOS::ServiceVersionDelete(const string& service, - bool* existed) +string LBOSPrivate::DeleteServiceVersion(const string& service, + bool* existed) { char* body_str = NULL, *status_message_str = NULL; AutoPtr< char*, Free > body_aptr(&body_str), @@ -424,30 +468,29 @@ string LBOS::ServiceVersionDelete(const string& service, } -CLBOSException::EErrCode - CLBOSException::s_HTTPCodeToEnum(unsigned short http_code) -{ - switch (http_code) { - case kLBOSNoLBOS: - return EErrCode::e_LBOSNoLBOS; - case kLBOSNotFound: - return EErrCode::e_LBOSNotFound; - case kLBOSBadRequest: - return EErrCode::e_LBOSBadRequest; - case kLBOSOff: - return EErrCode::e_LBOSOff; - case kLBOSInvalidArgs: - return EErrCode::e_LBOSInvalidArgs; - case kLBOSDNSResolveError: - return EErrCode::e_LBOSDNSResolveError; - case kLBOSMemAllocError: - return EErrCode::e_LBOSMemAllocError; - case kLBOSCorruptOutput: - return EErrCode::e_LBOSCorruptOutput; - case kLBOSServerError: - return EErrCode::e_LBOSServerError; +CLBOSException::EErrCode CLBOSException::s_HTTPCodeToEnum(unsigned short code) +{ + switch (code) { + case eLBOS_LbosNotFound: + return eLbosNotFound; + case eLBOS_NotFound: + return eNotFound; + case eLBOS_BadRequest: + return eBadRequest; + case eLBOS_Disabled: + return eDisabled; + case eLBOS_InvalidArgs: + return eInvalidArgs; + case eLBOS_DNSResolve: + return eDNSResolve; + case eLBOS_MemAlloc: + return eMemAlloc; + case eLBOS_Protocol: + return eProtocol; + case eLBOS_Server: + return eServer; default: - return EErrCode::e_LBOSUnknown; + return eUnknown; } } @@ -461,32 +504,32 @@ const char* CLBOSException::GetErrCodeString(void) const { switch (GetErrCode()) { /* 400 */ - case EErrCode::e_LBOSBadRequest: + case eBadRequest: return ""; /* 404 */ - case EErrCode::e_LBOSNotFound: + case eNotFound: return ""; /* 500 */ - case EErrCode::e_LBOSServerError: + case eServer: return ""; /* 450 */ - case EErrCode::e_LBOSNoLBOS: + case eLbosNotFound: return "LBOS was not found"; /* 451 */ - case EErrCode::e_LBOSDNSResolveError: + case eDNSResolve: return "DNS error. Possibly, cannot get IP of current machine or " "resolve provided hostname for the server"; /* 452 */ - case EErrCode::e_LBOSInvalidArgs: + case eInvalidArgs: return "Invalid arguments were provided. No request to LBOS was sent"; /* 453 */ - case EErrCode::e_LBOSMemAllocError: + case eMemAlloc: return "Memory allocation error happened while performing request"; /* 454 */ - case EErrCode::e_LBOSCorruptOutput: + case eProtocol: return "Failed to parse LBOS output."; /* 550 */ - case EErrCode::e_LBOSOff: + case eDisabled: return "LBOS functionality is turned OFF. Check config file or " "connection to LBOS."; default: @@ -565,4 +608,306 @@ const CException* CLBOSException::x_Clone(void) const return new CLBOSException(*this); } +#ifdef LBOS_METADATA +LBOS::CMetaData::CMetaData() +{ +} + + +void LBOS::CMetaData::Set(const CTempString name_in, const CTempString val_in) +{ + string name = name_in; + /* First, transform name to lower register to search it */ + NStr::ToLower(name); + /* Forbidden names for meta parameters */ + if (name == "version" || name == "ip" || name == "port" || name == "check" + || name == "format" || name == "name") { + throw CLBOSException(CDiagCompileInfo(__FILE__, __LINE__), NULL, + CLBOSException::eInvalidArgs, + "This name cannot be used for metadata", + eLBOS_InvalidArgs); + } + /* If val is empty, we delete the value from m_Meta */ + if (val_in.empty()) { + auto iter = m_Meta.find(name); + if (iter != m_Meta.end()) { + m_Meta.erase(iter); + } + } + else { + /* If val is not empty, save it to m_Meta or rewrite previous value */ + m_Meta[name] = val_in; + } +} + + +string LBOS::CMetaData::Get(const string& name) const +{ + auto iter = m_Meta.find(name); + if (iter != m_Meta.end()) { + return iter->second; + } + return ""; +} + + +void LBOS::CMetaData::GetNames(list& cont) +{ + auto iter = m_Meta.begin(); + for (; iter != m_Meta.end(); iter++) { + cont.push_back(iter->first); + } +} + + +void LBOS::CMetaData::GetNames(vector& cont) +{ + auto iter = m_Meta.begin(); + for (; iter != m_Meta.end(); iter++) { + cont.push_back(iter->first); + } +} + + +void LBOS::CMetaData::SetRate(const string& rate) +{ + if (rate.empty()) { + Set("rate", ""); + } else { + try { + SetRate(NStr::StringToInt(rate)); + } + catch (const CStringException&) { + throw CLBOSException(CDiagCompileInfo(__FILE__, __LINE__), NULL, + CLBOSException::eInvalidArgs, + "Could not parse string value for SetRate", + eLBOS_InvalidArgs); + } + } +} + + +void LBOS::CMetaData::SetRate(double rate) +{ + if (rate == 0) + Set("rate", ""); + else + Set("rate", NStr::DoubleToString(rate)); +} + + +double LBOS::CMetaData::GetRate() const +{ + string rate = Get("rate"); + if (rate.empty()) + return 0; + try { + return NStr::StringToDouble(rate); + } + catch (const CStringException&) { + throw CLBOSException(CDiagCompileInfo(__FILE__, __LINE__), NULL, + CLBOSException::eInvalidArgs, + "Value in \"rate\" meta parameter cannot " + "be represented as an integer", + eLBOS_InvalidArgs); + } +} + + +void LBOS::CMetaData::SetType(const string& host_type) +{ + if (host_type.find_first_of(" \t\n\v\f\r") != string::npos) { + throw CLBOSException(CDiagCompileInfo(__FILE__, __LINE__), NULL, + CLBOSException::eInvalidArgs, + "This convenience function throws on whitespace characters " + "in \"type\" meta parameter. If you know what you are doing, " + "you can use CMetaData::Set(\"type\", ...)", + eLBOS_InvalidArgs); + } + string type = host_type; + type = NStr::ToUpper(type); + Set("type", type); +} + + +void LBOS::CMetaData::SetType(EHostType host_type) +{ + switch (host_type) { + case eHTTP: + SetType("HTTP"); + break; + case eHTTP_POST: + SetType("HTTP_POST"); + break; + case eHTTP_GET: + SetType("HTTP_GET"); + break; + case eStandalone: + SetType("STANDALONE"); + break; + case eNCBID: + SetType("NCBID"); + break; + case eDNS: + SetType("DNS"); + break; + case eFirewall: + SetType("FIREWALL"); + break; + case eNone: + SetType(""); + break; + default: + throw CLBOSException(CDiagCompileInfo(__FILE__, __LINE__), NULL, + CLBOSException::eInvalidArgs, "Unknown EHostType " + "value. If you are sure that a correct value is " + "used, please tell the developer about this issue", + eLBOS_InvalidArgs); + } +} + + +void LBOS::CMetaData::SetType(ESERV_Type host_type) +{ + switch (host_type) { + case fSERV_Http: + SetType("HTTP"); + break; + case fSERV_HttpPost: + SetType("HTTP_POST"); + break; + case fSERV_HttpGet: + SetType("HTTP_GET"); + break; + case fSERV_Standalone: + SetType("STANDALONE"); + break; + case fSERV_Ncbid: + SetType("NCBID"); + break; + case fSERV_Dns: + SetType("DNS"); + break; + case fSERV_Firewall: + SetType("FIREWALL"); + break; + default: + throw CLBOSException(CDiagCompileInfo(__FILE__, __LINE__), NULL, + CLBOSException::eInvalidArgs, "Unknown ESERV_Type " + "value. If you are sure that a correct value is " + "used, please tell the developer about this issue", + eLBOS_InvalidArgs); + } +} + + +void LBOS::CMetaData::SetType(int host_type) +{ + switch (host_type) { + case (int)eHTTP: + SetType("HTTP"); + break; + case (int)eHTTP_POST: + SetType("HTTP_POST"); + break; + case (int)eStandalone: + SetType("STANDALONE"); + break; + case (int)eNCBID: + SetType("NCBID"); + break; + case (int)eDNS: + SetType("DNS"); + break; + case (int)eNone: + SetType(""); + break; + default: + throw CLBOSException(CDiagCompileInfo(__FILE__, __LINE__), NULL, + CLBOSException::eInvalidArgs, "Unknown EHostType " + "value. If you are sure that a correct value is " + "used, please tell the developer about this issue", + eLBOS_InvalidArgs); + } +} + + +string LBOS::CMetaData::GetType(bool) const +{ + string type = Get("type"); + return NStr::ToUpper(type); +} + + +LBOS::CMetaData::EHostType LBOS::CMetaData::GetType() const +{ + string type = GetType(true); + if (type == "HTTP") { + return eHTTP; + } + else if (type == "HTTP_POST") { + return eHTTP_POST; + } + else if (type == "STANDALONE") { + return eStandalone; + } + else if (type == "NCBID") { + return eNCBID; + } + else if (type == "DNS") { + return eDNS; + } + else if (type.empty()) { + return eNone; + } + else { + return eUnknown; + } +} + + +void LBOS::CMetaData::SetExtra(const string& extra) +{ + if (extra.find_first_of(" \t\n\v\f\r") != string::npos) { + throw CLBOSException(CDiagCompileInfo(__FILE__, __LINE__), NULL, + CLBOSException::eInvalidArgs, + "This convenience function throws on whitespace characters " + "in \"extra\" meta parameter. If you know what you are doing, " + "you can use CMetaData::Set(\"extra\", ...)", + eLBOS_InvalidArgs); + } + Set("extra", extra); +} + + +std::string LBOS::CMetaData::GetExtra() const +{ + return Get("extra"); +} + + +string LBOS::CMetaData::GetMetaString() const +{ + stringstream meta_stringstream; + auto iter = m_Meta.begin(); + for ( ; iter != m_Meta.end() ; ) { + meta_stringstream << NStr::URLEncode(iter->first) << "=" + << NStr::URLEncode(iter->second); + if (++iter != m_Meta.end()) { + meta_stringstream << "&"; + } + } + return meta_stringstream.str(); +} + + +ostream& operator<<(ostream& os, const LBOS::CMetaData& metadata) +{ + os << metadata.GetMetaString(); + return os; +} + + +#endif /* LBOS_METADATA */ + END_NCBI_SCOPE diff --git a/c++/src/connect/ncbi_lbosp.h b/c++/src/connect/ncbi_lbosp.h index 5592d46c..5aa68754 100644 --- a/c++/src/connect/ncbi_lbosp.h +++ b/c++/src/connect/ncbi_lbosp.h @@ -26,6 +26,7 @@ * =========================================================================== * * Authors: Dmitriy Elisov + * Credits: Denis Vakatov * @file * File Description: * This header was made only because of unit testing application. Please, @@ -42,6 +43,9 @@ extern "C" { #endif /*__cplusplus*/ +#ifndef LBOS_METADATA +#define LBOS_METADATA +#endif /* * Additional HTTP codes: @@ -52,17 +56,25 @@ extern "C" { * 454 - LBOS output could not be parsed * 550 - LBOS client is OFF in the current process */ -static const int kLBOSSuccess = 200; -static const int kLBOSBadRequest = 400; -static const int kLBOSNotFound = 404; -static const int kLBOSNoLBOS = 450; -static const int kLBOSDNSResolveError = 451; -static const int kLBOSInvalidArgs = 452; -static const int kLBOSMemAllocError = 453; -static const int kLBOSCorruptOutput = 454; -static const int kLBOSServerError = 500; -static const int kLBOSOff = 550; - +enum ELBOSStatusCodes { + eLBOS_Success = 200, /**< HTTP 200 OK */ + eLBOS_BadRequest = 400, /**< HTTP 400 Bad Request */ + eLBOS_NotFound = 404, /**< HTTP 404 Not Found */ + eLBOS_LbosNotFound = 450, /**< Not a HTTP code. LBOS was not found */ + eLBOS_DNSResolve = 451, /**< Not a HTTP code. Could not find IP of + localhost */ + eLBOS_InvalidArgs = 452, /**< Not a HTTP code. Some arguments were + invalid */ + eLBOS_MemAlloc = 453, /**< Not a HTTP code. Some memory could not be + allocated */ + eLBOS_Protocol = 454, /**< Not a HTTP code. LBOS response could not + be parsed */ + eLBOS_Server = 500, /**< HTTP 500 Internal Server Error */ + eLBOS_Disabled = 550 /**< Not a HTTP code. LBOS Client functionality + is disabled in registry or during + initialization (LBOS Client could not + establish connection with LBOS) */ +}; /////////////////////////////////////////////////////////////////////////////// // DATA TYPES // @@ -81,10 +93,10 @@ static const int kLBOSOff = 550; typedef enum { eLBOSFindMethod_None, /**< do not search. Used to skip "custom host" method */ - eLBOSFindMethod_CustomHost, /**< Use custom address provided by + eLBOS_FindMethod_CustomHost, /**< Use custom address provided by s_SetLBOSaddress() */ - eLBOSFindMethod_Registry, /**< Use value from registry (default) */ - eLBOSFindMethod_Lbosresolve, /**< Use value from /etc/ncbi/lbosresolve*/ + eLBOS_FindMethod_Registry, /**< Use value from registry (default) */ + eLBOS_FindMethod_Lbosresolve, /**< Use value from /etc/ncbi/lbosresolve*/ } ELBOSFindMethod; @@ -101,7 +113,7 @@ typedef struct { SConnNetInfo* net_info; /**< Connection point */ const char* lbos_addr; /**< LBOS host:port or IP:port. Used if find_method == - eLBOSFindMethod_CustomHost */ + eLBOS_FindMethod_CustomHost */ SLBOS_Candidate* cand; /**< Array of found server to iterate */ size_t pos_cand; /**< Current candidate */ size_t n_cand; /**< Used space for candidates */ @@ -117,8 +129,8 @@ typedef struct { int http_response_code; char* http_status_mesage; const char* header; - size_t content_length; /* Value of "Content-length" HTTP header tag. - -1 (max value) as no limit */ + size_t content_length; /**< Value of "Content-length" HTTP header tag. + -1 (max value) as no limit */ } SLBOS_UserData; @@ -191,13 +203,6 @@ EIO_Status FLBOS_ConnReadMethod(CONN conn, EIO_ReadMethod how); -/** Compose LBOS address from /etc/ncbi/{role, domain}. - * @return - * Constructed host:port or IP:port. Must be free()'d by the caller. */ -typedef -char* FLBOS_ComposeLBOSAddressMethod(void); - - /** Given just empty data structure and name of service, do all necessary * operations to fill the structure with servers. * @param data[out] @@ -253,6 +258,8 @@ SSERV_Info* FLBOS_GetNextInfoMethod(SERV_ITER iter, * @param healthcheck_url[in] * Full absolute URL starting with "http://" or "https://". Should include * hostname or IP and port, if necessary. + * @param metadata[in] + * URL-ready link with additional meta parameters * @param LBOS_answer[out] * This variable will be assigned a pointer to char* with exact answer of * LBOS, or NULL. If it is not NULL, must be free()'d by the caller. If @@ -269,6 +276,9 @@ unsigned short FLBOS_AnnounceMethod(const char* service, const char* host, unsigned short port, const char* healthcheck_url, +#ifdef LBOS_METADATA + const char* metadata, +#endif /* LBOS_METADATA */ char** LBOS_answer, char** http_status_message); @@ -327,7 +337,6 @@ typedef unsigned int FLBOS_SOCKGetLocalHostAddressMethod(ESwitch reget); typedef struct { FLBOS_ResolveIPPortMethod* ResolveIPPort; FLBOS_ConnReadMethod* Read; - FLBOS_ComposeLBOSAddressMethod* ComposeLBOSAddress; FLBOS_FillCandidatesMethod* FillCandidates; FLBOS_DestroyDataMethod* DestroyData; FLBOS_GetNextInfoMethod* GetNextInfo; @@ -357,7 +366,7 @@ char* g_LBOS_GetLBOSAddress(void); * First method to try. * @param[in] lbos_addr * String with "%hostname%:%port%" or "%IP%:%port%". If priority_find_method - * is set to eLBOSFindMethod_CustomHost, lbos_addr should be non-NULL + * is set to eLBOS_FindMethod_CustomHost, lbos_addr should be non-NULL * (or else the method will be ignored) * @return * LBOS address that needs to be free()'d by the caller. @@ -392,7 +401,7 @@ const SSERV_VTable* SERV_LBOS_Open(SERV_ITER iter, * true - string is NULL or empty; * false - string exists and contains elements. */ NCBI_XCONNECT_EXPORT -int/*bool*/ g_LBOS_StringIsNullOrEmpty(const char* const str); +int/*bool*/ g_LBOS_StringIsNullOrEmpty(const char* str); /** Compose LBOS address from /etc/ncbi/{role, domain}. @@ -402,7 +411,7 @@ NCBI_XCONNECT_EXPORT char* g_LBOS_ComposeLBOSAddress(void); -/** Set primary method how to find LBOS. Default is eLBOSFindMethod_Registry. +/** Set primary method how to find LBOS. Default is eLBOS_FindMethod_Registry. * @param[in] iter * Iterator that represents current request to LBOS. * @param[in] method @@ -416,7 +425,7 @@ int/*bool*/ g_LBOS_UnitTesting_SetLBOSFindMethod(SERV_ITER iter, /** Set custom host for LBOS. It will be used when method - * eLBOSFindMethod_CustomHost is used. + * eLBOS_FindMethod_CustomHost is used. * @param[in] iter * Iterator that represents current request to LBOS. * @param[in] address @@ -430,22 +439,14 @@ int/*bool*/ g_LBOS_UnitTesting_SetLBOSaddress(SERV_ITER iter, /** Set custom files to load role and domain from, respectively. - * @param roleFile[in] - * To change role file path, pass it here. To use current role file path, - * pass NULL. - * @param domainFile[in] - * To change domain file path, pass it here. To use current domain file path, - * pass NULL. * @param lbosresolverFile[in] * To change lbosresolver file path, pass it here. To use current * lbosresolver file path, pass NULL. * @return - * false - something went wrong, values not changed; + * false - values not changed; * true - success. */ NCBI_XCONNECT_EXPORT int/*bool*/ -g_LBOS_UnitTesting_SetLBOSRoleDomainResolverFile(const char* roleFile, - const char* domainFile, - const char* lbosresolverFile); +g_LBOS_UnitTesting_SetLBOSResolverFile(const char* lbosresolverFile); /** Checks iterator, fact that iterator belongs to this client, iterator data. @@ -576,22 +577,6 @@ NCBI_XCONNECT_EXPORT int g_LBOS_UnitTesting_GetAnnouncedServersNum(void); -/** Pointer to s_LBOS_CurrentDomain - * @return - * address of static variable s_LBOS_CurrentDomain. - * @see */ -NCBI_XCONNECT_EXPORT -char** g_LBOS_UnitTesting_CurrentDomain(void); - - -/** Pointer to s_LBOS_CurrentRole - * @return - * address of static variable s_LBOS_CurrentRole. - * @see */ -NCBI_XCONNECT_EXPORT -char** g_LBOS_UnitTesting_CurrentRole(void); - - /** Pointer to s_LBOS_Lbosresolver * @return * address of static variable s_LBOS_Lbosresolver. diff --git a/c++/src/connect/ncbi_lbosp.hpp b/c++/src/connect/ncbi_lbosp.hpp index 7de44ec7..27bd795b 100644 --- a/c++/src/connect/ncbi_lbosp.hpp +++ b/c++/src/connect/ncbi_lbosp.hpp @@ -41,7 +41,9 @@ BEGIN_NCBI_SCOPE class CLBOSIpCacheKey { public: - CLBOSIpCacheKey(string service, string hostname, string version, + CLBOSIpCacheKey(const string& service, + const string& hostname, + const string& version, unsigned short port); bool operator==(const CLBOSIpCacheKey& rh) const; @@ -63,33 +65,80 @@ public: /** Search the cache for previously resolved hostname with a given * service name, version, port. If not found - return the same hostname. */ - static - string HostnameTryFind(string service, string hostname, string version, - unsigned short port); + static string HostnameTryFind(const string& service, + const string& hostname, + const string& version, + unsigned short port); /** Search the cache for previously resolved hostname with a given * service name, version, port. If not found - resolve, cache and return * result. */ - static - string HostnameResolve(string service, string hostname, - string version, unsigned short port); + static string HostnameResolve(const string& service, + const string& hostname, + const string& version, + unsigned short port); /** We do not need to store hostname<->IP record after the server is * de-announced. So we just make sure that we delete the record only one * time, in case if many threads are going to delete it at the same * moment */ - static - void HostnameDelete(string service, string hostname, string version, - unsigned short port); + static void HostnameDelete(const string& service, + const string& hostname, + const string& version, + unsigned short port); private: - static CSafeStatic< map< CLBOSIpCacheKey, string > > x_IpCache; + static CSafeStatic< map< CLBOSIpCacheKey, string > > sm_IpCache; }; +/* Private API of LBOS */ +class NCBI_XCONNECT_EXPORT LBOSPrivate +{ +public: + /** Get global config for a service name. + * @note It does not change anything in the global DTab configuration. + * @param service[in] + * Name of service for which to get default version. + * @return + * Current default version. Can be an empty string + * @exception CLBOSException + * Throw on any error. Note: if the service is present in DTab but it has + * no default version, then "eBadVersion" code will be used. + * @note + * Config can be of 3 types: empty string, path or version + */ + static string GetServiceVersion(const string& service, + bool* exists = NULL); + + + /** Set default version for a service in the global DTab configuration. + * @param[in] service + * Name of service for which to change the default version. + * @param new_version[out] + * Version that will be used by default for specified service. + * @return + * Previously set default version. + */ + static string SetServiceVersion(const string& service, + const string& new_version, + bool* existed = NULL); + + + /** Remove service from the global DTab configuration configuration. + * @note Its default version will become empty. + * @param[in] service + * Name of service to delete from the global DTab configuration. + * @return + * Previously set default version. + */ + static string DeleteServiceVersion(const string& service, + bool* existed = NULL); +}; + END_NCBI_SCOPE diff --git a/c++/src/connect/ncbi_monkey.cpp b/c++/src/connect/ncbi_monkey.cpp new file mode 100644 index 00000000..683015e0 --- /dev/null +++ b/c++/src/connect/ncbi_monkey.cpp @@ -0,0 +1,1681 @@ +/* $Id: ncbi_monkey.cpp 505633 2016-06-27 19:28:13Z elisovdn $ +* =========================================================================== +* +* PUBLIC DOMAIN NOTICE +* National Center for Biotechnology Information +* +* This software/database is a "United States Government Work" under the +* terms of the United States Copyright Act. It was written as part of +* the author's official duties as a United States Government employee and +* thus cannot be copyrighted. This software/database is freely available +* to the public for use. The National Library of Medicine and the U.S. +* Government have not placed any restriction on its use or reproduction. +* +* Although all reasonable efforts have been taken to ensure the accuracy +* and reliability of the software and data, the NLM and the U.S. +* Government do not and cannot warrant the performance or results that +* may be obtained by using this software or data. The NLM and the U.S. +* Government disclaim all warranties, express or implied, including +* warranties of performance, merchantability or fitness for any particular +* purpose. +* +* Please cite the author in any work or product based on this material. +* +* =========================================================================== +* +* Author: Dmitriy Elisov +* +* File Description: +* Chaos Monkey - a library that is hooked with ncbi_socket.c and introduces +* problems in network connectivity - losses, bad data, delays. +* difficulties +* +*/ + +#include + +#include "ncbi_priv.h" + +#ifdef NCBI_MONKEY +# include +# include +# include +# include +# include +# include +# include +# include "ncbi_monkeyp.hpp" +# include + +/* OS-dependent way to set socket errors */ +# ifdef NCBI_OS_MSWIN +# define MONKEY_SET_SOCKET_ERROR(error) WSASetLastError(error) +# define MONKEY_ENOPROTOOPT WSAENOPROTOOPT +# else +# define MONKEY_SET_SOCKET_ERROR(error) errno = error +# define MONKEY_ENOPROTOOPT ENOPROTOOPT +# endif /* NCBI_OS_MSWIN */ + +/* Include OS-specific headers */ +# ifdef NCBI_OS_MSWIN +# include +# else +# include +# include +# include +# include +# endif /* NCBI_OS_MSWIN */ + + +BEGIN_NCBI_SCOPE + +DEFINE_STATIC_FAST_MUTEX(s_ConfigMutex); +DEFINE_STATIC_FAST_MUTEX(s_SeedLogConfigMutex); +DEFINE_STATIC_FAST_MUTEX(s_SingletonMutex); +DEFINE_STATIC_FAST_MUTEX(s_KnownConnMutex); +static CSocket* s_TimeoutingSock = NULL; +static CSocket* s_PeerSock = NULL; +const int kRandCount = 100; +/* Registry names */ +const string kMonkeyMainSect = "CHAOS_MONKEY"; +const string kEnablField = "enabled"; +const string kSeedField = "seed"; + +/*///////////////////////////////////////////////////////////////////////////// +// MOCK DEFINITIONS // +/////////////////////////////////////////////////////////////////////////////*/ +# ifdef NCBI_MONKEY_TESTS +# undef DECLARE_MONKEY_MOCK +/* Declare a static variable and global getter&setter for it */ +# define DECLARE_MONKEY_MOCK(ty,name,def_val) \ + static ty s_Monkey_ ## name = def_val; \ + ty g_MonkeyMock_Get ## name() { \ + return s_Monkey_ ## name; \ + } \ + void g_MonkeyMock_Set ## name(const ty& val) { \ + s_Monkey_ ## name = val; \ + } + +/* This macro contains the list of variables to be mocked. Needed mocks will + * be created with DECLARE_MONKEY_MOCK + */ +MONKEY_MOCK_MACRO() + +# endif /* NCBI_MONKEY_TESTS */ +/*///////////////////////////////////////////////////////////////////////////// +// STATIC CONVENIENCE FUNCTIONS // +/////////////////////////////////////////////////////////////////////////////*/ +static vector& s_Monkey_Split(const string &s, + char delim, + vector &elems) +{ + g_MonkeyMock_SetInterceptedPoll(false); + stringstream ss(s); + string item; + while (getline(ss, item, delim)) { + elems.push_back(item); + } + return elems; +} + + +/* Trash collector for Thread Local Storage */ +template +static void s_TlsCleanup(T* p_value, void* /* data */) +{ + delete p_value; +} + + +static void s_TimeoutingSocketInit(void) +{ + unsigned short i = 8080; + CListeningSocket* server_socket; + + for (; i < 8100; i++) { + /* Initialize a timeouting socket */ + try { + server_socket = new CListeningSocket(i); + } catch (CException) { + continue; + } + STimeout accept_timeout = { 0, 20000 }; + STimeout connect_timeout = { 1, 20000 }; + if (server_socket->GetStatus() != eIO_Success) { + server_socket->Close(); + delete server_socket; + continue; + } + try { + s_TimeoutingSock = new CSocket(CSocketAPI::gethostbyaddr(0), i, + &connect_timeout); + } catch (CException) { + continue; + } + s_PeerSock = new CSocket; + if (server_socket->Accept(*s_PeerSock, &accept_timeout) == eIO_Success) { + server_socket->Close(); + delete server_socket; + char buf[1024]; + size_t n_read; + s_TimeoutingSock->SetTimeout(eIO_Read, &accept_timeout); + s_TimeoutingSock->SetTimeout(eIO_Write, &accept_timeout); + s_TimeoutingSock->Read((void*)buf, 1024, &n_read); + return; + } else { + s_TimeoutingSock->Close(); + delete s_TimeoutingSock; + s_PeerSock->Close(); + delete s_PeerSock; + server_socket->Close(); + delete server_socket; + continue; + } + /* If we got here, everything works fine */ + } + throw CMonkeyException(CDiagCompileInfo(), NULL, + CMonkeyException::e_MonkeyUnknown, + "Could not create a peer socket for the " + "timeouting socket. Tried ports 8080-8100", + ncbi::EDiagSev::eDiagSevMin); +} + + +static void s_TimeoutingSocketDestroy(void) +{ + if (s_TimeoutingSock != NULL) { + s_TimeoutingSock->Close(); + delete s_TimeoutingSock; + s_TimeoutingSock = NULL; + } + if (s_PeerSock != NULL) { + s_PeerSock->Close(); + delete s_PeerSock; + s_PeerSock = NULL; + } +} + + +static string s_GetMonkeySection() +{ + CNcbiRegistry& config = CNcbiApplication::Instance()->GetConfig(); + return config.Get(kMonkeyMainSect, "config"); +} + + +static vector s_Monkey_Split(const string &s, char delim) { + vector elems; + s_Monkey_Split(s, delim, elems); + return elems; +} + + +static void s_MONKEY_GenRandomString(char *s, const size_t len) { + static const char alphabet[] = + "0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + " !@#$%^&*()-=_+/,.{}[];':`~<>" + "\\\n\""; + + for (size_t i = 0; i < len - 1; ++i) { + s[i] = alphabet[rand() % (sizeof(alphabet) - 1)]; + } + + s[len-1] = 0; +} + + +static void s_GetSocketDestinations(MONKEY_SOCKTYPE sock, + string* fqdn, + string* IP, + unsigned short* my_port, + unsigned short* peer_port) +{ + struct sockaddr_in sock_addr; +#ifdef NCBI_OS_MSWIN + int len_inet = sizeof(sock_addr); +#else + socklen_t len_inet = sizeof(sock_addr); +#endif + if (my_port != NULL) { + getsockname(sock, (struct sockaddr*)&sock_addr, &len_inet); + *my_port = ntohs(sock_addr.sin_port); + } + /* If we need peer information for at least one value */ + if (peer_port || fqdn || IP) + getpeername(sock, (struct sockaddr*)&sock_addr, &len_inet); + if (peer_port != NULL) + *peer_port = ntohs(sock_addr.sin_port); +#ifndef NCBI_OS_MSWIN + uint32_t addr = sock_addr.sin_addr.s_addr; +#else + u_long addr = sock_addr.sin_addr.S_un.S_addr; +#endif + if (fqdn != NULL) + *fqdn = CSocketAPI::gethostbyaddr (addr); + if (IP != NULL) + *IP = CSocketAPI::HostPortToString(addr, 0); +} + + +#if 0 +# ifdef NCBI_OS_MSWIN +static +int s_MONKEY_GetTimeOfDay(struct timeval* tv) +{ + FILETIME systime; + unsigned __int64 sysusec; + + if (!tv) + return -1; + + GetSystemTimeAsFileTime(&systime); + + sysusec = systime.dwHighDateTime; + sysusec <<= 32; + sysusec |= systime.dwLowDateTime; + sysusec += 5; + sysusec /= 10; + + tv->tv_usec = (long)(sysusec % 1000000); + tv->tv_sec = (long)(sysusec / 1000000 - 11644473600Ui64); + + return 0; +} + +# else + +# define s_MONKEY_GetTimeOfDay(tv) gettimeofday(tv, 0) + +# endif + +static +double s_MONKEY_TimeDiff(const struct timeval* end, +const struct timeval* beg) +{ + if (end->tv_sec < beg->tv_sec) + return 0.0; + if (end->tv_usec < beg->tv_usec) { + if (end->tv_sec == beg->tv_sec) + return 0.0; + return (end->tv_sec - beg->tv_sec - 1) + + (end->tv_usec - beg->tv_usec + 1000000) / 1000000.0; + } + return (end->tv_sec - beg->tv_sec) + + (end->tv_usec - beg->tv_usec) / 1000000.0; +} +#endif + + +/*////////////////////////////////////////////////////////////////////////////// +// CMonkeySeedKey // +//////////////////////////////////////////////////////////////////////////////*/ +const CMonkeySeedKey& CMonkeySeedAccessor::Key() +{ + static CMonkeySeedKey key; + return key; +} + + +/*////////////////////////////////////////////////////////////////////////////// +// CMonkeyException // +//////////////////////////////////////////////////////////////////////////////*/ +const char* CMonkeyException::what() const throw() +{ + return m_Message.c_str(); +} + + +/*////////////////////////////////////////////////////////////////////////////// +// CMonkeyRuleBase // +//////////////////////////////////////////////////////////////////////////////*/ +CMonkeyRuleBase::CMonkeyRuleBase(EMonkeyActionType action_type, + const vector& params) + : m_ReturnStatus(-1), m_RepeatType(eMonkey_RepeatNone), m_Delay (0), + m_RunsSize(0), m_ActionType(action_type) +{ + /** If there are no-interception runs before repeating the cycle, + * we know that from m_RunsSize */ + for (unsigned int i = 0; i < params.size(); i++) { + vector name_value = s_Monkey_Split(params[i], '='); + string name = name_value[0]; + string value = name_value[1]; + if (name == "return_status") { + x_ReadEIOStatus(value); + } else if (name == "runs") { + x_ReadRuns(value); + } else if (name == "delay") { + m_Delay = NStr::StringToULong(value); + } + } +} + + +static string s_PrintActionType(EMonkeyActionType action) { + switch (action) + { + case eMonkey_Recv: + return "recv()"; + case eMonkey_Send: + return "send()"; + case eMonkey_Poll: + return "poll()"; + case eMonkey_Connect: + return "connect()"; + default: + throw CMonkeyException( + CDiagCompileInfo(__FILE__, __LINE__), + NULL, CMonkeyException::e_MonkeyInvalidArgs, + string("Unknown EMonkeyActionType value")); + } +} + + +void CMonkeyRuleBase::AddSocket(MONKEY_SOCKTYPE sock) +{ + /* Element has to exist */ + m_RunPos[sock]; +} + +/** Check that the rule should trigger on this run */ +bool CMonkeyRuleBase::CheckRun(MONKEY_SOCKTYPE sock, + unsigned short probability_left) const +{ + bool isRun = false; + + int rand_val = CMonkey::Instance()->GetRand(Key()); + isRun = (rand_val % 100) < GetProbability(sock) * 100 / probability_left; + LOG_POST(Note << "[CMonkeyRuleBase::CheckRun] Checking if the rule " + << "for " << s_PrintActionType(m_ActionType) + << " will be run this time. Random value is " + << rand_val << ", probability threshold is " + << m_Runs.at(m_RunPos.at(sock)) * 100); + LOG_POST(Note << "[CMonkeyRuleBase::CheckRun] The rule will be " + << (isRun ? "" : "NOT ") << "run"); + return isRun; +} + + +unsigned short CMonkeyRuleBase::GetProbability(MONKEY_SOCKTYPE sock) const +{ + if (m_RunPos.find(sock) == m_RunPos.end()) { + throw CMonkeyException( + CDiagCompileInfo(__FILE__, __LINE__), + NULL, CMonkeyException::e_MonkeyInvalidArgs, + "The socket provided has not been registered with current rule"); + } + if (m_RunMode == eMonkey_RunProbability) { + return static_cast(m_Runs.at(m_RunPos.at(sock)) * 100); + } else { + if ((m_RunPos.at(sock) + 1) > *m_Runs.rbegin()) { + switch (m_RepeatType) { + case eMonkey_RepeatNone: + return 0; + case eMonkey_RepeatLast: + return 100; + } + } + /* If m_Runs has the exact number of current run, the rule triggers */ + return std::binary_search(m_Runs.begin(), + m_Runs.end(), + m_RunPos.at(sock) + 1) ? 100 : 0; + } + /* If "runs" is not set, rule always triggers */ + if (m_Runs.empty()) return 100; + +} + +void CMonkeyRuleBase::x_ReadEIOStatus(const string& eIOStatus_in) +{ + string eIOStatus = eIOStatus_in; + NStr::ToLower(eIOStatus); + if (eIOStatus == "eio_closed") { + m_ReturnStatus = eIO_Closed; + } else if (eIOStatus == "eio_invalidarg") { + m_ReturnStatus = eIO_InvalidArg; + } else if (eIOStatus == "eio_interrupt") { + m_ReturnStatus = eIO_Interrupt; + } else if (eIOStatus == "eio_success") { + m_ReturnStatus = eIO_Success; + } else if (eIOStatus == "eio_timeout") { + m_ReturnStatus = eIO_Timeout; + } else if (eIOStatus == "eio_unknown") { + m_ReturnStatus = eIO_Unknown; + } else if (eIOStatus == "eio_notsupported") { + m_ReturnStatus = eIO_NotSupported; + } else { + throw CMonkeyException( + CDiagCompileInfo(__FILE__, __LINE__), + NULL, CMonkeyException::e_MonkeyInvalidArgs, + string("Could not parse 'return_status': ") + eIOStatus_in); + } +} + + +void CMonkeyRuleBase::x_ReadRuns(const string& runs) +{ + /* We get the string already without whitespaces and only have to + split it on commas*/ + vector runs_list = s_Monkey_Split(runs, ','); + if (runs_list.size() == 0) + throw CMonkeyException( + CDiagCompileInfo(__FILE__, __LINE__), + NULL, CMonkeyException::e_MonkeyInvalidArgs, + string("\"Runs\" parameter is empty")); + if (runs_list.size() == 1) + runs_list.push_back("..."); + m_RunMode = runs_list[0][runs_list[0].length() - 1] == '%' + ? eMonkey_RunProbability : eMonkey_RunNumber; + + m_RepeatType = eMonkey_RepeatNone; + if ( *runs_list.rbegin() == "repeat" ) { + m_RepeatType = eMonkey_RepeatAgain; + } else if ( *runs_list.rbegin() == "..." ) { + m_RepeatType = eMonkey_RepeatLast; + } + + ERunFormat run_format = runs_list[0].find_first_of(':') != string::npos ? + eMonkey_RunRanges : + eMonkey_RunSequence; + + unsigned int end_pos = (m_RepeatType == eMonkey_RepeatNone) + ? runs_list.size() : runs_list.size() - 1; + + for ( unsigned int i = 0; i < end_pos; i++ ) { + string& run = runs_list[i]; + double prob; + if (m_RunMode == eMonkey_RunProbability) { + if (*run.rbegin() != '%') { + throw CMonkeyException( + CDiagCompileInfo(__FILE__, __LINE__), + NULL, CMonkeyException::e_MonkeyInvalidArgs, + "Value is not percentage: " + run + + ", values have to be either only percentages or " + "only numbers of tries, not mixed"); + } + switch (run_format) { + default: + assert(0); + /* In release build - fall through to eMonkey_RunSequence */ + case eMonkey_RunSequence: + prob = NStr::StringToDouble(run.substr(0, run.length() - 1)); + m_Runs.push_back(prob / 100); + break; + case eMonkey_RunRanges: + size_t prob_start = run.find_first_of(':'); + size_t step = NStr::StringToSizet(run.substr(0, prob_start)); + size_t last_step = m_Runs.size(); + if (last_step == 0 && step != 1) { + throw CMonkeyException( + CDiagCompileInfo(__FILE__, __LINE__), + NULL, CMonkeyException::e_MonkeyInvalidArgs, + "In the string of runs: " + runs + " the first " + "element MUST set value for the first run"); + } + prob = NStr::StringToDouble(run.substr(prob_start+1, run.length() - prob_start - 2)); + for (size_t j = last_step+1; j > 0 && j < step; j++) { + m_Runs.push_back(*m_Runs.rbegin()); + } + m_Runs.push_back(prob / 100); + break; + } + } else { + assert(run_format == eMonkey_RunSequence); + if (*run.rbegin() == '%') { + throw CMonkeyException( + CDiagCompileInfo(__FILE__, __LINE__), + NULL, CMonkeyException::e_MonkeyInvalidArgs, + string("Value is percentage: ") + run + + string(", values have to be either only percentages or " + "only numbers of tries, not mixed")); + } + int val = NStr::StringToInt(run); + if (m_Runs.size() > 0 && val <= *m_Runs.rbegin()) { + throw CMonkeyException( + CDiagCompileInfo(__FILE__, __LINE__), + NULL, CMonkeyException::e_MonkeyInvalidArgs, + string("\"runs\" should contain values in " + "increasing order")); + } + m_Runs.push_back(val); + } + } +} + + +int /* EIO_Status or -1 */ CMonkeyRuleBase::GetReturnStatus() const +{ + return m_ReturnStatus; +} + + +unsigned long CMonkeyRuleBase::GetDelay() const +{ + return m_Delay; +} + + +void CMonkeyRuleBase::IterateRun(MONKEY_SOCKTYPE sock) +{ + if (m_Runs.empty()) + return; + m_RunPos[sock]++; + /* In probability mode each item of m_Runs is a probability of each run */ + if (m_RunMode == eMonkey_RunProbability) { + assert(m_RunPos[sock] <= m_Runs.size()); + if (m_RunPos[sock] == m_Runs.size()) { + switch (m_RepeatType) { + case eMonkey_RepeatNone: case eMonkey_RepeatLast: + m_RunPos[sock]--; + case eMonkey_RepeatAgain: + m_RunPos[sock] = 0; + break; + } + } + return; + } + /* In "number of the run" mode each item in m_Runs is a specific number of + run when the rule should trigger */ + else if ((m_RunPos.at(sock) + 1) > *m_Runs.rbegin()) { + switch (m_RepeatType) { + case eMonkey_RepeatAgain: + m_RunPos[sock] = 0; + break; + } + } + return; +} + + +/*////////////////////////////////////////////////////////////////////////////// +// CMonkeyRWRuleBase // +//////////////////////////////////////////////////////////////////////////////*/ +CMonkeyRWRuleBase::CMonkeyRWRuleBase(EMonkeyActionType action_type, + const vector& params) + : CMonkeyRuleBase(action_type, params), m_Text(""), m_TextLength(0), + m_Garbage(false), m_FillType(eMonkey_FillRepeat) +{ + for ( unsigned int i = 0; i < params.size(); i++ ) { + vector name_value = s_Monkey_Split(params[i], '='); + string name = name_value[0]; + string value = name_value[1]; + if (name == "text") { + if (GetReturnStatus() != eIO_Success && GetReturnStatus() != -1) { + throw CMonkeyException( + CDiagCompileInfo(__FILE__, __LINE__), + NULL, CMonkeyException::e_MonkeyInvalidArgs, + string("Return error status is set in Rule, cannot " + "set 'text' parameter")); + } + if (value == "garbage") { + m_Garbage = true; + } + /* The text should start and finish with ' or " */ + else if ( value[0] == value[value.length() - 1] + && (value[0] == '\'' || value[0] == '\"') ) + { + m_Garbage = false; + m_Text = value.substr(1, value.length() - 2); + } else { + throw CMonkeyException( + CDiagCompileInfo(__FILE__, __LINE__), + NULL, CMonkeyException::e_MonkeyInvalidArgs, + string("Could not parse 'text' for Rule: ") + value); + } + } else if (name == "text_length") { + m_TextLength = NStr::StringToInt(value); + } else if (name == "fill") { + if (value == "last_letter") { + m_FillType = eMonkey_FillLastLetter; + } else if (name == "repeat") { + m_FillType = eMonkey_FillRepeat; + } + } + } + /* Checking that everything was set */ + if (GetReturnStatus() == eIO_Success && m_Text == "") { + throw CMonkeyException( + CDiagCompileInfo(__FILE__, __LINE__), + NULL, CMonkeyException::e_MonkeyInvalidArgs, + string("Parameter 'text' not set to a non-empty value for rule, " + "but 'return_status' set to eIO_Success requires 'text' to " + "be set")); + } + if (GetReturnStatus() == -1 && m_Text == "") { + throw CMonkeyException( + CDiagCompileInfo(__FILE__, __LINE__), + NULL, CMonkeyException::e_MonkeyInvalidArgs, + string("Parameter 'text' not set to a non-empty value for rule, " + "but 'return_status' not set requires 'text' to " + "be set")); + } +} + + +void CMonkeyRWRuleBase::x_ReadFill(const string& fill_str) +{ + string fill = fill_str; + if (NStr::ToLower(fill) == "repeat") { + m_FillType = eMonkey_FillRepeat; + } + if (NStr::ToLower(fill) == "last_letter") { + m_FillType = eMonkey_FillLastLetter; + } +} + + +string CMonkeyRWRuleBase::GetText() const +{ + return m_Text; +} + + +size_t CMonkeyRWRuleBase::GetTextLength() const +{ + return m_TextLength; +} + + +bool CMonkeyRWRuleBase::GetGarbage() const +{ + return m_Garbage; +} + + +CMonkeyRWRuleBase::EFillType CMonkeyRWRuleBase::GetFillType() const +{ + return m_FillType; +} + + +////////////////////////////////////////////////////////////////////////// +// CMonkeyWriteRule +////////////////////////////////////////////////////////////////////////// +CMonkeyWriteRule::CMonkeyWriteRule(const vector& params) + : CMonkeyRWRuleBase(eMonkey_Send, params) +{ +} + + +MONKEY_RETTYPE CMonkeyWriteRule::Run(MONKEY_SOCKTYPE sock, + const MONKEY_DATATYPE data, + MONKEY_LENTYPE size, + int flags, + SOCK* sock_ptr) +{ +#ifdef NCBI_MONKEY_TESTS + g_MonkeyMock_SetInterceptedSend(true); +#endif /* NCBI_MONKEY_TESTS */ + LOG_POST(Error << "[CMonkeyWriteRule::Run] CHAOS MONKEY ENGAGE!!! " + "INTERCEPTED send()"); + int return_status = GetReturnStatus(); + if (return_status != eIO_Success && return_status != -1) { + switch (return_status) { + case eIO_Timeout: + *sock_ptr = s_TimeoutingSock->GetSOCK(); + MONKEY_SET_SOCKET_ERROR(SOCK_EWOULDBLOCK); + return -1; + case eIO_Closed: + MONKEY_SET_SOCKET_ERROR(SOCK_ENOTCONN); + return -1; + case eIO_Unknown: + MONKEY_SET_SOCKET_ERROR(MONKEY_ENOPROTOOPT); + return -1; + default: + break; + } + } + + /* We cannot write more than the user asked */ + size_t max_size; + if (GetTextLength() == 0) { + max_size = min(GetTextLength(), (size_t)size); + } + else { + max_size = size; + } + /* Fill data */ + void* new_data = (char*)malloc(max_size * sizeof(char)); + if (GetGarbage()) { + s_MONKEY_GenRandomString((char*)new_data, max_size); + } else { + string text = GetText(); + if (GetFillType() == CMonkeyRWRuleBase::eMonkey_FillRepeat) { + text += text; + text = text.substr(0, max_size); + } + if (GetFillType() == CMonkeyRWRuleBase::eMonkey_FillLastLetter) + text.insert(text.length() - 1, max_size - text.length(), + text[text.length()-1]); + memcpy(new_data, text.c_str(), max_size); + } + return send(sock, (const char*)new_data, size, flags); +} + + +////////////////////////////////////////////////////////////////////////// +// CMonkeyReadRule +////////////////////////////////////////////////////////////////////////// +CMonkeyReadRule::CMonkeyReadRule(const vector& params) + : CMonkeyRWRuleBase(eMonkey_Recv, params) +{ + STimeout r_timeout = { 1, 0 }; +} + + +MONKEY_RETTYPE CMonkeyReadRule::Run(MONKEY_SOCKTYPE sock, + MONKEY_DATATYPE buf, + MONKEY_LENTYPE size, + int flags, + SOCK* sock_ptr) +{ +#ifdef NCBI_MONKEY_TESTS + g_MonkeyMock_SetInterceptedRecv(true); +#endif /* NCBI_MONKEY_TESTS */ + LOG_POST(Error << "[CMonkeyReadRule::Run] CHAOS MONKEY ENGAGE!!! " + "INTERCEPTED recv()"); + int return_status = GetReturnStatus(); + if (return_status != eIO_Success && return_status != -1) { + switch (return_status) { + case eIO_Timeout: + *sock_ptr = s_TimeoutingSock->GetSOCK(); + MONKEY_SET_SOCKET_ERROR(SOCK_EWOULDBLOCK); + return -1; + case eIO_Closed: + MONKEY_SET_SOCKET_ERROR(SOCK_ENOTCONN); + return -1; + case eIO_Unknown: + MONKEY_SET_SOCKET_ERROR(MONKEY_ENOPROTOOPT); + return -1; + default: + break; + } + } + + if (size == 0) + return 0; + + /* So we decided to override */ + MONKEY_RETTYPE bytes_read = recv(sock, buf, size, flags); + + /* We cannot resize the buffer since it can be a local array, so we have to + * decrease monkey text length instead */ + size_t max_size = min(GetTextLength() - 1, static_cast(size) - 1); + /* Replace data */ + if (GetGarbage()) { + s_MONKEY_GenRandomString((char*)buf, max_size); + } else { + string text = GetText(); + if (GetFillType() == CMonkeyRWRuleBase::eMonkey_FillRepeat) { + text += text; + text = text.substr(0, GetTextLength()); + } + if (GetFillType() == CMonkeyRWRuleBase::eMonkey_FillLastLetter) + text.insert(text.length()-1, GetTextLength() - text.length(), + text[text.length()-1]); + memcpy(buf, text.c_str(), GetTextLength()); + } + + return bytes_read; +} + + +////////////////////////////////////////////////////////////////////////// +// CMonkeyConnectRule +////////////////////////////////////////////////////////////////////////// + +CMonkeyConnectRule::CMonkeyConnectRule(const vector& params) + : CMonkeyRuleBase(eMonkey_Connect, params) +{ + for (unsigned int i = 0; i < params.size(); i++) { + vector name_value = s_Monkey_Split(params[i], '='); + string name = name_value[0]; + string value = name_value[1]; + if (name == "allow") { + m_Allow = ConnNetInfo_Boolean(value.c_str()) == 1; + } + } +} + + +int CMonkeyConnectRule::Run(MONKEY_SOCKTYPE sock, + const struct sockaddr* name, + MONKEY_SOCKLENTYPE namelen) +{ +#ifdef NCBI_MONKEY_TESTS + g_MonkeyMock_SetInterceptedConnect(true); +#endif /* NCBI_MONKEY_TESTS */ + LOG_POST(Error << "[CMonkeyConnectRule::Run] CHAOS MONKEY ENGAGE!!! " + "INTERCEPTED connect()"); + int return_status = GetReturnStatus(); + if (return_status != eIO_Success && return_status != -1) { + switch (return_status) { + case eIO_Timeout: + MONKEY_SET_SOCKET_ERROR(SOCK_EWOULDBLOCK); + return -1; + case eIO_Closed: + MONKEY_SET_SOCKET_ERROR(SOCK_ECONNREFUSED); + return -1; + case eIO_Unknown: + MONKEY_SET_SOCKET_ERROR(MONKEY_ENOPROTOOPT); + return -1; + case eIO_Interrupt: + MONKEY_SET_SOCKET_ERROR(SOCK_EINTR); + return -1; + default: + break; + } + } + if (GetDelay() > 0) { + SleepMilliSec(GetDelay(), EInterruptOnSignal::eInterruptOnSignal); + } + if (m_Allow) { + return connect(sock, name, namelen); + } + else { + struct sockaddr_in addr; + /* Connect to a non-existing host */ + addr.sin_family = AF_INET; + addr.sin_port = 65511; + /* 3232235631 is 192.168.0.111 - does not exist at NCBI, which is + enough for the goal of test */ +#ifdef NCBI_OS_MSWIN + addr.sin_addr.S_un.S_addr = htonl(3232235631); +#else + addr.sin_addr.s_addr = htonl(3232235631); +#endif /* NCBI_OS_MSWIN */ + return connect(sock, (struct sockaddr*)&addr, namelen); + } +} + + +////////////////////////////////////////////////////////////////////////// +// CMonkeyPollRule +////////////////////////////////////////////////////////////////////////// +CMonkeyPollRule::CMonkeyPollRule(const vector& params) + : CMonkeyRuleBase(eMonkey_Poll, params) +{ +#ifdef NCBI_MONKEY_TESTS + g_MonkeyMock_SetInterceptedPoll(true); +#endif /* NCBI_MONKEY_TESTS */ + for ( unsigned int i = 0; i < params.size(); i++ ) { + vector name_value = s_Monkey_Split(params[i], '='); + string name = name_value[0]; + string value = name_value[1]; + if (name == "ignore") { + m_Ignore = ConnNetInfo_Boolean(value.c_str()) == 1; + } + } +} + + +bool CMonkeyPollRule::Run(size_t* n, + SOCK* sock, + EIO_Status* return_status) +{ + LOG_POST(Error << "[CMonkeyPollRule::Run] CHAOS MONKEY ENGAGE!!! " + "INTERCEPTED poll()"); + if (m_Ignore) { + return true; + } + return false; +} + + +////////////////////////////////////////////////////////////////////////// +// CMonkeyPlan +////////////////////////////////////////////////////////////////////////// +CMonkeyPlan::CMonkeyPlan(const string& section) + : m_Probability(100), m_HostRegex(".*"), m_Name(section) +{ + /* Plan settings */ + CNcbiRegistry& config = CNcbiApplication::Instance()->GetConfig(); + string probability = config.Get(section, "probability"); + if (probability != "") { + if (probability.find('%') != string::npos) { + probability = probability.substr(0, probability.length() - 1); + m_Probability = static_cast( + NStr::StringToUInt(probability)); + } else { + m_Probability = static_cast( + NStr::StringToDouble(probability) * 100); + } + } + m_HostRegex = NStr::Replace(NStr::Replace( + config.Get(section, "host_match"), " ", ""), + "\t", ""); + + x_ReadPortRange(config.Get(section, "port_match")); + + /* Write rules */ + x_LoadRules(section, "write", m_WriteRules); + /* Read rules */ + x_LoadRules(section, "read", m_ReadRules); + /* Connect rules */ + x_LoadRules(section, "connect", m_ConnectRules); + /* Poll rules */ + x_LoadRules(section, "poll", m_PollRules); +} + + +template +void CMonkeyPlan::x_LoadRules(const string& section, + const string& rule_type_str, + vector& container) +{ + CNcbiRegistry& config = CNcbiApplication::Instance()->GetConfig(); + bool multi_rule = false; + string rule_str = config.Get(section, rule_type_str); + if (rule_str == "") { + /* Try check if there are multiple rules defined */ + if ((rule_str = config.Get(section, rule_type_str + "1")) != "") + multi_rule = true; + } + if ( rule_str == "" ) + return; + /* If a rule was read - parse it */ + string temp_conf = NStr::Replace(rule_str, string(" "), string("")); + vector params = s_Monkey_Split(temp_conf, ';'); + container.push_back(Rule_Ty(params)); + if ( multi_rule ) { + int rule_num = 2; + string val_name = rule_type_str + NStr::IntToString(rule_num++); + while ( (rule_str = config.Get(section, val_name)) != "" ) { + temp_conf = NStr::Replace(rule_str, string(" "), string("")); + params = s_Monkey_Split(temp_conf, ';'); + container.push_back(Rule_Ty(params)); + val_name = rule_type_str+ NStr::IntToString(rule_num++); + } + } +} + +#ifndef NCBI_OS_MSWIN +/** Regex-like check (might use some refactoring) */ +static bool s_MatchRegex(const string& to_match, const string& regex) +{ + /* Convert "match regex" task to "haystack and needle" task. We check + * whether there is a wildcard in the beginning and/or in the end of + * regex (other cases are not supported). And then check if to_match + * starts with, end with or contains the needle */ + + /* First - compatibility check. Functionality is limited. */ + /* Check for special characters and combinations that cannot be processed. + * Method - remove combinations of characters that are supported and check + * the rest */ + string exception_message = string("Pattern") + regex + " " + "cannot be processed because regular expressions " + "are not fully supported. You can use .* in the " + "beginning and in the end of a pattern and | to separate " + "patterns. Stop mark is set with \\\\.\n" + "Example:\n" + "host_match = .*nlm\\\\.nih.*|.*gov|10\\\\.55.*\n"; + string filtered = NStr::Replace(NStr::Replace(regex, "\\.", ""), + ".*" , ""); + if (filtered.find_first_of("[]()+^?{}$.*\\") != string::npos) { + throw CMonkeyException( + CDiagCompileInfo(__FILE__, __LINE__), + NULL, + CMonkeyException::e_MonkeyInvalidArgs, + exception_message); + } + size_t pos = 0; + size_t last_find = 0; + bool start_wildcard = false, end_wildcard = false; + while ((last_find = NStr::Find(regex, ".*", pos)) != NPOS && + pos < regex.length()) { + pos = last_find + 1; + if (last_find == 0) { + start_wildcard = true; + } + else if (last_find == regex.length() - strlen(".*")) { + end_wildcard = true; + } + else { + throw CMonkeyException( + CDiagCompileInfo(__FILE__, __LINE__), + NULL, + CMonkeyException::e_MonkeyInvalidArgs, + exception_message); + } + } + /* + * Run the "Needle in a haystack" task + */ + string needle = NStr::Replace(NStr::Replace(regex, ".*", ""), "\\.", "."); + if (start_wildcard && !end_wildcard) { + if (!NStr::StartsWith(to_match, needle)) { + return false; + } + } + else if (!start_wildcard && end_wildcard) { + if (!NStr::EndsWith(to_match, needle)) { + return false; + } + } + else if (start_wildcard && end_wildcard) { + if (NStr::Find(to_match, needle) == NPOS) { + return false; + } + } + return true; +} +#endif /* NCBI_OS_MSWIN */ + + +/* Compares supplied parameters to */ +bool CMonkeyPlan::Match(const string& sock_host, + unsigned short sock_port, + const string& sock_url, + unsigned short probability_left) +{ + /* Regex test just in case */ + static int regex_works = 1; /* 0 for not working, 1 for working */ +#if 0 + if (regex_works == -1) { + regex test_regexp("test_regex"); /* should not match "test" */ + string test_string = "test.*"; + smatch test_find; + if (!regex_match(test_string, test_find, test_regexp)) { + regex_works = 0; /* we learn that regex implementation is fake */ + } + regex_works = 1; + } +#endif /* 0 */ + + /* Check that regex works and that at least one of hostname and IP + * is not empty*/ + if ( regex_works && !m_HostRegex.empty() && + (sock_host.length() + sock_url.length() > 0) ) { +#ifdef NCBI_OS_MSWIN + regex reg(m_HostRegex); + smatch find; + if (!regex_match(sock_host, find, reg) && + !regex_match(sock_url, find, reg)) { + return false; + } +#else + /* + * Regex is not supported - work with simple simulation - only .* in + * beginning and end of pattern and | to separate patterns + */ + vector patterns = s_Monkey_Split(m_HostRegex, '|'); + auto it = patterns.begin(); + bool match_found = false; + for ( ; it != patterns.end(); it++) { + if (s_MatchRegex(sock_url, *it) || s_MatchRegex(sock_host, *it)) { + match_found = true; + break; + } + } + if (!match_found) { + return false; + } +#endif /* NCBI_OS_MSWIN */ + } + /* If port match pattern is not set, any port is good */ + bool port_match = m_PortRanges.empty(); + auto port_iter = m_PortRanges.begin(); + for (; port_iter != m_PortRanges.end(); port_iter++) { + if (sock_port >= *port_iter && sock_port <= *++port_iter) { + port_match = true; + break; + } + } + int rand_val = CMonkey::Instance()->GetRand(Key()); + LOG_POST(Note << "[CMonkeyPlan::Match] Checking if plan " << m_Name + << " will be matched. Random value is " + << rand_val << ", plan probability is " + << m_Probability << "%, probability left is " + << probability_left << "%, so probability threshold is" + << m_Probability * 100 / probability_left << "%"); + LOG_POST(Note << "[CMonkeyPlan::Match] Plan " << m_Name << " was " + << ((port_match && ((rand_val % 100) < m_Probability)) ? + "" : "NOT ") << "matched"); + return port_match ? ((rand_val % 100) < m_Probability*100/probability_left) + : false; +} + + +bool CMonkeyPlan::WriteRule(MONKEY_SOCKTYPE sock, + const MONKEY_DATATYPE data, + MONKEY_LENTYPE size, + int flags, + MONKEY_RETTYPE* bytes_written, + SOCK* sock_ptr) +{ + short probability_left = 100; + for (unsigned int i = 0; i < m_WriteRules.size(); i++) { + m_WriteRules[i].AddSocket(sock); + unsigned short rule_prob = m_WriteRules[i].GetProbability(sock); + if (m_WriteRules[i].CheckRun(sock)) { + *bytes_written = m_WriteRules[i].Run(sock, data, size, flags, + sock_ptr); + return true; + } + /* If this rule did not engage, we go to the next rule, and + remember to normalize probability of next rule */ + probability_left -= rule_prob; + if (probability_left <= 0) { + stringstream ss; + ss << "Probability below zero for write rule in plan " << m_Name + << ". Check config!"; + throw CMonkeyException( + CDiagCompileInfo(__FILE__, __LINE__), + NULL, CMonkeyException::e_MonkeyInvalidArgs, + ss.str()); + } + } + // If no rules engaged, return 0 + return false; +} + + +bool CMonkeyPlan::ReadRule(MONKEY_SOCKTYPE sock, + MONKEY_DATATYPE buf, + MONKEY_LENTYPE size, + int flags, + MONKEY_RETTYPE* bytes_read, + SOCK* sock_ptr) +{ + short probability_left = 100; + for (unsigned int i = 0; i < m_ReadRules.size(); i++) { + m_ReadRules[i].AddSocket(sock); + unsigned short rule_prob = m_ReadRules[i].GetProbability(sock); + if (m_ReadRules[i].CheckRun(sock)) { + *bytes_read = m_ReadRules[i].Run(sock, buf, size, flags, sock_ptr); + return true; + } + /* If this rule did not engage, we go to the next rule, and + and remember to normalize probability of next rule */ + probability_left -= rule_prob; + if (probability_left <= 0) { + stringstream ss; + ss << "Probability below zero for write rule in plan " << m_Name + << ". Check config!"; + throw CMonkeyException( + CDiagCompileInfo(__FILE__, __LINE__), + NULL, CMonkeyException::e_MonkeyInvalidArgs, + ss.str()); + } + } + return false; +} + + +bool CMonkeyPlan::ConnectRule(MONKEY_SOCKTYPE sock, + const struct sockaddr* name, + MONKEY_SOCKLENTYPE namelen, + int* result) +{ + short probability_left = 100; + for (unsigned int i = 0; i < m_ConnectRules.size(); i++) { + m_ConnectRules[i].AddSocket(sock); + unsigned short rule_prob = m_ConnectRules[i].GetProbability(sock); + /* Check if the rule will trigger on this run. If not - we go to the + next rule in plan */ + if (m_ConnectRules[i].CheckRun(sock)) { + /* 'result' is the result of connect() launched in the rule. It can + even be result of original connect() with real parameters. + Or, it can be an error code of a failed fake connect() */ + *result = m_ConnectRules[i].Run(sock, name, namelen); + return true; + } + /* If this rule did not engage, we go to the next rule, and + and remember to normalize probability of next rule */ + probability_left -= rule_prob; + if (probability_left <= 0) { + stringstream ss; + ss << "Probability below zero for write rule in plan " << m_Name + << ". Check config!"; + throw CMonkeyException( + CDiagCompileInfo(__FILE__, __LINE__), + NULL, CMonkeyException::e_MonkeyInvalidArgs, + ss.str()); + } + } + // If no rules triggered + return false; +} + + +bool CMonkeyPlan::PollRule(size_t* n, + SOCK* sock, + EIO_Status* return_status) +{ + short probability_left = 100; + for (unsigned int i = 0; i < m_PollRules.size(); i++) { + m_PollRules[i].AddSocket((*sock)->sock); + unsigned short rule_prob = m_PollRules[i].GetProbability((*sock)->sock); + if (m_PollRules[i].CheckRun((*sock)->sock)) { + return m_PollRules[i].Run(n, sock, return_status); + } + LOG_POST(Error << "[CMonkeyPlan::PollRule] CHAOS MONKEY NOT " + "ENGAGED!!! poll() passed"); + /* If this rule did not engage, we go to the next rule, and + and remember to normalize probability of next rule */ + probability_left -= rule_prob; + if (probability_left <= 0) { + stringstream ss; + ss << "Probability below zero for write rule in plan " << m_Name + << ". Check config!"; + throw CMonkeyException( + CDiagCompileInfo(__FILE__, __LINE__), + NULL, CMonkeyException::e_MonkeyInvalidArgs, + ss.str()); + } + } + // If no rules triggered, return 0 + *return_status = EIO_Status::eIO_Success; + return false; +} + + +unsigned short CMonkeyPlan::GetProbabilty(void) +{ + return m_Probability; +} + + +void CMonkeyPlan::x_ReadPortRange(const string& conf) +{ + vector ranges = s_Monkey_Split(conf, ','); + unsigned short from, to; + auto it = ranges.begin(); + for ( ; it != ranges.end(); it++ ) { + if (it->find('-') != string::npos) { + vector ports = s_Monkey_Split(*it, '-'); + from = static_cast(NStr::StringToUInt(ports[0])); + to = static_cast(NStr::StringToUInt(ports[1])); + } else { + from = to = static_cast(NStr::StringToUInt(*it)); + } + /* From*/ + m_PortRanges.push_back(from); + /* Until */ + m_PortRanges.push_back(to); + } +} + + +////////////////////////////////////////////////////////////////////////// +// CMonkey +////////////////////////////////////////////////////////////////////////// +CMonkey* CMonkey::sm_Instance = NULL; +FMonkeyHookSwitch CMonkey::sm_HookSwitch = NULL; + + +CMonkey::CMonkey() : m_Probability(1.0), m_Enabled(false) +{ + if (sm_HookSwitch == NULL) { + throw CMonkeyException( + CDiagCompileInfo(__FILE__, __LINE__), + NULL, CMonkeyException::e_MonkeyInvalidArgs, + "Launch CONNECT_Init() before initializing CMonkey instance"); + } + m_TlsToken = new CTls; + m_TlsRandList = new CTls >; + m_TlsRandListPos = new CTls; + srand((unsigned int)time(NULL)); + m_Seed = rand(); + LOG_POST(Note << "[CMonkey::CMonkey()] Chaos Monkey seed is: " << m_Seed); + ReloadConfig(); +} + + +CMonkey* CMonkey::Instance() +{ + CFastMutexGuard spawn_guard(s_SingletonMutex); + + if (sm_Instance == NULL) { + sm_Instance = new CMonkey; + } + return sm_Instance; +} + + +bool CMonkey::IsEnabled() +{ + return m_Enabled; +} + + +void CMonkey::ReloadConfig(const string& config) +{ + assert(sm_HookSwitch != NULL); + CFastMutexGuard spawn_guard(s_ConfigMutex); + string rules; + string monkey_section = config.empty() ? s_GetMonkeySection() : + config; + list sections; + CNcbiRegistry& reg = CNcbiApplication::Instance()->GetConfig(); + if (ConnNetInfo_Boolean(reg.Get(kMonkeyMainSect, kEnablField).c_str()) != 1) + { + LOG_POST(Note << "[CMonkey::ReloadConfig] Chaos Monkey is disabled " + << "in [" << kMonkeyMainSect << "]"); + m_Enabled = false; + return; + } + string seed = reg.Get(kMonkeyMainSect, kSeedField).c_str(); + if (seed != "") { + LOG_POST(Note << "[CMonkey::ReloadConfig] Chaos Monkey seed is set " + << "to " << seed << " in config"); + SetSeed(NStr::StringToInt(seed)); + } + reg.EnumerateSections(§ions); + /* If the section does not exist */ + if (find(sections.begin(), sections.end(), monkey_section) + == sections.end()) { + m_Enabled = false; + return; + } + if (ConnNetInfo_Boolean(reg.Get(monkey_section, kEnablField).c_str()) != 1) + { + LOG_POST(Note << "[CMonkey::ReloadConfig] Chaos Monkey is disabled " + << "in [" << monkey_section << "]"); + m_Enabled = false; + return; + } + m_Enabled = true; + LOG_POST(Error << "[CMonkey::ReloadConfig] Chaos Monkey is active!"); + string probability = reg.Get(monkey_section, "probability"); + if (probability != "") { + probability = NStr::Replace(probability, " ", ""); + auto arr = s_Monkey_Split(probability, '='); + try { + if (*probability.rbegin() != '%') { + m_Probability = NStr::StringToDouble(probability) * 100; + } + else { + probability = probability.substr(0, probability.length() - 1); + m_Probability = NStr::StringToDouble(probability); + } + } + catch (const CStringException&) { + throw CMonkeyException(CDiagCompileInfo(__FILE__, __LINE__), + NULL, CMonkeyException::e_MonkeyInvalidArgs, + "Probability \"" + probability + + "\" for section " + monkey_section + + " could not be parsed"); + } + } + // Disable hooks while Monkey initializes + sm_HookSwitch(eMonkeyHookSwitch_Disabled); + unsigned short total_probability = 0; + for (int i = 1; ; ++i) { + string section = monkey_section + "_PLAN" + NStr::IntToString(i); + if (find(sections.begin(), sections.end(), section) == + sections.end()) { + break; + } + m_Plans.push_back(CMonkeyPlan(section)); + total_probability += (*m_Plans.rbegin()).GetProbabilty(); + } + /* Check that sum of probabilities for plans is less than 100%, otherwise - + * throw an exception with an easy-to-read message */ + if (total_probability > 100) { + stringstream ss; + ss << "Total probability for plans in configuration " << + monkey_section << " exceeds 100%. Please check that summary " << + "probability for plans stays under 100% (where the remaining " + "percents go to connections that are not intercepted by any plan)." + "\nTurning Chaos Monkey off"; + CORE_LOG(eLOG_Critical, ss.str().c_str()); + m_Enabled = false; + } + if (m_Enabled) { + s_TimeoutingSocketInit(); + } + else { + s_TimeoutingSocketDestroy(); + } + sm_HookSwitch(m_Enabled ? eMonkeyHookSwitch_Enabled + : eMonkeyHookSwitch_Disabled); +} + + +MONKEY_RETTYPE CMonkey::Send(MONKEY_SOCKTYPE sock, + const MONKEY_DATATYPE data, + MONKEY_LENTYPE size, + int flags, + SOCK* sock_ptr) +{ + string host_fqdn, host_IP; + unsigned short peer_port; + s_GetSocketDestinations(sock, &host_fqdn, &host_IP, NULL, &peer_port); + CMonkeyPlan* sock_plan = x_FindPlan(sock, host_fqdn, host_IP, peer_port); + + if (sock_plan != NULL) { + MONKEY_RETTYPE bytes_written; + /* Plan may decide to leave connection untouched */ + if ( sock_plan->WriteRule(sock, data, size, flags, &bytes_written, + sock_ptr) ) + return bytes_written; + } + return send(sock, (const char*)data, size, flags); +} + + +MONKEY_RETTYPE CMonkey::Recv(MONKEY_SOCKTYPE sock, + MONKEY_DATATYPE buf, + MONKEY_LENTYPE size, + int flags, + SOCK* sock_ptr) +{ + string host_fqdn, host_IP; + unsigned short peer_port; + s_GetSocketDestinations(sock, &host_fqdn, &host_IP, NULL, &peer_port); + + CMonkeyPlan* sock_plan = x_FindPlan(sock, host_fqdn, host_IP, peer_port); + + if (sock_plan != NULL) { + MONKEY_RETTYPE bytes_read; + if (sock_plan->ReadRule(sock, buf, size, flags, &bytes_read, sock_ptr)) + return bytes_read; + } + return recv(sock, buf, size, flags); +} + + +int CMonkey::Connect(MONKEY_SOCKTYPE sock, + const struct sockaddr* name, + MONKEY_SOCKLENTYPE namelen) +{ + union { + struct sockaddr sa; + struct sockaddr_in in; +#ifdef NCBI_OS_UNIX + struct sockaddr_un un; +#endif /*NCBI_OS_UNIX*/ + } addr; + addr.sa = *name; + unsigned int host = addr.in.sin_addr.s_addr; + string host_fqdn, host_IP; + unsigned short peer_port = ntohs(addr.in.sin_port); + host_fqdn = CSocketAPI::gethostbyaddr(host); + host_IP = CSocketAPI::HostPortToString(host, 0); + + CMonkeyPlan* sock_plan = x_FindPlan(sock, host_fqdn, host_IP, peer_port); + if (sock_plan != NULL) { + int result; + if ( sock_plan->ConnectRule(sock, name, namelen, &result) ) + return result; + } + return connect(sock, name, namelen); +} + + +bool CMonkey::Poll(size_t* n, + SSOCK_Poll** polls, + EIO_Status* return_status) +{ + size_t polls_iter = 0; + SSOCK_Poll* new_polls = + static_cast(calloc(*n, sizeof(SSOCK_Poll))); + int polls_count = 0; + while (polls_iter < *n) { + SOCK& sock = (*polls)[polls_iter].sock; + string host_fqdn = CSocketAPI::gethostbyaddr(sock->host); + string host_IP = CSocketAPI::HostPortToString(sock->host, 0); + CMonkeyPlan* sock_plan = x_FindPlan(sock->id, "", "", sock->myport); + if (sock_plan == NULL || + (sock_plan != NULL && !sock_plan->PollRule(n, &sock, return_status)) + ) { + new_polls[polls_count++] = (*polls)[polls_iter]; + } + polls_iter++; + } + *polls = new_polls; + *n = polls_count; + return false; +} + + +void CMonkey::Close(MONKEY_SOCKTYPE sock) +{ + auto sock_plan = m_KnownSockets.find(sock); + if (sock_plan != m_KnownSockets.end()) { + m_KnownSockets.erase(sock_plan); + } +} + + +void CMonkey::MonkeyHookSwitchSet(FMonkeyHookSwitch hook_switch_func) +{ + sm_HookSwitch = hook_switch_func; +} + + +/** Return plan for the socket, new or already assigned one. If the socket + * is ignored by Chaos Monkey, NULL is returned */ +CMonkeyPlan* CMonkey::x_FindPlan(MONKEY_SOCKTYPE sock, const string& hostname, + const string& host_IP, unsigned short port) +{ + CFastMutexGuard spawn_guard(s_KnownConnMutex); + auto sock_plan = m_KnownSockets.find(sock); + if (sock_plan != m_KnownSockets.end()) { + return sock_plan->second; + } + /* Plan was not found. First roll the dice to know if Monkey will process + * current socket */ + int rand_val = CMonkey::Instance()->GetRand(Key()); + LOG_POST(Note << "[CMonkey::x_FindPlan] Checking if connection will be " + << "intercepted by Chaos Monkey. Random value is " + << rand_val << ", probability threshold is " + << m_Probability); + LOG_POST(Note << "[CMonkey::x_FindPlan] The connection will be " + << ((rand_val % 100 >= m_Probability) ? "NOT " : "") + << "processed."); + if (rand_val % 100 >= m_Probability) { + return NULL; + } + /* Now we can find a plan */ + bool match_found = false; + unsigned short probability_left = 100; /* If we tried to match a plan with + n% probability with no luck, + next plan only has (100-n)% + fraction of connections to match + against, so if its probability to + all connections is m%, its + probability to connections left + is m/(100-n)*100%. To count this, + we need probability_left */ + for (unsigned int i = 0; i < m_Plans.size() && !match_found; i++) { + /* Match includes probability of plan*/ + if (m_Plans[i].Match(host_IP, port, hostname, probability_left)) { + // 3. If found plan - use it and assign to this socket + m_KnownSockets[sock] = &m_Plans[i]; + return m_KnownSockets[sock]; + } + probability_left -= m_Plans[i].GetProbabilty(); + } + /* If no plan triggered, then this socket will be always ignored */ + m_KnownSockets[sock] = NULL; + return NULL; +} + + +bool CMonkey::RegisterThread(int token) +{ + if (!m_Enabled) { + ERR_POST(Error << "[CMonkey::RegisterThread] Chaos Monkey is " + << "disabled, the thread with token " + << token << " was not registered"); + return false; + } + CFastMutexGuard guard(s_SeedLogConfigMutex); + LOG_POST(Note << "[CMonkey::RegisterThread] Registering thread with " + << "token " << token); + + stringstream ss; + ss << "[CMonkey::RegisterThread] Token " << token + << " has been already registered in CMonkey and cannot be used again"; + if (m_RegisteredTokens.find(token) != m_RegisteredTokens.end()) { + throw CMonkeyException( + CDiagCompileInfo(__FILE__, __LINE__), + NULL, CMonkeyException::e_MonkeyInvalidArgs, + ss.str()); + } + m_RegisteredTokens.insert(token); + + /* Remember token */ + m_TlsToken->SetValue(new int, s_TlsCleanup); + *m_TlsToken->GetValue() = token; + + vector* rand_list = new vector(); + srand(m_Seed + token); + stringstream rand_list_str; + for (unsigned int i = 0; i < kRandCount; ++i) { + rand_list->push_back(rand()); + rand_list_str << *rand_list->rbegin() << " "; + } + LOG_POST(Note << "[CMonkey::RegisterThread] Random list for token " + << token << " is " << rand_list_str.str()); + m_TlsRandList->SetValue(rand_list, s_TlsCleanup< vector >); + + m_TlsRandListPos->SetValue(new int, s_TlsCleanup); + *m_TlsRandListPos->GetValue() = 0; + + return true; +} + + +int CMonkey::GetSeed() +{ + /* save m_seedlog to file */ + return m_Seed; +} + + +void CMonkey::SetSeed(int seed) +{ + /* load m_seedlog from file */ + m_Seed = seed; + LOG_POST(Info << "[CMonkey::SetSeed] Chaos Monkey seed was manually " + "changed to: " << m_Seed); +} + + +int CMonkey::GetRand(const CMonkeySeedKey& /* key */) +{ + if (m_TlsToken->GetValue() == NULL) { + return rand(); + } + int& list_pos = *m_TlsRandListPos->GetValue(); + if (++list_pos == kRandCount) { + list_pos = 0; + } + int next_list_pos = (list_pos + 1 == kRandCount) ? 0 : list_pos + 1; + LOG_POST(Note << "[CMonkey::GetRand] Getting random value " + << (*m_TlsRandList->GetValue())[list_pos] + << " for thread " << *m_TlsToken->GetValue() + << ". Next random value is " + << (*m_TlsRandList->GetValue())[next_list_pos]); + return (*m_TlsRandList->GetValue())[list_pos]; +} + + +END_NCBI_SCOPE + +#endif /* #ifdef NCBI_MONKEY */ + diff --git a/c++/src/connect/ncbi_monkeyp.hpp b/c++/src/connect/ncbi_monkeyp.hpp new file mode 100644 index 00000000..05250edf --- /dev/null +++ b/c++/src/connect/ncbi_monkeyp.hpp @@ -0,0 +1,81 @@ +/* $Id: ncbi_monkeyp.hpp 503153 2016-06-01 19:11:37Z elisovdn $ +* =========================================================================== +* +* PUBLIC DOMAIN NOTICE +* National Center for Biotechnology Information +* +* This software/database is a "United States Government Work" under the +* terms of the United States Copyright Act. It was written as part of +* the author's official duties as a United States Government employee and +* thus cannot be copyrighted. This software/database is freely available +* to the public for use. The National Library of Medicine and the U.S. +* Government have not placed any restriction on its use or reproduction. +* +* Although all reasonable efforts have been taken to ensure the accuracy +* and reliability of the software and data, the NLM and the U.S. +* Government do not and cannot warrant the performance or results that +* may be obtained by using this software or data. The NLM and the U.S. +* Government disclaim all warranties, express or implied, including +* warranties of performance, merchantability or fitness for any particular +* purpose. +* +* Please cite the author in any work or product based on this material. +* +* =========================================================================== +* +* Author: Dmitriy Elisov +* +* File Description: +* Chaos Monkey - a library that is hooked with ncbi_socket.c and introduces +* problems in network connectivity - losses, bad data, delays. +* difficulties +* +*/ + +#ifndef CONNECT___NCBI_MONKEYP__HPP +#define CONNECT___NCBI_MONKEYP__HPP + +# include + +BEGIN_NCBI_SCOPE + + +/* A special class which opens access to writing to Monkey Action Log*/ + + +#ifdef NCBI_MONKEY_TESTS + + +using namespace std; + +#define MONKEY_MOCK_MACRO() \ +DECLARE_MONKEY_MOCK(bool, InterceptedRecv, false); \ +DECLARE_MONKEY_MOCK(bool, InterceptedSend, false); \ +DECLARE_MONKEY_MOCK(bool, InterceptedConnect, false); \ +DECLARE_MONKEY_MOCK(bool, InterceptedPoll, false); \ +DECLARE_MONKEY_MOCK(string, LastRecvContent, ""); \ +DECLARE_MONKEY_MOCK(string, LastSendContent, ""); \ +DECLARE_MONKEY_MOCK(EIO_Status, LastRecvStatus, eIO_Success); \ +DECLARE_MONKEY_MOCK(EIO_Status, LastSendStatus, eIO_Success); \ +DECLARE_MONKEY_MOCK(EIO_Status, LastConnectStatus, eIO_Success); + + +#undef DECLARE_MONKEY_MOCK +#define DECLARE_MONKEY_MOCK(ty,name,def_val/*not used*/) \ + ty g_MonkeyMock_Get ## name(); \ + void g_MonkeyMock_Set ## name(const ty& val); + +MONKEY_MOCK_MACRO() +void g_Monkey_Foo(); + +class CMonkeySpy +{ + +}; + + +#endif /* #ifdef NCBI_MONKEY_TESTS */ + +END_NCBI_SCOPE + +#endif /* CONNECT___NCBI_MONKEYP__HPP */ \ No newline at end of file diff --git a/c++/src/connect/ncbi_priv.c b/c++/src/connect/ncbi_priv.c index a2f4511f..87cd30c3 100644 --- a/c++/src/connect/ncbi_priv.c +++ b/c++/src/connect/ncbi_priv.c @@ -1,4 +1,4 @@ -/* $Id: ncbi_priv.c 488838 2016-01-06 13:45:11Z elisovdn $ +/* $Id: ncbi_priv.c 507875 2016-07-21 21:24:44Z lavr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -31,26 +31,34 @@ */ #include "ncbi_priv.h" -#if defined(NCBI_OS_UNIX) +#if defined(NCBI_OS_UNIX) # include #elif defined(NCBI_OS_MSWIN) # include #else # include -#endif /*NCBI_OS_...*/ +#endif /*NCBI_OS*/ #include #include #include - /* GLOBALS */ -int g_NCBI_ConnectRandomSeed = 0; -MT_LOCK g_CORE_MT_Lock = &g_CORE_MT_Lock_default; -LOG g_CORE_Log = 0; -REG g_CORE_Registry = 0; -FNcbiGetAppName g_CORE_GetAppName = 0; -FNcbiGetRequestID g_CORE_GetRequestID = 0; -FNcbiGetRequestDtab g_CORE_GetRequestDtab = 0; +TCORE_Set g_CORE_Set = 0; +MT_LOCK g_CORE_MT_Lock = &g_CORE_MT_Lock_default; +LOG g_CORE_Log = 0; +REG g_CORE_Registry = 0; +int g_NCBI_ConnectRandomSeed = 0; +FNcbiGetAppName g_CORE_GetAppName = 0; +FNcbiGetRequestID g_CORE_GetRequestID = 0; +FNcbiGetRequestDtab g_CORE_GetRequestDtab = 0; + +#ifdef NCBI_MONKEY +FMonkeySend g_MONKEY_Send = 0; +FMonkeyRecv g_MONKEY_Recv = 0; +FMonkeyConnect g_MONKEY_Connect = 0; +FMonkeyPoll g_MONKEY_Poll = 0; +FMonkeyClose g_MONKEY_Close = 0; +#endif /*NCBI_MONKEY*/ extern int g_NCBI_ConnectSrandAddend(void) diff --git a/c++/src/connect/ncbi_priv.h b/c++/src/connect/ncbi_priv.h index e043cf2c..72eeb088 100644 --- a/c++/src/connect/ncbi_priv.h +++ b/c++/src/connect/ncbi_priv.h @@ -1,7 +1,7 @@ #ifndef CONNECT___NCBI_PRIV__H #define CONNECT___NCBI_PRIV__H -/* $Id: ncbi_priv.h 488838 2016-01-06 13:45:11Z elisovdn $ +/* $Id: ncbi_priv.h 507875 2016-07-21 21:24:44Z lavr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -43,17 +43,28 @@ * Registry: * private global: g_CORE_Registry * macros: CORE_REG_GET, CORE_REG_SET + * Setup accounting: ECORE_Set + * private global: g_CORE_Set * Random generator seeding support * private global: g_NCBI_ConnectRandomSeed * macro: NCBI_CONNECT_SRAND_ADDEND - * App name and NCBI ID support + * App name / NCBI ID / DTab support * private globals: g_CORE_GetAppName * g_CORE_GetRequestID + * g_CORE_GetRequestDtab * */ #include "ncbi_assert.h" #include +#ifdef NCBI_MONKEY +# if defined(NCBI_OS_MSWIN) +# include +# else +# include +# define SOCKET int +# endif /*NCBI_OS_MSWIN*/ +#endif /* NCBI_MONKEY */ #ifdef __cplusplus @@ -304,6 +315,22 @@ extern NCBI_XCONNECT_EXPORT int/*bool*/ g_CORE_RegistrySET ); +/****************************************************************************** + * Setup accounting + */ + +typedef enum { + eCORE_SetSSL = 1, + eCORE_SetREG = 4, + eCORE_SetLOG = 2, + eCORE_SetLOCK = 8 +} ECORE_Set; +typedef unsigned int TCORE_Set; + + +extern TCORE_Set g_CORE_Set; + + /****************************************************************************** * Random generator seeding support */ @@ -332,12 +359,16 @@ extern NCBI_XCONNECT_EXPORT FNcbiGetRequestID g_CORE_GetRequestID; /****************************************************************************** - * DTab-Local support (may return NULL; gets converted to "" at the user level) + * DTab-Local support (returned NULL gets converted to "" at the user level) */ typedef const char* (*FNcbiGetRequestDtab)(void); extern NCBI_XCONNECT_EXPORT FNcbiGetRequestDtab g_CORE_GetRequestDtab; +/****************************************************************************** + * Miscellanea + */ + #ifdef __GNUC__ # define likely(x) __builtin_expect(!!(x),1) # define unlikely(x) __builtin_expect(!!(x),0) @@ -347,6 +378,63 @@ extern NCBI_XCONNECT_EXPORT FNcbiGetRequestDtab g_CORE_GetRequestDtab; #endif /*__GNUC__*/ +/****************************************************************************** + * NCBI Crazy Monkey support + */ + +#ifdef NCBI_MONKEY +/* UNIX and Windows have different prototypes for send(), recv(), etc., so + * some types have to be pre-selected based on current OS + */ +# ifdef NCBI_OS_MSWIN +# define MONKEY_RETTYPE int +# define MONKEY_SOCKTYPE SOCKET +# define MONKEY_DATATYPE char* +# define MONKEY_LENTYPE int +# define MONKEY_SOCKLENTYPE int +# define MONKEY_STDCALL __stdcall /* in Windows, socket functions have + prototypes with __stdcall */ +# else +# define MONKEY_RETTYPE ssize_t +# define MONKEY_SOCKTYPE int +# define MONKEY_DATATYPE void* +# define MONKEY_LENTYPE size_t +# define MONKEY_SOCKLENTYPE socklen_t +# define MONKEY_STDCALL /* empty*/ +# endif /* NCBI_OS_MSWIN */ + +/****************************************************************************** + * Socket functions via Crazy Monkey + */ +typedef MONKEY_RETTYPE + (MONKEY_STDCALL *FMonkeyRecv) (MONKEY_SOCKTYPE sock, + MONKEY_DATATYPE buf, + MONKEY_LENTYPE size, + int flags, + void* /* SOCK* */ sock_ptr); +typedef MONKEY_RETTYPE + (MONKEY_STDCALL *FMonkeySend) (MONKEY_SOCKTYPE sock, + const MONKEY_DATATYPE data, + MONKEY_LENTYPE size, + int flags, + void* /* SOCK* */ sock_ptr); +typedef int(MONKEY_STDCALL *FMonkeyConnect)(MONKEY_SOCKTYPE sock, + const struct sockaddr* name, + MONKEY_SOCKLENTYPE namelen); + +typedef int /* bool */ (*FMonkeyPoll) (size_t* n, + void* /*SSOCK_Poll[]* */polls, + EIO_Status* ret_status); +typedef void (*FMonkeyClose) (SOCKET sock); + +extern NCBI_XCONNECT_EXPORT FMonkeySend g_MONKEY_Send; +extern NCBI_XCONNECT_EXPORT FMonkeyRecv g_MONKEY_Recv; +extern NCBI_XCONNECT_EXPORT FMonkeyPoll g_MONKEY_Poll; +extern NCBI_XCONNECT_EXPORT FMonkeyConnect g_MONKEY_Connect; +extern NCBI_XCONNECT_EXPORT FMonkeyClose g_MONKEY_Close; +#endif /*NCBI_MONKEY*/ + + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/c++/src/connect/ncbi_server_info.c b/c++/src/connect/ncbi_server_info.c index 28eb087b..542fe63b 100644 --- a/c++/src/connect/ncbi_server_info.c +++ b/c++/src/connect/ncbi_server_info.c @@ -1,4 +1,4 @@ -/* $Id: ncbi_server_info.c 465213 2015-04-17 20:53:10Z lavr $ +/* $Id: ncbi_server_info.c 507385 2016-07-18 22:38:48Z lavr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -241,9 +241,8 @@ SSERV_Info* SERV_ReadInfoEx(const char* str, if (!info) return 0; info->host = host; - if (port) - info->port = port; - coef = mime = locl = priv = rate = sful = secu = time = flag = 0;/*false*/ + info->port = port; + coef = mime = locl = priv = rate = sful = secu = time = flag = 0/*false*/; /* continue reading server info: optional parts... */ while (*str && isspace((unsigned char)(*str))) ++str; @@ -262,7 +261,7 @@ SSERV_Info* SERV_ReadInfoEx(const char* str, case 'B': if (coef) break; - coef = 1; + coef = 1/*true*/; d = NCBI_simple_atof(++str, &e); if (e > str) { if (fabs(d) < SERV_MINIMAL_BONUS / 2.0) @@ -278,7 +277,7 @@ SSERV_Info* SERV_ReadInfoEx(const char* str, case 'C': if (mime || type == fSERV_Dns) break; - mime = 1; + mime = 1/*true*/; if (MIME_ParseContentTypeEx(++str, &mime_t, &mime_s, &mime_e)){ info->mime_t = mime_t; info->mime_s = mime_s; @@ -291,7 +290,7 @@ SSERV_Info* SERV_ReadInfoEx(const char* str, case 'L': if (locl) break; - locl = 1; + locl = 1/*true*/; if (sscanf(++str, "%3s%n", s, &n) >= 1) { if (strcasecmp(s, "YES") == 0) { info->site |= fSERV_Local; @@ -305,7 +304,7 @@ SSERV_Info* SERV_ReadInfoEx(const char* str, case 'P': if (priv || type == fSERV_Dns) break; - priv = 1; + priv = 1/*true*/; if (sscanf(++str, "%3s%n", s, &n) >= 1) { if (strcasecmp(s, "YES") == 0) { info->site |= fSERV_Private; @@ -319,7 +318,7 @@ SSERV_Info* SERV_ReadInfoEx(const char* str, case 'R': if (rate) break; - rate = 1; + rate = 1/*true*/; d = NCBI_simple_atof(++str, &e); if (e > str) { if (fabs(d) < SERV_MINIMAL_RATE / 2.0) @@ -335,7 +334,7 @@ SSERV_Info* SERV_ReadInfoEx(const char* str, case 'S': if (sful || type == fSERV_Dns || (type & fSERV_Http)) break; - sful = 1; + sful = 1/*true*/; if (sscanf(++str, "%3s%n", s, &n) >= 1) { if (strcasecmp(s, "YES") == 0) { info->mode |= fSERV_Stateful; @@ -349,7 +348,7 @@ SSERV_Info* SERV_ReadInfoEx(const char* str, case '$': if (secu || type == fSERV_Dns) break; - secu = 1; + secu = 1/*true*/; if (sscanf(++str, "%3s%n", s, &n) >= 1) { if (strcasecmp(s, "YES") == 0) { info->mode |= fSERV_Secure; @@ -363,7 +362,7 @@ SSERV_Info* SERV_ReadInfoEx(const char* str, case 'T': if (time) break; - time = 1; + time = 1/*true*/; if (sscanf(++str, "%lu%n", &t, &n) >= 1) { info->time = (TNCBI_Time) t; str += n; @@ -372,7 +371,7 @@ SSERV_Info* SERV_ReadInfoEx(const char* str, } } else if (!flag) { size_t i; - flag = 1; + flag = 1/*true*/; for (i = 0; i < sizeof(kFlags) / sizeof(kFlags[0]); ++i) { if (strncasecmp(str, kFlags[i].tag, kFlags[i].len) == 0) { info->flag = kFlags[i].val; @@ -387,15 +386,21 @@ SSERV_Info* SERV_ReadInfoEx(const char* str, while (*str && isspace((unsigned char)(*str))) ++str; } - if (*str) { + if (!*str) { + if (name) { + strcpy((char*) info + SERV_SizeOfInfo(info), name); + if (info->type == fSERV_Dns) + info->u.dns.name = 1/*true*/; + } else if (info->type == fSERV_Dns) + info->u.dns.name = 0/*false*/; + if (!info->port + && (info->type == fSERV_Ncbid || (info->type & fSERV_Http))) { + info->port = secu ? CONN_PORT_HTTPS : CONN_PORT_HTTP; + } + } else { free(info); info = 0; - } else if (name) { - strcpy((char*) info + SERV_SizeOfInfo(info), name); - if (info->type == fSERV_Dns) - info->u.dns.name = 1/*true*/; - } else if (info->type == fSERV_Dns) - info->u.dns.name = 0/*false*/; + } return info; } @@ -485,15 +490,15 @@ static SSERV_Info* s_Ncbid_Read(const char** str, size_t add) if (!(args = strdup(*str))) return 0; - for (c = args; *c; c++) { + for (c = args; *c; ++c) { if (isspace((unsigned char)(*c))) { *c++ = '\0'; while (*c && isspace((unsigned char)(*c))) - c++; + ++c; break; } } - info = SERV_CreateNcbidInfoEx(0, CONN_PORT_HTTP, args, add); + info = SERV_CreateNcbidInfoEx(0, 0, args, add); if (info) *str += c - args; free(args); @@ -640,17 +645,17 @@ static SSERV_Info* s_HttpAny_Read(ESERV_Type type,const char** str, size_t add) if (!**str || !(path = strdup(*str))) return 0; - for (c = path; *c; c++) { + for (c = path; *c; ++c) { if (isspace((unsigned char)(*c))) { *c++ = '\0'; while (*c && isspace((unsigned char)(*c))) - c++; + ++c; break; } } if ((args = strchr(path, '?')) != 0) *args++ = '\0'; - info = SERV_CreateHttpInfoEx(type, 0, CONN_PORT_HTTP, path, args, add); + info = SERV_CreateHttpInfoEx(type, 0, 0, path, args, add); if (info) *str += c - path; free(path); diff --git a/c++/src/connect/ncbi_service.c b/c++/src/connect/ncbi_service.c index 5c92a231..f4f9ecc1 100644 --- a/c++/src/connect/ncbi_service.c +++ b/c++/src/connect/ncbi_service.c @@ -1,4 +1,4 @@ -/* $Id: ncbi_service.c 488579 2016-01-01 00:38:12Z lavr $ +/* $Id: ncbi_service.c 513929 2016-09-16 15:08:30Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -239,7 +239,7 @@ static SERV_ITER x_Open(const char* service, iter->reverse_dns = 1; if (types & fSERV_Stateless) iter->stateless = 1; - iter->external = external; + iter->external = external ? 1 : 0; if (arg && *arg) { iter->arg = arg; iter->arglen = strlen(arg); @@ -275,6 +275,8 @@ static SERV_ITER x_Open(const char* service, iter->o_skip = iter->n_skip; if (net_info) { + if (net_info->external) + iter->external = 1; if (net_info->firewall) iter->types |= fSERV_Firewall; if (net_info->stateless) @@ -692,7 +694,7 @@ int/*bool*/ SERV_Update(SERV_ITER iter, const char* text, int code) } -static void s_SetDefaultReferer(SERV_ITER iter, SConnNetInfo* net_info) +static void s_SetDefaultReferer(SConnNetInfo* net_info, SERV_ITER iter) { char* str, *referer = 0; @@ -733,8 +735,8 @@ char* SERV_Print(SERV_ITER iter, SConnNetInfo* net_info, int/*bool*/ but_last) static const char kAcceptedServerTypes[] = "Accepted-Server-Types:"; static const char kClientRevision[] = "Client-Revision: %u.%u\r\n"; static const char kUsedServerInfo[] = "Used-Server-Info: "; + static const char kNcbiExternal[] = NCBI_EXTERNAL ": Y\r\n"; static const char kNcbiFWPorts[] = "NCBI-Firewall-Ports: "; - static const char kServerCount[] = "Server-Count: "; static const char kPreference[] = "Preference: "; static const char kSkipInfo[] = "Skip-Info-%u: "; static const char kAffinity[] = "Affinity: "; @@ -754,7 +756,7 @@ char* SERV_Print(SERV_ITER iter, SConnNetInfo* net_info, int/*bool*/ but_last) if (iter) { assert(iter->op); if (net_info && !net_info->http_referer && iter->op->mapper) - s_SetDefaultReferer(iter, net_info); + s_SetDefaultReferer(net_info, iter); /* Accepted server types */ buflen = sizeof(kAcceptedServerTypes) - 1; memcpy(buffer, kAcceptedServerTypes, buflen); @@ -777,13 +779,9 @@ char* SERV_Print(SERV_ITER iter, SConnNetInfo* net_info, int/*bool*/ but_last) return 0; } } - if (iter->ismask || (iter->pref && (iter->host | iter->port))) { - /* FIXME: To obsolete? */ - /* How many server-infos for the dispatcher to send to us */ - if (!BUF_Write(&buf, kServerCount, sizeof(kServerCount) - 1) || - !BUF_Write(&buf, - iter->ismask ? "10\r\n" : "ALL\r\n", - iter->ismask ? 4 : 5)) { + if (iter->external) { + /* External */ + if (!BUF_Write(&buf, kNcbiExternal, sizeof(kNcbiExternal)-1)) { BUF_Destroy(buf); return 0; } diff --git a/c++/src/connect/ncbi_service_connector.c b/c++/src/connect/ncbi_service_connector.c index bef1bb96..f6394d33 100644 --- a/c++/src/connect/ncbi_service_connector.c +++ b/c++/src/connect/ncbi_service_connector.c @@ -1,4 +1,4 @@ -/* $Id: ncbi_service_connector.c 465077 2015-04-16 17:34:16Z lavr $ +/* $Id: ncbi_service_connector.c 516325 2016-10-12 17:18:28Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -648,6 +648,8 @@ static CONNECTOR s_Open(SServiceConnector* uuu, switch (info->type) { case fSERV_Ncbid: /* Connection directly to NCBID, add NCBID-specific tags */ + if (info->mode & fSERV_Secure) + net_info->scheme = eURL_Https; if (net_info->stateless) { /* Connection request with data */ user_header = "Connection-Mode: STATELESS\r\n"; /*default*/ @@ -702,6 +704,8 @@ static CONNECTOR s_Open(SServiceConnector* uuu, EMIME_Type mime_t; EMIME_SubType mime_s; EMIME_Encoding mime_e; + if (!net_info->scheme) + net_info->scheme = eURL_Https; if (net_info->stateless || (info && (info->u.firewall.type & fSERV_Http))) { if (info) { @@ -724,7 +728,7 @@ static CONNECTOR s_Open(SServiceConnector* uuu, mime_s = eMIME_Undefined; mime_e = eENCOD_None; } - /* Firewall/relay connection to dispatcher, special tags */ + /* Firewall/relay connection thru dispatcher, special tags */ user_header = (net_info->stateless ? "Client-Mode: STATELESS_ONLY\r\n" /*default*/ : "Client-Mode: STATEFUL_CAPABLE\r\n"); @@ -849,6 +853,8 @@ static CONNECTOR s_Open(SServiceConnector* uuu, net_info->port = uuu->port; assert(!uuu->descr); uuu->descr = x_HostPort(net_info->host, net_info->port); + if (net_info->http_proxy_host[0] && net_info->http_proxy_port) + net_info->scheme = uuu->net_info->scheme; return s_SocketConnectorBuilder(net_info, uuu->descr, status, &uuu->ticket, uuu->ticket ? sizeof(uuu->ticket) : 0, @@ -951,12 +957,11 @@ static EIO_Status s_VT_Open(CONNECTOR connector, const STimeout* timeout) if (!uuu->iter && !s_OpenDispatcher(uuu)) break; - if (uuu->net_info->firewall - && strcasecmp(SERV_MapperName(uuu->iter), "local") != 0) { - info = 0; - } else if (!(info = s_GetNextInfo(uuu, 0/*any*/))) + if (!(info = s_GetNextInfo(uuu, 0/*any*/)) + && (!uuu->net_info->firewall + || strcasecmp(SERV_MapperName(uuu->iter), "local") == 0)) { break; - + } if (uuu->type) { free((void*) uuu->type); uuu->type = 0; @@ -983,7 +988,7 @@ static EIO_Status s_VT_Open(CONNECTOR connector, const STimeout* timeout) /* Setup the new connector on a temporary meta-connector... */ memset(&uuu->meta, 0, sizeof(uuu->meta)); - if ((status = METACONN_Add(&uuu->meta, c)) != eIO_Success) { + if ((status = METACONN_Insert(&uuu->meta, c)) != eIO_Success) { x_DestroyConnector(c); continue; } @@ -1027,15 +1032,13 @@ static EIO_Status s_VT_Open(CONNECTOR connector, const STimeout* timeout) break; if (!stateless && (!info || info->type == fSERV_Firewall)) { - static const char kFWLink[] = { "http://www.ncbi.nlm.nih.gov" - "/IEB/ToolBox/NETWORK" - "/dispatcher.html#Firewalling" }; + static const char kFWDLink[] = CONN_FWD_LINK; CORE_LOGF_X(6, eLOG_Error, ("[%s] %s connection failure (%s) usually" " indicates possible firewall configuration" " problems; please consult <%s>", uuu->service, !info ? "Firewall" : "Stateful relay", - IO_StatusStr(status), kFWLink)); + IO_StatusStr(status), kFWDLink)); } s_Close(connector, timeout, 0/*retain*/); diff --git a/c++/src/connect/ncbi_socket.c b/c++/src/connect/ncbi_socket.c index a7928016..2c092db5 100644 --- a/c++/src/connect/ncbi_socket.c +++ b/c++/src/connect/ncbi_socket.c @@ -1,4 +1,4 @@ -/* $Id: ncbi_socket.c 495662 2016-03-18 22:10:31Z ucko $ +/* $Id: ncbi_socket.c 517038 2016-10-20 11:20:53Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -131,7 +131,14 @@ #endif /* MAXHOSTNAMELEN */ - +#ifdef NCBI_MONKEY +/* A hack - we know that SOCK variable has name "sock" in code. + * If the desired behavior is timeout, "sock" will be replaced with a + * connection to non-working server */ +# define send(a,b,c,d) ((g_MONKEY_Send == NULL) ? send(a,b,c,d) : g_MONKEY_Send(a,b,c,d,&sock)) +# define recv(a,b,c,d) ((g_MONKEY_Recv == NULL) ? recv(a,b,c,d) : g_MONKEY_Recv(a,b,c,d,&sock)) +# define connect(a,b,c) ((g_MONKEY_Connect == NULL) ? connect(a,b,c) : g_MONKEY_Connect(a,b,c)) +#endif /****************************************************************************** * TYPEDEFS & MACROS */ @@ -151,6 +158,7 @@ # define SOCK_NFDS(s) 0 # define SOCK_CLOSE(s) closesocket(s) # define SOCK_EVENTS (FD_CLOSE|FD_CONNECT|FD_OOB|FD_WRITE|FD_READ) +# define WIN_INT_CAST (int) /* NCBI_OS_MSWIN */ #elif defined(NCBI_OS_UNIX) @@ -158,6 +166,7 @@ # define SOCK_INVALID (-1) # define SOCK_ERRNO errno # define SOCK_NFDS(s) ((s) + 1) +# define WIN_INT_CAST /* no cast */ # ifdef NCBI_OS_BEOS # define SOCK_CLOSE(s) closesocket(s) # else @@ -270,7 +279,7 @@ static const char* s_StrError(SOCK sock, int error) return 0; if (sock) { - FSSLError sslerror = s_SSL ? s_SSL->Error : 0; + FSSLError sslerror = sock->session && s_SSL ? s_SSL->Error : 0; if (sslerror) { const char* strerr = sslerror(sock->session == SESSION_INVALID ? 0 : sock->session, error); @@ -796,13 +805,18 @@ static EIO_Status s_Init(void) s_Initialized = 1/*inited*/; #ifndef NCBI_OS_MSWIN {{ - static int/*bool*/ s_AtExitSet = 0; + static void*/*bool*/ s_AtExitSet = 0; +#ifdef NCBI_CXX_TOOLKIT + if (!NCBI_SwapPointers(&s_AtExitSet, (void*) 1)) + atexit((void (*)(void)) SOCK_ShutdownAPI); +#else if (!s_AtExitSet) { + s_AtExitSet = (void*) 1; atexit((void (*)(void)) SOCK_ShutdownAPI); - s_AtExitSet = 1; } +#endif /*NCBI_CXX_TOOLKIT*/ }} -#endif +#endif /*NCBI_OS_MSWIN*/ CORE_UNLOCK; CORE_TRACE("[SOCK::InitializeAPI] End"); @@ -1148,8 +1162,8 @@ static unsigned int s_gethostbyname_(const char* hostname, ESwitch log) } #ifdef NCBI_OS_DARWIN -out: -#endif + out: +#endif /*NCBI_OS_DARWIN*/ #if defined(_DEBUG) && !defined(NDEBUG) if (!SOCK_isipEx(hostname, 1) || !host) { char addr[40]; @@ -2152,7 +2166,7 @@ static EIO_Status s_Select(size_t n, SSOCK_Poll polls[], const struct timeval* tv, int/*bool*/ asis) -{ +{ #if defined(NCBI_OS_MSWIN) && defined(NCBI_CXX_TOOLKIT) DWORD wait = tv ? tv->tv_sec * 1000 + (tv->tv_usec + 500)/1000 : INFINITE; HANDLE what[MAXIMUM_WAIT_OBJECTS]; @@ -2639,7 +2653,7 @@ static EIO_Status s_IsConnected_(SOCK sock, if (sock->log == eOn || (sock->log == eDefault && s_Log == eOn)) { CORE_LOGF(eLOG_Trace, - ("%sSSL session established%s%s", + ("%sSSL session created%s%s", s_ID(sock, _id), &" "[!desc], desc ? desc : "")); } @@ -2664,11 +2678,11 @@ static EIO_Status s_IsConnected(SOCK sock, const struct timeval* tv) EIO_Status status = s_IsConnected_(sock, tv, &what, &unused, 0); if (s_ErrHook && status != eIO_Success && status != eIO_Timeout) { SSOCK_ErrInfo info; + char addr[40]; memset(&info, 0, sizeof(info)); info.type = eSOCK_ErrIO; info.sock = sock; if (sock->port) { - char addr[40]; SOCK_ntoa(sock->host, addr, sizeof(addr)); info.host = addr; info.port = sock->port; @@ -2710,12 +2724,7 @@ static EIO_Status s_Recv(SOCK sock, readable = 0/*false*/; for (;;) { /* optionally auto-resume if interrupted */ int error; - - int x_read = recv(sock->sock, buf, -#ifdef NCBI_OS_MSWIN - /*WINSOCK wants it weird*/ (int) -#endif /*NCBI_OS_MSWIN*/ - size, 0/*flags*/); + int x_read = recv(sock->sock, buf, WIN_INT_CAST size, 0/*flags*/); #ifdef NCBI_OS_MSWIN /* recv() resets IO event recording */ sock->readable = sock->closing; @@ -2907,8 +2916,9 @@ static EIO_Status s_Read_(SOCK sock, break/*error*/; } status = sslread(sock->session, x_buf, n_todo, &x_read, &error); - assert(status == eIO_Success || error); assert(status == eIO_Success || !x_read); + assert(status == eIO_Success || error); + assert(x_read <= n_todo); /* statistics & logging */ if ((status != eIO_Success && sock->log != eOff) || @@ -3012,11 +3022,11 @@ static EIO_Status s_Read(SOCK sock, && (status != eIO_Closed || !(sock->r_status == eIO_Success && sock->eof))) { SSOCK_ErrInfo info; + char addr[40]; memset(&info, 0, sizeof(info)); info.type = eSOCK_ErrIO; info.sock = sock; if (sock->port) { - char addr[40]; SOCK_ntoa(sock->host, addr, sizeof(addr)); info.host = addr; info.port = sock->port; @@ -3204,11 +3214,7 @@ static EIO_Status s_Send(SOCK sock, for (;;) { /* optionally auto-resume if interrupted */ int error = 0; - int x_written = send(sock->sock, (void*) data, -#ifdef NCBI_OS_MSWIN - /*WINSOCK wants it weird*/ (int) -#endif /*NCBI_OS_MSWIN*/ - size, flag < 0 ? MSG_OOB : 0); + int x_written = send(sock->sock, (void*) data, WIN_INT_CAST size, flag < 0 ? MSG_OOB : 0); if (x_written >= 0 || (x_written < 0 && ((error = SOCK_ERRNO) == SOCK_EPIPE || @@ -3353,8 +3359,8 @@ static EIO_Status s_Send(SOCK sock, /* Wrapper for s_Send() that slices the output buffer for some brain-dead * systems (e.g. old Macs) that cannot handle large data chunks in "send()". - * Return eIO_Success if some data have been successfully sent; - * an error code if nothing at all has been sent. + * Return eIO_Success only if some data have been successfully sent; + * otherwise, an error code if nothing at all has been sent. */ #ifdef SOCK_SEND_SLICE # undef s_Send @@ -3370,17 +3376,17 @@ static EIO_Status s_Send(SOCK sock, assert(!*n_written); do { - size_t n_todo = size > SOCK_SEND_SLICE ? SOCK_SEND_SLICE : size; - const char* temp = (const char*) data + *n_written; - size_t n_done = 0; - status = s_Send_(sock, temp, n_todo, &n_done, flag); - assert(status == eIO_Success || !n_done); + size_t n_todo = size > SOCK_SEND_SLICE ? SOCK_SEND_SLICE : size; + size_t n_done = 0; + status = s_Send_(sock, data, n_todo, &n_done, flag); + assert((status == eIO_Success) == (n_done > 0)); if (status != eIO_Success) break; *n_written += n_done; if (n_todo != n_done) break; size -= n_done; + data = (const char*) data + n_done; } while (size); return *n_written ? eIO_Success : status; @@ -3388,13 +3394,14 @@ static EIO_Status s_Send(SOCK sock, #endif /*SOCK_SEND_SLICE*/ +/* Return eIO_Success iff some data have been written; error code otherwise */ static EIO_Status s_WriteData(SOCK sock, const void* data, size_t size, size_t* n_written, int/*bool*/ oob) { - assert(sock->type == eSocket && !sock->pending && size > 0); + assert(sock->type == eSocket && !sock->pending && size); if (sock->session) { int error; @@ -3408,6 +3415,7 @@ static EIO_Status s_WriteData(SOCK sock, status = sslwrite(sock->session, data, size, n_written, &error); assert((status == eIO_Success) == (*n_written > 0)); assert(status == eIO_Success || error); + assert(*n_written <= size); /* statistics & logging */ if ((status != eIO_Success && sock->log != eOff) || @@ -3443,16 +3451,17 @@ static size_t x_WriteBuf(void* data, const void* buf, size_t size) do { size_t x_written; ctx->status = s_WriteData(ctx->sock, buf, size, &x_written, 0); - if (ctx->status != eIO_Success) { - assert(!x_written); + assert((ctx->status == eIO_Success) == (x_written > 0)); + assert(x_written <= size); + if (ctx->status != eIO_Success) break; - } n_written += x_written; size -= x_written; buf = (const char*) buf + x_written; } while (size); assert(!size/*n_written == initial size*/ || ctx->status != eIO_Success); + return n_written; } @@ -3565,7 +3574,7 @@ static EIO_Status s_Write_(SOCK sock, return size ? status : eIO_Success; } - assert(sock->w_len == 0); + assert(size && sock->w_len == 0); return s_WriteData(sock, data, size, n_written, oob); } @@ -3579,11 +3588,11 @@ static EIO_Status s_Write(SOCK sock, EIO_Status status = s_Write_(sock, data, size, n_written, oob); if (s_ErrHook && status != eIO_Success) { SSOCK_ErrInfo info; + char addr[40]; memset(&info, 0, sizeof(info)); info.type = eSOCK_ErrIO; info.sock = sock; if (sock->port) { - char addr[40]; SOCK_ntoa(sock->host, addr, sizeof(addr)); info.host = addr; info.port = sock->port; @@ -3648,7 +3657,7 @@ static EIO_Status s_Shutdown(SOCK sock, case eIO_Close: if (sock->w_status != eIO_Closed) { if ((status = s_WritePending(sock, tv, 0, 0)) != eIO_Success) { - if (!sock->pending && sock->w_len) { + if (!sock->pending && sock->w_len) { CORE_LOGF_X(13, !tv || (tv->tv_sec | tv->tv_usec) ? eLOG_Warning : eLOG_Trace, ("%s[SOCK::%s] " @@ -3665,7 +3674,7 @@ static EIO_Status s_Shutdown(SOCK sock, } else if (!(dir & eIO_ReadWrite)) status = eIO_Success; } - if (sock->session && !sock->pending) { + if (!sock->pending && sock->session) { FSSLClose sslclose = s_SSL ? s_SSL->Close : 0; assert(sock->session != SESSION_INVALID); if (sslclose) { @@ -3714,11 +3723,7 @@ static EIO_Status s_Shutdown(SOCK sock, } assert((EIO_Event)(dir | eIO_ReadWrite) == eIO_ReadWrite); -#ifndef NCBI_OS_MSWIN - /* on MS-Win, socket shutdown for write apparently messes up (?!) - * with later reading, especially when reading a lot of data... */ - -# ifdef NCBI_OS_BSD +#ifdef NCBI_OS_BSD /* at least on FreeBSD: shutting down a socket for write (i.e. forcing to * send a FIN) for a socket that has been already closed by another end * (e.g. when peer has done writing, so this end has done reading and is @@ -3726,38 +3731,27 @@ static EIO_Status s_Shutdown(SOCK sock, * see kern/146845 @ http://www.freebsd.org/cgi/query-pr.cgi?pr=146845 */ if (dir == eIO_ReadWrite && how != SOCK_SHUTDOWN_RDWR) return status; -# endif /*NCBI_OS_BSD*/ +#endif /*NCBI_OS_BSD*/ -# ifdef NCBI_OS_UNIX +#ifdef NCBI_OS_UNIX if (sock->path[0]) return status; -# endif /*NCBI_OS_UNIX*/ +#endif /*NCBI_OS_UNIX*/ + +#ifndef NCBI_OS_MSWIN + /* on MS-Win, socket shutdown for write apparently messes up (?!) + * with later reading, especially when reading a lot of data... */ if (s_Initialized > 0 && shutdown(sock->sock, how) != 0) { - error = SOCK_ERRNO; -# ifdef NCBI_OS_MSWIN - if (error == WSANOTINITIALISED) - s_Initialized = -1/*deinited*/; - else -# endif /*NCBI_OS_MSWIN*/ - if ( -# if defined(NCBI_OS_LINUX)/*bug in the Linux kernel to report*/ || \ - defined(NCBI_OS_IRIX) || \ - defined(NCBI_OS_OSF1) - error != SOCK_ENOTCONN -# else - error != SOCK_ENOTCONN || sock->pending -# endif /*UNIX flavors*/ - ) { - const char* strerr = SOCK_STRERROR(error); - CORE_LOGF_ERRNO_EXX(16, eLOG_Trace, - error, strerr ? strerr : "", - ("%s[SOCK::Shutdown] " - " Failed shutdown(%s)", - s_ID(sock, _id), dir == eIO_Read ? "R" : - dir == eIO_Write ? "W" : "RW")); - UTIL_ReleaseBuffer(strerr); - } + const char* strerr = SOCK_STRERROR(error = SOCK_ERRNO); + CORE_LOGF_ERRNO_EXX(16, eLOG_Trace, + error, strerr ? strerr : "", + ("%s[SOCK::Shutdown] " + " Failed shutdown(%s)", + s_ID(sock, _id), dir == eIO_Read ? "R" : + dir == eIO_Write ? "W" : "RW")); + UTIL_ReleaseBuffer(strerr); + status = eIO_Unknown; } #endif /*!NCBI_OS_MSWIN*/ @@ -3952,14 +3946,20 @@ static EIO_Status s_Close_(SOCK sock, int abort) static EIO_Status s_Close(SOCK sock) { +#if defined NCBI_MONKEY + /* Not interception of close(). + We only tell Monkey to "forget" this socket */ + if (g_MONKEY_Close != NULL) + g_MONKEY_Close(sock->sock); +#endif /* NCBI_MONKEY */ EIO_Status status = s_Close_(sock, 0/*orderly*/); if (s_ErrHook && status != eIO_Success) { SSOCK_ErrInfo info; + char addr[40]; memset(&info, 0, sizeof(info)); info.type = eSOCK_ErrIO; info.sock = sock; if (sock->port) { - char addr[40]; SOCK_ntoa(sock->host, addr, sizeof(addr)); info.host = addr; info.port = sock->port; @@ -4053,6 +4053,11 @@ static EIO_Status s_Connect_(SOCK sock, } else #endif /*NCBI_OS_UNIX*/ { + /* first, set the port to connect to (same port if zero) */ + if (port) + sock->port = port; + else + assert(sock->port); /* get address of the remote host (assume the same host if NULL) */ if (host && !(sock->host = s_gethostbyname(host, (ESwitch)sock->log))){ CORE_LOGF_X(22, eLOG_Error, @@ -4061,11 +4066,6 @@ static EIO_Status s_Connect_(SOCK sock, s_ID(sock, _id), MAXHOSTNAMELEN, host)); return eIO_Unknown; } - /* set the port to connect to (same port if zero) */ - if (port) - sock->port = port; - else - assert(sock->port); addrlen = (TSOCK_socklen_t) sizeof(addr.in); #ifdef HAVE_SIN_LEN addr.in.sin_len = addrlen; @@ -4284,22 +4284,16 @@ static EIO_Status s_Connect(SOCK sock, EIO_Status status = s_Connect_(sock, host, port, timeout); if (status != eIO_Success) { SSOCK_ErrInfo info; + char addr[40]; memset(&info, 0, sizeof(info)); info.type = eSOCK_ErrIO; info.sock = sock; - if (sock->port) { - char addr[40]; - if (sock->host) { - SOCK_ntoa(sock->host, addr, sizeof(addr)); - info.host = addr; - } else - info.host = host; - info.port = port; - } -#ifdef NCBI_OS_UNIX - else - info.host = sock->path; -#endif /*NCBI_OS_UNIX*/ + if (sock->host) { + SOCK_ntoa(sock->host, addr, sizeof(addr)); + info.host = addr; + } else + info.host = host; + info.port = port; info.status = status; s_ErrorCallback(&info); } @@ -6252,11 +6246,11 @@ extern EIO_Status SOCK_Shutdown(SOCK sock, status = s_Shutdown(sock, dir, SOCK_GET_TIMEOUT(sock, c)); if (s_ErrHook && status != eIO_Success) { SSOCK_ErrInfo info; + char addr[40]; memset(&info, 0, sizeof(info)); info.type = eSOCK_ErrIO; info.sock = sock; if (sock->port) { - char addr[40]; SOCK_ntoa(sock->host, addr, sizeof(addr)); info.host = addr; info.port = sock->port; @@ -6346,6 +6340,7 @@ extern EIO_Status SOCK_CloseOSHandle(const void* handle, size_t handle_size) error == SOCK_ENETRESET || error == SOCK_ECONNRESET || error == SOCK_ECONNABORTED) { + status = eIO_Closed; break; } if (error != SOCK_EINTR) { @@ -6467,11 +6462,11 @@ extern EIO_Status SOCK_Wait(SOCK sock, status = s_Wait(sock, event, timeout); if (s_ErrHook && status != eIO_Success && status != eIO_Timeout) { SSOCK_ErrInfo info; + char addr[40]; memset(&info, 0, sizeof(info)); info.type = eSOCK_ErrIO; info.sock = sock; if (sock->port) { - char addr[40]; SOCK_ntoa(sock->host, addr, sizeof(addr)); info.host = addr; info.port = sock->port; @@ -6493,38 +6488,82 @@ extern EIO_Status SOCK_Poll(size_t n, const STimeout* timeout, size_t* n_ready) { + EIO_Status status; +#if defined NCBI_MONKEY + int/*bool*/ call_intercepted = 0; + size_t orig_n = n; + SSOCK_Poll* orig_polls = polls; /* to know if 'polls' was replaced */ + EIO_Status mnk_status = -1; + if (g_MONKEY_Poll != NULL) { + /* Not a poll function itself, just removes some of "polls" items */ + call_intercepted = g_MONKEY_Poll(&n, &polls, &mnk_status); + } + /* Even if call was intercepted, s_Select continues as if nothing + happened, because what we did is just removed some SSOCK_Poll pointers. + The changes made in s_Select will appear in the original array, but only + for those SSOCK_Poll's that were left by Monkey */ +#endif /* defined NCBI_MONKEY */ struct timeval tv; size_t i; if (n && !polls) { - if ( n_ready ) + if (n_ready) *n_ready = 0; return eIO_InvalidArg; } - for (i = 0; i < n; i++) { + for (i = 0; i < n; i++) { SOCK sock = polls[i].sock; polls[i].revent = - sock && sock->type == eTrigger && ((TRIGGER) sock)->isset.ptr + sock && sock->type == eTrigger && ((TRIGGER)sock)->isset.ptr ? polls[i].event : eIO_Open; - if (!sock || !(sock->type & eSocket) || sock->sock == SOCK_INVALID) + if (!sock || !(sock->type & eSocket) || sock->sock == SOCK_INVALID) continue; - if ((polls[i].event & eIO_Read) && BUF_Size(sock->r_buf) != 0) { + if ((polls[i].event & eIO_Read) && BUF_Size(sock->r_buf) != 0) { polls[i].revent = eIO_Read; continue; } if (sock->type != eSocket) continue; if ((polls[i].event == eIO_Read - && (sock->r_status == eIO_Closed || sock->eof)) || + && (sock->r_status == eIO_Closed || sock->eof)) || (polls[i].event == eIO_Write - && sock->w_status == eIO_Closed)) { + && sock->w_status == eIO_Closed)) { polls[i].revent = eIO_Close; } } - return s_SelectStallsafe(n, polls, s_to2tv(timeout, &tv), n_ready); + status = s_SelectStallsafe(n, polls, s_to2tv(timeout, &tv), n_ready); +#if defined NCBI_MONKEY + /* Copy poll results to the original array. Probably Monkey excluded + * some sockets from array, so we need two iterators */ + if (orig_polls != polls) { + size_t orig_iter = 0, new_iter = 0; + /* First - initialize events with eIO_Open (no event) */ + for (orig_iter = 0; orig_iter < orig_n; orig_iter++) { + orig_polls[orig_iter].event = eIO_Open /* no event */; + orig_polls[orig_iter].revent = eIO_Open /* no event */; + } + for (; new_iter < n; new_iter++) { + while (orig_iter < orig_n) { + if (orig_polls[orig_iter].sock->sock + == polls[new_iter].sock->sock) { + orig_polls[orig_iter].event = polls[new_iter].event; + orig_polls[orig_iter].revent = polls[new_iter].revent; + break; /* Item found! Now increase new_iter */ + } + orig_iter++; + } + } + free(polls); + polls = orig_polls; + if (mnk_status != -1) { + return mnk_status; + } + } +#endif /* defined NCBI_MONKEY */ + return status; } @@ -7525,8 +7564,8 @@ extern EIO_Status DSOCK_RecvMsg(SOCK sock, status = s_RecvMsg(sock, buf, bufsize, msgsize, msglen, sender_addr, sender_port); if (s_ErrHook && status != eIO_Success) { - char addr[40]; SSOCK_ErrInfo info; + char addr[40]; memset(&info, 0, sizeof(info)); info.type = eSOCK_ErrIO; info.sock = sock; @@ -7568,8 +7607,8 @@ extern EIO_Status DSOCK_SendMsg(SOCK sock, status = s_SendMsg(sock, host, port, data, datalen); if (s_ErrHook && status != eIO_Success) { - char addr[40]; SSOCK_ErrInfo info; + char addr[40]; memset(&info, 0, sizeof(info)); info.type = eSOCK_ErrIO; info.sock = sock; @@ -7953,7 +7992,7 @@ extern int/*bool*/ SOCK_isipEx(const char* str, int/*bool*/ fullquad) if (!isdigit((unsigned char)(*str))) return 0/*false*/; errno = 0; - val = strtoul(str, &e, fullquad ? 10 : 0); + val = strtoul(str, &e, 0); if (errno || str == e) return 0/*false*/; str = e; @@ -7983,7 +8022,7 @@ extern int/*bool*/ SOCK_IsLoopbackAddress(unsigned int ip) && (addr & IN_CLASSA_NET) == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT); #else return !((addr & 0xFF000000) ^ (INADDR_LOOPBACK-1)); -# endif /*IN_CLASSA && IN_CLASSA_NET && IN_CLASSA_NSHIFT*/ +#endif /*IN_CLASSA && IN_CLASSA_NET && IN_CLASSA_NSHIFT*/ } return 0/*false*/; } @@ -8218,6 +8257,8 @@ extern void SOCK_SetupSSL(FSSLSetup setup) CORE_LOG(eLOG_Critical, "Cannot reset SSL while it is in use"); } + g_CORE_Set |= eCORE_SetSSL; + CORE_UNLOCK; } diff --git a/c++/src/connect/ncbi_util.c b/c++/src/connect/ncbi_util.c index 0dbe8fa4..55205f56 100644 --- a/c++/src/connect/ncbi_util.c +++ b/c++/src/connect/ncbi_util.c @@ -1,4 +1,4 @@ -/* $Id: ncbi_util.c 488579 2016-01-01 00:38:12Z lavr $ +/* $Id: ncbi_util.c 507875 2016-07-21 21:24:44Z lavr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -72,7 +72,6 @@ #define NCBI_USE_PRECOMPILED_CRC32_TABLES 1 - /****************************************************************************** * MT locking */ @@ -81,6 +80,7 @@ extern void CORE_SetLOCK(MT_LOCK lk) { MT_LOCK old_lk = g_CORE_MT_Lock; g_CORE_MT_Lock = lk; + g_CORE_Set |= eCORE_SetLOCK; if (old_lk && old_lk != lk) MT_LOCK_Delete(old_lk); } @@ -104,6 +104,7 @@ extern void CORE_SetLOG(LOG lg) CORE_LOCK_WRITE; old_lg = g_CORE_Log; g_CORE_Log = lg; + g_CORE_Set |= eCORE_SetLOG; CORE_UNLOCK; if (old_lg && old_lg != lg) LOG_Delete(old_lg); @@ -610,6 +611,7 @@ extern void CORE_SetREG(REG rg) CORE_LOCK_WRITE; old_rg = g_CORE_Registry; g_CORE_Registry = rg; + g_CORE_Set |= eCORE_SetREG; CORE_UNLOCK; if (old_rg && old_rg != rg) REG_Delete(old_rg); diff --git a/c++/src/connect/parson.c b/c++/src/connect/parson.c new file mode 100644 index 00000000..9b6267be --- /dev/null +++ b/c++/src/connect/parson.c @@ -0,0 +1,1767 @@ +/* + Parson ( http://kgabis.github.com/parson/ ) + Copyright (c) 2012 - 2016 Krzysztof Gabis + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ +#ifdef _MSC_VER +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS +#endif /* _CRT_SECURE_NO_WARNINGS */ +#endif /* _MSC_VER */ + +#include "parson.h" + +#include +#include +#include +#include +#include + +#define STARTING_CAPACITY 15 +#define ARRAY_MAX_CAPACITY 122880 /* 15*(2^13) */ +#define OBJECT_MAX_CAPACITY 960 /* 15*(2^6) */ +#define MAX_NESTING 19 +#define DOUBLE_SERIALIZATION_FORMAT "%f" + +#define SIZEOF_TOKEN(a) (sizeof(a) - 1) +#define SKIP_CHAR(str) ((*str)++) +#define SKIP_WHITESPACES(str) while (isspace(**str)) { SKIP_CHAR(str); } +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + +#undef malloc +#undef free + +static x_JSON_Malloc_Function parson_malloc = malloc; +static x_JSON_Free_Function parson_free = free; + +#define IS_CONT(b) (((unsigned char)(b) & 0xC0) == 0x80) /* is utf-8 continuation byte */ + +/* Type definitions */ +typedef union x_json_value_value { + char *string; + double number; + x_JSON_Object *object; + x_JSON_Array *array; + int boolean; + int null; +} x_JSON_Value_Value; + +struct x_json_value_t { + x_JSON_Value_Type type; + x_JSON_Value_Value value; +}; + +struct x_json_object_t { + char **names; + x_JSON_Value **values; + size_t count; + size_t capacity; +}; + +struct x_json_array_t { + x_JSON_Value **items; + size_t count; + size_t capacity; +}; + +/* Various */ +static char * read_file(const char *filename); +static void remove_comments(char *string, const char *start_token, const char *end_token); +static char * parson_strndup(const char *string, size_t n); +static char * parson_strdup(const char *string); +static int is_utf16_hex(const unsigned char *string); +static int num_bytes_in_utf8_sequence(unsigned char c); +static int verify_utf8_sequence(const unsigned char *string, int *len); +static int is_valid_utf8(const char *string, size_t string_len); +static int is_decimal(const char *string, size_t length); + +/* JSON Object */ +static x_JSON_Object * x_json_object_init(void); +static x_JSON_Status x_json_object_add(x_JSON_Object *object, const char *name, x_JSON_Value *value); +static x_JSON_Status x_json_object_resize(x_JSON_Object *object, size_t new_capacity); +static x_JSON_Value * x_json_object_nget_value(const x_JSON_Object *object, const char *name, size_t n); +static void x_json_object_free(x_JSON_Object *object); + +/* JSON Array */ +static x_JSON_Array * x_json_array_init(void); +static x_JSON_Status x_json_array_add(x_JSON_Array *array, x_JSON_Value *value); +static x_JSON_Status x_json_array_resize(x_JSON_Array *array, size_t new_capacity); +static void x_json_array_free(x_JSON_Array *array); + +/* JSON Value */ +static x_JSON_Value * x_json_value_init_string_no_copy(char *string); + +/* Parser */ +static void skip_quotes(const char **string); +static int parse_utf_16(const char **unprocessed, char **processed); +static char * process_string(const char *input, size_t len); +static char * get_quoted_string(const char **string); +static x_JSON_Value * parse_object_value(const char **string, size_t nesting); +static x_JSON_Value * parse_array_value(const char **string, size_t nesting); +static x_JSON_Value * parse_string_value(const char **string); +static x_JSON_Value * parse_boolean_value(const char **string); +static x_JSON_Value * parse_number_value(const char **string); +static x_JSON_Value * parse_null_value(const char **string); +static x_JSON_Value * parse_value(const char **string, size_t nesting); + +/* Serialization */ +static int x_json_serialize_to_buffer_r(const x_JSON_Value *value, char *buf, int level, int is_pretty, char *num_buf); +static int x_json_serialize_string(const char *string, char *buf); +static int append_indent(char *buf, int level); +static int append_string(char *buf, const char *string); + +/* Various */ +static char * parson_strndup(const char *string, size_t n) { + char *output_string = (char*)parson_malloc(n + 1); + if (!output_string) + return NULL; + output_string[n] = '\0'; + strncpy(output_string, string, n); + return output_string; +} + +static char * parson_strdup(const char *string) { + return parson_strndup(string, strlen(string)); +} + +static int is_utf16_hex(const unsigned char *s) { + return isxdigit(s[0]) && isxdigit(s[1]) && isxdigit(s[2]) && isxdigit(s[3]); +} + +static int num_bytes_in_utf8_sequence(unsigned char c) { + if (c == 0xC0 || c == 0xC1 || c > 0xF4 || IS_CONT(c)) { + return 0; + } else if ((c & 0x80) == 0) { /* 0xxxxxxx */ + return 1; + } else if ((c & 0xE0) == 0xC0) { /* 110xxxxx */ + return 2; + } else if ((c & 0xF0) == 0xE0) { /* 1110xxxx */ + return 3; + } else if ((c & 0xF8) == 0xF0) { /* 11110xxx */ + return 4; + } + return 0; /* won't happen */ +} + +static int verify_utf8_sequence(const unsigned char *string, int *len) { + unsigned int cp = 0; + *len = num_bytes_in_utf8_sequence(string[0]); + + if (*len == 1) { + cp = string[0]; + } else if (*len == 2 && IS_CONT(string[1])) { + cp = string[0] & 0x1F; + cp = (cp << 6) | (string[1] & 0x3F); + } else if (*len == 3 && IS_CONT(string[1]) && IS_CONT(string[2])) { + cp = ((unsigned char)string[0]) & 0xF; + cp = (cp << 6) | (string[1] & 0x3F); + cp = (cp << 6) | (string[2] & 0x3F); + } else if (*len == 4 && IS_CONT(string[1]) && IS_CONT(string[2]) && IS_CONT(string[3])) { + cp = string[0] & 0x7; + cp = (cp << 6) | (string[1] & 0x3F); + cp = (cp << 6) | (string[2] & 0x3F); + cp = (cp << 6) | (string[3] & 0x3F); + } else { + return 0; + } + + /* overlong encodings */ + if ((cp < 0x80 && *len > 1) || + (cp < 0x800 && *len > 2) || + (cp < 0x10000 && *len > 3)) { + return 0; + } + + /* invalid unicode */ + if (cp > 0x10FFFF) { + return 0; + } + + /* surrogate halves */ + if (cp >= 0xD800 && cp <= 0xDFFF) { + return 0; + } + + return 1; +} + +static int is_valid_utf8(const char *string, size_t string_len) { + int len = 0; + const char *string_end = string + string_len; + while (string < string_end) { + if (!verify_utf8_sequence((const unsigned char*)string, &len)) { + return 0; + } + string += len; + } + return 1; +} + +static int is_decimal(const char *string, size_t length) { + if (length > 1 && string[0] == '0' && string[1] != '.') + return 0; + if (length > 2 && !strncmp(string, "-0", 2) && string[2] != '.') + return 0; + while (length--) + if (strchr("xX", string[length])) + return 0; + return 1; +} + +static char * read_file(const char * filename) { + FILE *fp = fopen(filename, "r"); + size_t file_size; + long pos; + char *file_contents; + if (!fp) + return NULL; + fseek(fp, 0L, SEEK_END); + pos = ftell(fp); + if (pos < 0) { + fclose(fp); + return NULL; + } + file_size = pos; + rewind(fp); + file_contents = (char*)parson_malloc(sizeof(char) * (file_size + 1)); + if (!file_contents) { + fclose(fp); + return NULL; + } + if (fread(file_contents, file_size, 1, fp) < 1) { + if (ferror(fp)) { + fclose(fp); + parson_free(file_contents); + return NULL; + } + } + fclose(fp); + file_contents[file_size] = '\0'; + return file_contents; +} + +static void remove_comments(char *string, const char *start_token, const char *end_token) { + int in_string = 0, escaped = 0; + size_t i; + char *ptr = NULL, current_char; + size_t start_token_len = strlen(start_token); + size_t end_token_len = strlen(end_token); + if (start_token_len == 0 || end_token_len == 0) + return; + while ((current_char = *string) != '\0') { + if (current_char == '\\' && !escaped) { + escaped = 1; + string++; + continue; + } else if (current_char == '\"' && !escaped) { + in_string = !in_string; + } else if (!in_string && strncmp(string, start_token, start_token_len) == 0) { + for(i = 0; i < start_token_len; i++) + string[i] = ' '; + string = string + start_token_len; + ptr = strstr(string, end_token); + if (!ptr) + return; + for (i = 0; i < (ptr - string) + end_token_len; i++) + string[i] = ' '; + string = ptr + end_token_len - 1; + } + escaped = 0; + string++; + } +} + +/* JSON Object */ +static x_JSON_Object * x_json_object_init(void) { + x_JSON_Object *new_obj = (x_JSON_Object*)parson_malloc(sizeof(x_JSON_Object)); + if (!new_obj) + return NULL; + new_obj->names = (char**)NULL; + new_obj->values = (x_JSON_Value**)NULL; + new_obj->capacity = 0; + new_obj->count = 0; + return new_obj; +} + +static x_JSON_Status x_json_object_add(x_JSON_Object *object, const char *name, x_JSON_Value *value) { + size_t index = 0; + if (object == NULL || name == NULL || value == NULL) { + return JSONFailure; + } + if (x_json_object_get_value(object, name) != NULL) { + return JSONFailure; + } + if (object->count >= object->capacity) { + size_t new_capacity = MAX(object->capacity * 2, STARTING_CAPACITY); + if (new_capacity > OBJECT_MAX_CAPACITY) + return JSONFailure; + if (x_json_object_resize(object, new_capacity) == JSONFailure) + return JSONFailure; + } + index = object->count; + object->names[index] = parson_strdup(name); + if (object->names[index] == NULL) + return JSONFailure; + object->values[index] = value; + object->count++; + return JSONSuccess; +} + +static x_JSON_Status x_json_object_resize(x_JSON_Object *object, size_t new_capacity) { + char **temp_names = NULL; + x_JSON_Value **temp_values = NULL; + + if ((object->names == NULL && object->values != NULL) || + (object->names != NULL && object->values == NULL) || + new_capacity == 0) { + return JSONFailure; /* Shouldn't happen */ + } + + temp_names = (char**)parson_malloc(new_capacity * sizeof(char*)); + if (temp_names == NULL) + return JSONFailure; + + temp_values = (x_JSON_Value**)parson_malloc(new_capacity * sizeof(x_JSON_Value*)); + if (temp_values == NULL) { + parson_free(temp_names); + return JSONFailure; + } + + if (object->names != NULL && object->values != NULL && object->count > 0) { + memcpy(temp_names, object->names, object->count * sizeof(char*)); + memcpy(temp_values, object->values, object->count * sizeof(x_JSON_Value*)); + } + parson_free(object->names); + parson_free(object->values); + object->names = temp_names; + object->values = temp_values; + object->capacity = new_capacity; + return JSONSuccess; +} + +static x_JSON_Value * x_json_object_nget_value(const x_JSON_Object *object, const char *name, size_t n) { + size_t i, name_length; + for (i = 0; i < x_json_object_get_count(object); i++) { + name_length = strlen(object->names[i]); + if (name_length != n) + continue; + if (strncmp(object->names[i], name, n) == 0) + return object->values[i]; + } + return NULL; +} + +static void x_json_object_free(x_JSON_Object *object) { + while(object->count--) { + parson_free(object->names[object->count]); + x_json_value_free(object->values[object->count]); + } + parson_free(object->names); + parson_free(object->values); + parson_free(object); +} + +/* JSON Array */ +static x_JSON_Array * x_json_array_init(void) { + x_JSON_Array *new_array = (x_JSON_Array*)parson_malloc(sizeof(x_JSON_Array)); + if (!new_array) + return NULL; + new_array->items = (x_JSON_Value**)NULL; + new_array->capacity = 0; + new_array->count = 0; + return new_array; +} + +static x_JSON_Status x_json_array_add(x_JSON_Array *array, x_JSON_Value *value) { + if (array->count >= array->capacity) { + size_t new_capacity = MAX(array->capacity * 2, STARTING_CAPACITY); + if (new_capacity > ARRAY_MAX_CAPACITY) + return JSONFailure; + if (x_json_array_resize(array, new_capacity) == JSONFailure) + return JSONFailure; + } + array->items[array->count] = value; + array->count++; + return JSONSuccess; +} + +static x_JSON_Status x_json_array_resize(x_JSON_Array *array, size_t new_capacity) { + x_JSON_Value **new_items = NULL; + if (new_capacity == 0) { + return JSONFailure; + } + new_items = (x_JSON_Value**)parson_malloc(new_capacity * sizeof(x_JSON_Value*)); + if (new_items == NULL) { + return JSONFailure; + } + if (array->items != NULL && array->count > 0) { + memcpy(new_items, array->items, array->count * sizeof(x_JSON_Value*)); + } + parson_free(array->items); + array->items = new_items; + array->capacity = new_capacity; + return JSONSuccess; +} + +static void x_json_array_free(x_JSON_Array *array) { + while (array->count--) + x_json_value_free(array->items[array->count]); + parson_free(array->items); + parson_free(array); +} + +/* JSON Value */ +static x_JSON_Value * x_json_value_init_string_no_copy(char *string) { + x_JSON_Value *new_value = (x_JSON_Value*)parson_malloc(sizeof(x_JSON_Value)); + if (!new_value) + return NULL; + new_value->type = JSONString; + new_value->value.string = string; + return new_value; +} + +/* Parser */ +static void skip_quotes(const char **string) { + SKIP_CHAR(string); + while (**string != '\"') { + if (**string == '\0') + return; + if (**string == '\\') { + SKIP_CHAR(string); + if (**string == '\0') + return; + } + SKIP_CHAR(string); + } + SKIP_CHAR(string); +} + +static int parse_utf_16(const char **unprocessed, char **processed) { + unsigned int cp, lead, trail; + char *processed_ptr = *processed; + const char *unprocessed_ptr = *unprocessed; + unprocessed_ptr++; /* skips u */ + if (!is_utf16_hex((const unsigned char*)unprocessed_ptr) || sscanf(unprocessed_ptr, "%4x", &cp) == EOF) + return JSONFailure; + if (cp < 0x80) { + *processed_ptr = cp; /* 0xxxxxxx */ + } else if (cp < 0x800) { + *processed_ptr++ = ((cp >> 6) & 0x1F) | 0xC0; /* 110xxxxx */ + *processed_ptr = ((cp ) & 0x3F) | 0x80; /* 10xxxxxx */ + } else if (cp < 0xD800 || cp > 0xDFFF) { + *processed_ptr++ = ((cp >> 12) & 0x0F) | 0xE0; /* 1110xxxx */ + *processed_ptr++ = ((cp >> 6) & 0x3F) | 0x80; /* 10xxxxxx */ + *processed_ptr = ((cp ) & 0x3F) | 0x80; /* 10xxxxxx */ + } else if (cp >= 0xD800 && cp <= 0xDBFF) { /* lead surrogate (0xD800..0xDBFF) */ + lead = cp; + unprocessed_ptr += 4; /* should always be within the buffer, otherwise previous sscanf would fail */ + if (*unprocessed_ptr++ != '\\' || *unprocessed_ptr++ != 'u' || /* starts with \u? */ + !is_utf16_hex((const unsigned char*)unprocessed_ptr) || + sscanf(unprocessed_ptr, "%4x", &trail) == EOF || + trail < 0xDC00 || trail > 0xDFFF) { /* valid trail surrogate? (0xDC00..0xDFFF) */ + return JSONFailure; + } + cp = ((((lead-0xD800)&0x3FF)<<10)|((trail-0xDC00)&0x3FF))+0x010000; + *processed_ptr++ = (((cp >> 18) & 0x07) | 0xF0); /* 11110xxx */ + *processed_ptr++ = (((cp >> 12) & 0x3F) | 0x80); /* 10xxxxxx */ + *processed_ptr++ = (((cp >> 6) & 0x3F) | 0x80); /* 10xxxxxx */ + *processed_ptr = (((cp ) & 0x3F) | 0x80); /* 10xxxxxx */ + } else { /* trail surrogate before lead surrogate */ + return JSONFailure; + } + unprocessed_ptr += 3; + *processed = processed_ptr; + *unprocessed = unprocessed_ptr; + return JSONSuccess; +} + + +/* Copies and processes passed string up to supplied length. +Example: "\u006Corem ipsum" -> lorem ipsum */ +static char* process_string(const char *input, size_t len) { + const char *input_ptr = input; + size_t initial_size = (len + 1) * sizeof(char); + size_t final_size = 0; + char *output = (char*)parson_malloc(initial_size); + char *output_ptr = output; + char *resized_output = NULL; + while ((*input_ptr != '\0') && (size_t)(input_ptr - input) < len) { + if (*input_ptr == '\\') { + input_ptr++; + switch (*input_ptr) { + case '\"': *output_ptr = '\"'; break; + case '\\': *output_ptr = '\\'; break; + case '/': *output_ptr = '/'; break; + case 'b': *output_ptr = '\b'; break; + case 'f': *output_ptr = '\f'; break; + case 'n': *output_ptr = '\n'; break; + case 'r': *output_ptr = '\r'; break; + case 't': *output_ptr = '\t'; break; + case 'u': + if (parse_utf_16(&input_ptr, &output_ptr) == JSONFailure) + goto error; + break; + default: + goto error; + } + } else if ((unsigned char)*input_ptr < 0x20) { + goto error; /* 0x00-0x19 are invalid characters for json string (http://www.ietf.org/rfc/rfc4627.txt) */ + } else { + *output_ptr = *input_ptr; + } + output_ptr++; + input_ptr++; + } + *output_ptr = '\0'; + /* resize to new length */ + final_size = (size_t)(output_ptr-output) + 1; + resized_output = (char*)parson_malloc(final_size); + if (resized_output == NULL) + goto error; + memcpy(resized_output, output, final_size); + parson_free(output); + return resized_output; +error: + parson_free(output); + return NULL; +} + +/* Return processed contents of a string between quotes and + skips passed argument to a matching quote. */ +static char * get_quoted_string(const char **string) { + const char *string_start = *string; + size_t string_len = 0; + skip_quotes(string); + string_len = *string - string_start - 2; /* length without quotes */ + return process_string(string_start + 1, string_len); +} + +static x_JSON_Value * parse_value(const char **string, size_t nesting) { + if (nesting > MAX_NESTING) + return NULL; + SKIP_WHITESPACES(string); + switch (**string) { + case '{': + return parse_object_value(string, nesting + 1); + case '[': + return parse_array_value(string, nesting + 1); + case '\"': + return parse_string_value(string); + case 'f': case 't': + return parse_boolean_value(string); + case '-': + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + return parse_number_value(string); + case 'n': + return parse_null_value(string); + default: + return NULL; + } +} + +static x_JSON_Value * parse_object_value(const char **string, size_t nesting) { + x_JSON_Value *output_value = x_json_value_init_object(), *new_value = NULL; + x_JSON_Object *output_object = x_json_value_get_object(output_value); + char *new_key = NULL; + if (output_value == NULL) + return NULL; + SKIP_CHAR(string); + SKIP_WHITESPACES(string); + if (**string == '}') { /* empty object */ + SKIP_CHAR(string); + return output_value; + } + while (**string != '\0') { + new_key = get_quoted_string(string); + SKIP_WHITESPACES(string); + if (new_key == NULL || **string != ':') { + x_json_value_free(output_value); + return NULL; + } + SKIP_CHAR(string); + new_value = parse_value(string, nesting); + if (new_value == NULL) { + parson_free(new_key); + x_json_value_free(output_value); + return NULL; + } + if(x_json_object_add(output_object, new_key, new_value) == JSONFailure) { + parson_free(new_key); + parson_free(new_value); + x_json_value_free(output_value); + return NULL; + } + parson_free(new_key); + SKIP_WHITESPACES(string); + if (**string != ',') + break; + SKIP_CHAR(string); + SKIP_WHITESPACES(string); + } + SKIP_WHITESPACES(string); + if (**string != '}' || /* Trim object after parsing is over */ + x_json_object_resize(output_object, x_json_object_get_count(output_object)) == JSONFailure) { + x_json_value_free(output_value); + return NULL; + } + SKIP_CHAR(string); + return output_value; +} + +static x_JSON_Value * parse_array_value(const char **string, size_t nesting) { + x_JSON_Value *output_value = x_json_value_init_array(), *new_array_value = NULL; + x_JSON_Array *output_array = x_json_value_get_array(output_value); + if (!output_value) + return NULL; + SKIP_CHAR(string); + SKIP_WHITESPACES(string); + if (**string == ']') { /* empty array */ + SKIP_CHAR(string); + return output_value; + } + while (**string != '\0') { + new_array_value = parse_value(string, nesting); + if (!new_array_value) { + x_json_value_free(output_value); + return NULL; + } + if(x_json_array_add(output_array, new_array_value) == JSONFailure) { + parson_free(new_array_value); + x_json_value_free(output_value); + return NULL; + } + SKIP_WHITESPACES(string); + if (**string != ',') + break; + SKIP_CHAR(string); + SKIP_WHITESPACES(string); + } + SKIP_WHITESPACES(string); + if (**string != ']' || /* Trim array after parsing is over */ + x_json_array_resize(output_array, x_json_array_get_count(output_array)) == JSONFailure) { + x_json_value_free(output_value); + return NULL; + } + SKIP_CHAR(string); + return output_value; +} + +static x_JSON_Value * parse_string_value(const char **string) { + x_JSON_Value *value = NULL; + char *new_string = get_quoted_string(string); + if (new_string == NULL) + return NULL; + value = x_json_value_init_string_no_copy(new_string); + if (value == NULL) { + parson_free(new_string); + return NULL; + } + return value; +} + +static x_JSON_Value * parse_boolean_value(const char **string) { + size_t true_token_size = SIZEOF_TOKEN("true"); + size_t false_token_size = SIZEOF_TOKEN("false"); + if (strncmp("true", *string, true_token_size) == 0) { + *string += true_token_size; + return x_json_value_init_boolean(1); + } else if (strncmp("false", *string, false_token_size) == 0) { + *string += false_token_size; + return x_json_value_init_boolean(0); + } + return NULL; +} + +static x_JSON_Value * parse_number_value(const char **string) { + char *end; + double number = strtod(*string, &end); + x_JSON_Value *output_value; + if (is_decimal(*string, end - *string)) { + *string = end; + output_value = x_json_value_init_number(number); + } else { + output_value = NULL; + } + return output_value; +} + +static x_JSON_Value * parse_null_value(const char **string) { + size_t token_size = SIZEOF_TOKEN("null"); + if (strncmp("null", *string, token_size) == 0) { + *string += token_size; + return x_json_value_init_null(); + } + return NULL; +} + +/* Serialization */ +#define APPEND_STRING(str) do { written = append_string(buf, (str));\ + if (written < 0) { return -1; }\ + if (buf != NULL) { buf += written; }\ + written_total += written; } while(0) + +#define APPEND_INDENT(level) do { written = append_indent(buf, (level));\ + if (written < 0) { return -1; }\ + if (buf != NULL) { buf += written; }\ + written_total += written; } while(0) + +static int x_json_serialize_to_buffer_r(const x_JSON_Value *value, char *buf, int level, int is_pretty, char *num_buf) +{ + const char *key = NULL, *string = NULL; + x_JSON_Value *temp_value = NULL; + x_JSON_Array *array = NULL; + x_JSON_Object *object = NULL; + size_t i = 0, count = 0; + double num = 0.0; + int written = -1, written_total = 0; + + switch (x_json_value_get_type(value)) { + case JSONArray: + array = x_json_value_get_array(value); + count = x_json_array_get_count(array); + APPEND_STRING("["); + if (count > 0 && is_pretty) + APPEND_STRING("\n"); + for (i = 0; i < count; i++) { + if (is_pretty) + APPEND_INDENT(level+1); + temp_value = x_json_array_get_value(array, i); + written = x_json_serialize_to_buffer_r(temp_value, buf, level+1, is_pretty, num_buf); + if (written < 0) + return -1; + if (buf != NULL) + buf += written; + written_total += written; + if (i < (count - 1)) + APPEND_STRING(","); + if (is_pretty) + APPEND_STRING("\n"); + } + if (count > 0 && is_pretty) + APPEND_INDENT(level); + APPEND_STRING("]"); + return written_total; + case JSONObject: + object = x_json_value_get_object(value); + count = x_json_object_get_count(object); + APPEND_STRING("{"); + if (count > 0 && is_pretty) + APPEND_STRING("\n"); + for (i = 0; i < count; i++) { + key = x_json_object_get_name(object, i); + if (is_pretty) + APPEND_INDENT(level+1); + written = x_json_serialize_string(key, buf); + if (written < 0) + return -1; + if (buf != NULL) + buf += written; + written_total += written; + APPEND_STRING(":"); + if (is_pretty) + APPEND_STRING(" "); + temp_value = x_json_object_get_value(object, key); + written = x_json_serialize_to_buffer_r(temp_value, buf, level+1, is_pretty, num_buf); + if (written < 0) + return -1; + if (buf != NULL) + buf += written; + written_total += written; + if (i < (count - 1)) + APPEND_STRING(","); + if (is_pretty) + APPEND_STRING("\n"); + } + if (count > 0 && is_pretty) + APPEND_INDENT(level); + APPEND_STRING("}"); + return written_total; + case JSONString: + string = x_json_value_get_string(value); + written = x_json_serialize_string(string, buf); + if (written < 0) + return -1; + if (buf != NULL) + buf += written; + written_total += written; + return written_total; + case JSONBoolean: + if (x_json_value_get_boolean(value)) + APPEND_STRING("true"); + else + APPEND_STRING("false"); + return written_total; + case JSONNumber: + num = x_json_value_get_number(value); + if (buf != NULL) + num_buf = buf; + if (num == ((double)(int)num)) /* check if num is integer */ + written = sprintf(num_buf, "%d", (int)num); + else + written = sprintf(num_buf, DOUBLE_SERIALIZATION_FORMAT, num); + if (written < 0) + return -1; + if (buf != NULL) + buf += written; + written_total += written; + return written_total; + case JSONNull: + APPEND_STRING("null"); + return written_total; + case JSONError: + return -1; + default: + return -1; + } +} + +static int x_json_serialize_string(const char *string, char *buf) { + size_t i = 0, len = strlen(string); + char c = '\0'; + int written = -1, written_total = 0; + APPEND_STRING("\""); + for (i = 0; i < len; i++) { + c = string[i]; + switch (c) { + case '\"': APPEND_STRING("\\\""); break; + case '\\': APPEND_STRING("\\\\"); break; + case '/': APPEND_STRING("\\/"); break; /* to make json embeddable in xml\/html */ + case '\b': APPEND_STRING("\\b"); break; + case '\f': APPEND_STRING("\\f"); break; + case '\n': APPEND_STRING("\\n"); break; + case '\r': APPEND_STRING("\\r"); break; + case '\t': APPEND_STRING("\\t"); break; + default: + if (buf != NULL) { + buf[0] = c; + buf += 1; + } + written_total += 1; + break; + } + } + APPEND_STRING("\""); + return written_total; +} + +static int append_indent(char *buf, int level) { + int i; + int written = -1, written_total = 0; + for (i = 0; i < level; i++) { + APPEND_STRING(" "); + } + return written_total; +} + +static int append_string(char *buf, const char *string) { + if (buf == NULL) { + return (int)strlen(string); + } + return sprintf(buf, "%s", string); +} + +#undef APPEND_STRING +#undef APPEND_INDENT + +/* Parser API */ +x_JSON_Value * x_json_parse_file(const char *filename) { + char *file_contents = read_file(filename); + x_JSON_Value *output_value = NULL; + if (file_contents == NULL) + return NULL; + output_value = x_json_parse_string(file_contents); + parson_free(file_contents); + return output_value; +} + +x_JSON_Value * x_json_parse_file_with_comments(const char *filename) { + char *file_contents = read_file(filename); + x_JSON_Value *output_value = NULL; + if (file_contents == NULL) + return NULL; + output_value = x_json_parse_string_with_comments(file_contents); + parson_free(file_contents); + return output_value; +} + +x_JSON_Value * x_json_parse_string(const char *string) { + if (string == NULL) + return NULL; + return parse_value((const char**)&string, 0); +} + +x_JSON_Value * x_json_parse_string_with_comments(const char *string) { + x_JSON_Value *result = NULL; + char *string_mutable_copy = NULL, *string_mutable_copy_ptr = NULL; + string_mutable_copy = parson_strdup(string); + if (string_mutable_copy == NULL) + return NULL; + remove_comments(string_mutable_copy, "/*", "*/"); + remove_comments(string_mutable_copy, "//", "\n"); + string_mutable_copy_ptr = string_mutable_copy; + result = parse_value((const char**)&string_mutable_copy_ptr, 0); + parson_free(string_mutable_copy); + return result; +} + +/* JSON Object API */ + +x_JSON_Value * x_json_object_get_value(const x_JSON_Object *object, const char *name) { + if (object == NULL || name == NULL) + return NULL; + return x_json_object_nget_value(object, name, strlen(name)); +} + +const char * x_json_object_get_string(const x_JSON_Object *object, const char *name) { + return x_json_value_get_string(x_json_object_get_value(object, name)); +} + +double x_json_object_get_number(const x_JSON_Object *object, const char *name) { + return x_json_value_get_number(x_json_object_get_value(object, name)); +} + +x_JSON_Object * x_json_object_get_object(const x_JSON_Object *object, const char *name) { + return x_json_value_get_object(x_json_object_get_value(object, name)); +} + +x_JSON_Array * x_json_object_get_array(const x_JSON_Object *object, const char *name) { + return x_json_value_get_array(x_json_object_get_value(object, name)); +} + +int x_json_object_get_boolean(const x_JSON_Object *object, const char *name) { + return x_json_value_get_boolean(x_json_object_get_value(object, name)); +} + +x_JSON_Value * x_json_object_dotget_value(const x_JSON_Object *object, const char *name) { + const char *dot_position = strchr(name, '.'); + if (!dot_position) + return x_json_object_get_value(object, name); + object = x_json_value_get_object(x_json_object_nget_value(object, name, dot_position - name)); + return x_json_object_dotget_value(object, dot_position + 1); +} + +const char * x_json_object_dotget_string(const x_JSON_Object *object, const char *name) { + return x_json_value_get_string(x_json_object_dotget_value(object, name)); +} + +double x_json_object_dotget_number(const x_JSON_Object *object, const char *name) { + return x_json_value_get_number(x_json_object_dotget_value(object, name)); +} + +x_JSON_Object * x_json_object_dotget_object(const x_JSON_Object *object, const char *name) { + return x_json_value_get_object(x_json_object_dotget_value(object, name)); +} + +x_JSON_Array * x_json_object_dotget_array(const x_JSON_Object *object, const char *name) { + return x_json_value_get_array(x_json_object_dotget_value(object, name)); +} + +int x_json_object_dotget_boolean(const x_JSON_Object *object, const char *name) { + return x_json_value_get_boolean(x_json_object_dotget_value(object, name)); +} + +size_t x_json_object_get_count(const x_JSON_Object *object) { + return object ? object->count : 0; +} + +const char * x_json_object_get_name(const x_JSON_Object *object, size_t index) { + if (object == NULL || index >= x_json_object_get_count(object)) + return NULL; + return object->names[index]; +} + +x_JSON_Value * x_json_object_get_value_at(const x_JSON_Object *object, size_t index) { + if (object == NULL || index >= x_json_object_get_count(object)) + return NULL; + return object->values[index]; +} + +/* JSON Array API */ +x_JSON_Value * x_json_array_get_value(const x_JSON_Array *array, size_t index) { + if (array == NULL || index >= x_json_array_get_count(array)) + return NULL; + return array->items[index]; +} + +const char * x_json_array_get_string(const x_JSON_Array *array, size_t index) { + return x_json_value_get_string(x_json_array_get_value(array, index)); +} + +double x_json_array_get_number(const x_JSON_Array *array, size_t index) { + return x_json_value_get_number(x_json_array_get_value(array, index)); +} + +x_JSON_Object * x_json_array_get_object(const x_JSON_Array *array, size_t index) { + return x_json_value_get_object(x_json_array_get_value(array, index)); +} + +x_JSON_Array * x_json_array_get_array(const x_JSON_Array *array, size_t index) { + return x_json_value_get_array(x_json_array_get_value(array, index)); +} + +int x_json_array_get_boolean(const x_JSON_Array *array, size_t index) { + return x_json_value_get_boolean(x_json_array_get_value(array, index)); +} + +size_t x_json_array_get_count(const x_JSON_Array *array) { + return array ? array->count : 0; +} + +/* JSON Value API */ +x_JSON_Value_Type x_json_value_get_type(const x_JSON_Value *value) { + return value ? value->type : JSONError; +} + +x_JSON_Object * x_json_value_get_object(const x_JSON_Value *value) { + return x_json_value_get_type(value) == JSONObject ? value->value.object : NULL; +} + +x_JSON_Array * x_json_value_get_array(const x_JSON_Value *value) { + return x_json_value_get_type(value) == JSONArray ? value->value.array : NULL; +} + +const char * x_json_value_get_string(const x_JSON_Value *value) { + return x_json_value_get_type(value) == JSONString ? value->value.string : NULL; +} + +double x_json_value_get_number(const x_JSON_Value *value) { + return x_json_value_get_type(value) == JSONNumber ? value->value.number : 0; +} + +int x_json_value_get_boolean(const x_JSON_Value *value) { + return x_json_value_get_type(value) == JSONBoolean ? value->value.boolean : -1; +} + +void x_json_value_free(x_JSON_Value *value) { + switch (x_json_value_get_type(value)) { + case JSONObject: + x_json_object_free(value->value.object); + break; + case JSONString: + if (value->value.string) { parson_free(value->value.string); } + break; + case JSONArray: + x_json_array_free(value->value.array); + break; + default: + break; + } + parson_free(value); +} + +x_JSON_Value * x_json_value_init_object(void) { + x_JSON_Value *new_value = (x_JSON_Value*)parson_malloc(sizeof(x_JSON_Value)); + if (!new_value) + return NULL; + new_value->type = JSONObject; + new_value->value.object = x_json_object_init(); + if (!new_value->value.object) { + parson_free(new_value); + return NULL; + } + return new_value; +} + +x_JSON_Value * x_json_value_init_array(void) { + x_JSON_Value *new_value = (x_JSON_Value*)parson_malloc(sizeof(x_JSON_Value)); + if (!new_value) + return NULL; + new_value->type = JSONArray; + new_value->value.array = x_json_array_init(); + if (!new_value->value.array) { + parson_free(new_value); + return NULL; + } + return new_value; +} + +x_JSON_Value * x_json_value_init_string(const char *string) { + char *copy = NULL; + x_JSON_Value *value; + size_t string_len = 0; + if (string == NULL) + return NULL; + string_len = strlen(string); + if (!is_valid_utf8(string, string_len)) + return NULL; + copy = parson_strndup(string, string_len); + if (copy == NULL) + return NULL; + value = x_json_value_init_string_no_copy(copy); + if (value == NULL) + parson_free(copy); + return value; +} + +x_JSON_Value * x_json_value_init_number(double number) { + x_JSON_Value *new_value = (x_JSON_Value*)parson_malloc(sizeof(x_JSON_Value)); + if (!new_value) + return NULL; + new_value->type = JSONNumber; + new_value->value.number = number; + return new_value; +} + +x_JSON_Value * x_json_value_init_boolean(int boolean) { + x_JSON_Value *new_value = (x_JSON_Value*)parson_malloc(sizeof(x_JSON_Value)); + if (!new_value) + return NULL; + new_value->type = JSONBoolean; + new_value->value.boolean = boolean ? 1 : 0; + return new_value; +} + +x_JSON_Value * x_json_value_init_null(void) { + x_JSON_Value *new_value = (x_JSON_Value*)parson_malloc(sizeof(x_JSON_Value)); + if (!new_value) + return NULL; + new_value->type = JSONNull; + return new_value; +} + +x_JSON_Value * x_json_value_deep_copy(const x_JSON_Value *value) { + size_t i = 0; + x_JSON_Value *return_value = NULL, *temp_value_copy = NULL, *temp_value = NULL; + const char *temp_string = NULL, *temp_key = NULL; + char *temp_string_copy = NULL; + x_JSON_Array *temp_array = NULL, *temp_array_copy = NULL; + x_JSON_Object *temp_object = NULL, *temp_object_copy = NULL; + + switch (x_json_value_get_type(value)) { + case JSONArray: + temp_array = x_json_value_get_array(value); + return_value = x_json_value_init_array(); + if (return_value == NULL) + return NULL; + temp_array_copy = x_json_value_get_array(return_value); + for (i = 0; i < x_json_array_get_count(temp_array); i++) { + temp_value = x_json_array_get_value(temp_array, i); + temp_value_copy = x_json_value_deep_copy(temp_value); + if (temp_value_copy == NULL) { + x_json_value_free(return_value); + return NULL; + } + if (x_json_array_add(temp_array_copy, temp_value_copy) == JSONFailure) { + x_json_value_free(return_value); + x_json_value_free(temp_value_copy); + return NULL; + } + } + return return_value; + case JSONObject: + temp_object = x_json_value_get_object(value); + return_value = x_json_value_init_object(); + if (return_value == NULL) + return NULL; + temp_object_copy = x_json_value_get_object(return_value); + for (i = 0; i < x_json_object_get_count(temp_object); i++) { + temp_key = x_json_object_get_name(temp_object, i); + temp_value = x_json_object_get_value(temp_object, temp_key); + temp_value_copy = x_json_value_deep_copy(temp_value); + if (temp_value_copy == NULL) { + x_json_value_free(return_value); + return NULL; + } + if (x_json_object_add(temp_object_copy, temp_key, temp_value_copy) == JSONFailure) { + x_json_value_free(return_value); + x_json_value_free(temp_value_copy); + return NULL; + } + } + return return_value; + case JSONBoolean: + return x_json_value_init_boolean(x_json_value_get_boolean(value)); + case JSONNumber: + return x_json_value_init_number(x_json_value_get_number(value)); + case JSONString: + temp_string = x_json_value_get_string(value); + temp_string_copy = parson_strdup(temp_string); + if (temp_string_copy == NULL) + return NULL; + return_value = x_json_value_init_string_no_copy(temp_string_copy); + if (return_value == NULL) + parson_free(temp_string_copy); + return return_value; + case JSONNull: + return x_json_value_init_null(); + case JSONError: + return NULL; + default: + return NULL; + } +} + +size_t x_json_serialization_size(const x_JSON_Value *value) { + char num_buf[1100]; /* recursively allocating buffer on stack is a bad idea, so let's do it only once */ + int res = x_json_serialize_to_buffer_r(value, NULL, 0, 0, num_buf); + return res < 0 ? 0 : (size_t)(res + 1); +} + +x_JSON_Status x_json_serialize_to_buffer(const x_JSON_Value *value, char *buf, size_t buf_size_in_bytes) { + int written = -1; + size_t needed_size_in_bytes = x_json_serialization_size(value); + if (needed_size_in_bytes == 0 || buf_size_in_bytes < needed_size_in_bytes) { + return JSONFailure; + } + written = x_json_serialize_to_buffer_r(value, buf, 0, 0, NULL); + if (written < 0) + return JSONFailure; + return JSONSuccess; +} + +x_JSON_Status x_json_serialize_to_file(const x_JSON_Value *value, const char *filename) { + x_JSON_Status return_code = JSONSuccess; + FILE *fp = NULL; + char *serialized_string = x_json_serialize_to_string(value); + if (serialized_string == NULL) { + return JSONFailure; + } + fp = fopen (filename, "w"); + if (fp == NULL) { + x_json_free_serialized_string(serialized_string); + return JSONFailure; + } + if (fputs(serialized_string, fp) == EOF) { + return_code = JSONFailure; + } + if (fclose(fp) == EOF) { + return_code = JSONFailure; + } + x_json_free_serialized_string(serialized_string); + return return_code; +} + +char * x_json_serialize_to_string(const x_JSON_Value *value) { + x_JSON_Status serialization_result = JSONFailure; + size_t buf_size_bytes = x_json_serialization_size(value); + char *buf = NULL; + if (buf_size_bytes == 0) { + return NULL; + } + buf = (char*)parson_malloc(buf_size_bytes); + if (buf == NULL) + return NULL; + serialization_result = x_json_serialize_to_buffer(value, buf, buf_size_bytes); + if (serialization_result == JSONFailure) { + x_json_free_serialized_string(buf); + return NULL; + } + return buf; +} + +size_t x_json_serialization_size_pretty(const x_JSON_Value *value) { + char num_buf[1100]; /* recursively allocating buffer on stack is a bad idea, so let's do it only once */ + int res = x_json_serialize_to_buffer_r(value, NULL, 0, 1, num_buf); + return res < 0 ? 0 : (size_t)(res + 1); +} + +x_JSON_Status x_json_serialize_to_buffer_pretty(const x_JSON_Value *value, char *buf, size_t buf_size_in_bytes) { + int written = -1; + size_t needed_size_in_bytes = x_json_serialization_size_pretty(value); + if (needed_size_in_bytes == 0 || buf_size_in_bytes < needed_size_in_bytes) + return JSONFailure; + written = x_json_serialize_to_buffer_r(value, buf, 0, 1, NULL); + if (written < 0) + return JSONFailure; + return JSONSuccess; +} + +x_JSON_Status x_json_serialize_to_file_pretty(const x_JSON_Value *value, const char *filename) { + x_JSON_Status return_code = JSONSuccess; + FILE *fp = NULL; + char *serialized_string = x_json_serialize_to_string_pretty(value); + if (serialized_string == NULL) { + return JSONFailure; + } + fp = fopen (filename, "w"); + if (fp == NULL) { + x_json_free_serialized_string(serialized_string); + return JSONFailure; + } + if (fputs(serialized_string, fp) == EOF) { + return_code = JSONFailure; + } + if (fclose(fp) == EOF) { + return_code = JSONFailure; + } + x_json_free_serialized_string(serialized_string); + return return_code; +} + +char * x_json_serialize_to_string_pretty(const x_JSON_Value *value) { + x_JSON_Status serialization_result = JSONFailure; + size_t buf_size_bytes = x_json_serialization_size_pretty(value); + char *buf = NULL; + if (buf_size_bytes == 0) { + return NULL; + } + buf = (char*)parson_malloc(buf_size_bytes); + if (buf == NULL) + return NULL; + serialization_result = x_json_serialize_to_buffer_pretty(value, buf, buf_size_bytes); + if (serialization_result == JSONFailure) { + x_json_free_serialized_string(buf); + return NULL; + } + return buf; +} + +void x_json_free_serialized_string(char *string) { + parson_free(string); +} + +x_JSON_Status x_json_array_remove(x_JSON_Array *array, size_t ix) { + x_JSON_Value *temp_value = NULL; + size_t last_element_ix = 0; + if (array == NULL || ix >= x_json_array_get_count(array)) { + return JSONFailure; + } + last_element_ix = x_json_array_get_count(array) - 1; + x_json_value_free(x_json_array_get_value(array, ix)); + if (ix != last_element_ix) { /* Replace value with one from the end of array */ + temp_value = x_json_array_get_value(array, last_element_ix); + if (temp_value == NULL) { + return JSONFailure; + } + array->items[ix] = temp_value; + } + array->count -= 1; + return JSONSuccess; +} + +x_JSON_Status x_json_array_replace_value(x_JSON_Array *array, size_t ix, x_JSON_Value *value) { + if (array == NULL || value == NULL || ix >= x_json_array_get_count(array)) { + return JSONFailure; + } + x_json_value_free(x_json_array_get_value(array, ix)); + array->items[ix] = value; + return JSONSuccess; +} + +x_JSON_Status x_json_array_replace_string(x_JSON_Array *array, size_t i, const char* string) { + x_JSON_Value *value = x_json_value_init_string(string); + if (value == NULL) + return JSONFailure; + if (x_json_array_replace_value(array, i, value) == JSONFailure) { + x_json_value_free(value); + return JSONFailure; + } + return JSONSuccess; +} + +x_JSON_Status x_json_array_replace_number(x_JSON_Array *array, size_t i, double number) { + x_JSON_Value *value = x_json_value_init_number(number); + if (value == NULL) + return JSONFailure; + if (x_json_array_replace_value(array, i, value) == JSONFailure) { + x_json_value_free(value); + return JSONFailure; + } + return JSONSuccess; +} + +x_JSON_Status x_json_array_replace_boolean(x_JSON_Array *array, size_t i, int boolean) { + x_JSON_Value *value = x_json_value_init_boolean(boolean); + if (value == NULL) + return JSONFailure; + if (x_json_array_replace_value(array, i, value) == JSONFailure) { + x_json_value_free(value); + return JSONFailure; + } + return JSONSuccess; +} + +x_JSON_Status x_json_array_replace_null(x_JSON_Array *array, size_t i) { + x_JSON_Value *value = x_json_value_init_null(); + if (value == NULL) + return JSONFailure; + if (x_json_array_replace_value(array, i, value) == JSONFailure) { + x_json_value_free(value); + return JSONFailure; + } + return JSONSuccess; +} + +x_JSON_Status x_json_array_clear(x_JSON_Array *array) { + size_t i = 0; + if (array == NULL) + return JSONFailure; + for (i = 0; i < x_json_array_get_count(array); i++) { + x_json_value_free(x_json_array_get_value(array, i)); + } + array->count = 0; + return JSONSuccess; +} + +x_JSON_Status x_json_array_append_value(x_JSON_Array *array, x_JSON_Value *value) { + if (array == NULL || value == NULL) + return JSONFailure; + return x_json_array_add(array, value); +} + +x_JSON_Status x_json_array_append_string(x_JSON_Array *array, const char *string) { + x_JSON_Value *value = x_json_value_init_string(string); + if (value == NULL) + return JSONFailure; + if (x_json_array_append_value(array, value) == JSONFailure) { + x_json_value_free(value); + return JSONFailure; + } + return JSONSuccess; +} + +x_JSON_Status x_json_array_append_number(x_JSON_Array *array, double number) { + x_JSON_Value *value = x_json_value_init_number(number); + if (value == NULL) + return JSONFailure; + if (x_json_array_append_value(array, value) == JSONFailure) { + x_json_value_free(value); + return JSONFailure; + } + return JSONSuccess; +} + +x_JSON_Status x_json_array_append_boolean(x_JSON_Array *array, int boolean) { + x_JSON_Value *value = x_json_value_init_boolean(boolean); + if (value == NULL) + return JSONFailure; + if (x_json_array_append_value(array, value) == JSONFailure) { + x_json_value_free(value); + return JSONFailure; + } + return JSONSuccess; +} + +x_JSON_Status x_json_array_append_null(x_JSON_Array *array) { + x_JSON_Value *value = x_json_value_init_null(); + if (value == NULL) + return JSONFailure; + if (x_json_array_append_value(array, value) == JSONFailure) { + x_json_value_free(value); + return JSONFailure; + } + return JSONSuccess; +} + +x_JSON_Status x_json_object_set_value(x_JSON_Object *object, const char *name, x_JSON_Value *value) { + size_t i = 0; + x_JSON_Value *old_value; + if (object == NULL || name == NULL || value == NULL) + return JSONFailure; + old_value = x_json_object_get_value(object, name); + if (old_value != NULL) { /* free and overwrite old value */ + x_json_value_free(old_value); + for (i = 0; i < x_json_object_get_count(object); i++) { + if (strcmp(object->names[i], name) == 0) { + object->values[i] = value; + return JSONSuccess; + } + } + } + /* add new key value pair */ + return x_json_object_add(object, name, value); +} + +x_JSON_Status x_json_object_set_string(x_JSON_Object *object, const char *name, const char *string) { + return x_json_object_set_value(object, name, x_json_value_init_string(string)); +} + +x_JSON_Status x_json_object_set_number(x_JSON_Object *object, const char *name, double number) { + return x_json_object_set_value(object, name, x_json_value_init_number(number)); +} + +x_JSON_Status x_json_object_set_boolean(x_JSON_Object *object, const char *name, int boolean) { + return x_json_object_set_value(object, name, x_json_value_init_boolean(boolean)); +} + +x_JSON_Status x_json_object_set_null(x_JSON_Object *object, const char *name) { + return x_json_object_set_value(object, name, x_json_value_init_null()); +} + +x_JSON_Status x_json_object_dotset_value(x_JSON_Object *object, const char *name, x_JSON_Value *value) { + const char *dot_pos = NULL; + char *current_name = NULL; + x_JSON_Object *temp_obj = NULL; + x_JSON_Value *new_value = NULL; + if (value == NULL || name == NULL || value == NULL) + return JSONFailure; + dot_pos = strchr(name, '.'); + if (dot_pos == NULL) { + return x_json_object_set_value(object, name, value); + } else { + current_name = parson_strndup(name, dot_pos - name); + temp_obj = x_json_object_get_object(object, current_name); + if (temp_obj == NULL) { + new_value = x_json_value_init_object(); + if (new_value == NULL) { + parson_free(current_name); + return JSONFailure; + } + if (x_json_object_add(object, current_name, new_value) == JSONFailure) { + x_json_value_free(new_value); + parson_free(current_name); + return JSONFailure; + } + temp_obj = x_json_object_get_object(object, current_name); + } + parson_free(current_name); + return x_json_object_dotset_value(temp_obj, dot_pos + 1, value); + } +} + +x_JSON_Status x_json_object_dotset_string(x_JSON_Object *object, const char *name, const char *string) { + x_JSON_Value *value = x_json_value_init_string(string); + if (value == NULL) + return JSONFailure; + if (x_json_object_dotset_value(object, name, value) == JSONFailure) { + x_json_value_free(value); + return JSONFailure; + } + return JSONSuccess; +} + +x_JSON_Status x_json_object_dotset_number(x_JSON_Object *object, const char *name, double number) { + x_JSON_Value *value = x_json_value_init_number(number); + if (value == NULL) + return JSONFailure; + if (x_json_object_dotset_value(object, name, value) == JSONFailure) { + x_json_value_free(value); + return JSONFailure; + } + return JSONSuccess; +} + +x_JSON_Status x_json_object_dotset_boolean(x_JSON_Object *object, const char *name, int boolean) { + x_JSON_Value *value = x_json_value_init_boolean(boolean); + if (value == NULL) + return JSONFailure; + if (x_json_object_dotset_value(object, name, value) == JSONFailure) { + x_json_value_free(value); + return JSONFailure; + } + return JSONSuccess; +} + +x_JSON_Status x_json_object_dotset_null(x_JSON_Object *object, const char *name) { + x_JSON_Value *value = x_json_value_init_null(); + if (value == NULL) + return JSONFailure; + if (x_json_object_dotset_value(object, name, value) == JSONFailure) { + x_json_value_free(value); + return JSONFailure; + } + return JSONSuccess; +} + +x_JSON_Status x_json_object_remove(x_JSON_Object *object, const char *name) { + size_t i = 0, last_item_index = 0; + if (object == NULL || x_json_object_get_value(object, name) == NULL) + return JSONFailure; + last_item_index = x_json_object_get_count(object) - 1; + for (i = 0; i < x_json_object_get_count(object); i++) { + if (strcmp(object->names[i], name) == 0) { + parson_free(object->names[i]); + x_json_value_free(object->values[i]); + if (i != last_item_index) { /* Replace key value pair with one from the end */ + object->names[i] = object->names[last_item_index]; + object->values[i] = object->values[last_item_index]; + } + object->count -= 1; + return JSONSuccess; + } + } + return JSONFailure; /* No execution path should end here */ +} + +x_JSON_Status x_json_object_dotremove(x_JSON_Object *object, const char *name) { + const char *dot_pos = strchr(name, '.'); + char *current_name = NULL; + x_JSON_Object *temp_obj = NULL; + if (dot_pos == NULL) { + return x_json_object_remove(object, name); + } else { + current_name = parson_strndup(name, dot_pos - name); + temp_obj = x_json_object_get_object(object, current_name); + if (temp_obj == NULL) { + parson_free(current_name); + return JSONFailure; + } + parson_free(current_name); + return x_json_object_dotremove(temp_obj, dot_pos + 1); + } +} + +x_JSON_Status x_json_object_clear(x_JSON_Object *object) { + size_t i = 0; + if (object == NULL) { + return JSONFailure; + } + for (i = 0; i < x_json_object_get_count(object); i++) { + parson_free(object->names[i]); + x_json_value_free(object->values[i]); + } + object->count = 0; + return JSONSuccess; +} + +x_JSON_Status x_json_validate(const x_JSON_Value *schema, const x_JSON_Value *value) { + x_JSON_Value *temp_schema_value = NULL, *temp_value = NULL; + x_JSON_Array *schema_array = NULL, *value_array = NULL; + x_JSON_Object *schema_object = NULL, *value_object = NULL; + x_JSON_Value_Type schema_type = JSONError, value_type = JSONError; + const char *key = NULL; + size_t i = 0, count = 0; + if (schema == NULL || value == NULL) + return JSONFailure; + schema_type = x_json_value_get_type(schema); + value_type = x_json_value_get_type(value); + if (schema_type != value_type && schema_type != JSONNull) /* null represents all values */ + return JSONFailure; + switch (schema_type) { + case JSONArray: + schema_array = x_json_value_get_array(schema); + value_array = x_json_value_get_array(value); + count = x_json_array_get_count(schema_array); + if (count == 0) + return JSONSuccess; /* Empty array allows all types */ + /* Get first value from array, rest is ignored */ + temp_schema_value = x_json_array_get_value(schema_array, 0); + for (i = 0; i < x_json_array_get_count(value_array); i++) { + temp_value = x_json_array_get_value(value_array, i); + if (x_json_validate(temp_schema_value, temp_value) == 0) { + return JSONFailure; + } + } + return JSONSuccess; + case JSONObject: + schema_object = x_json_value_get_object(schema); + value_object = x_json_value_get_object(value); + count = x_json_object_get_count(schema_object); + if (count == 0) + return JSONSuccess; /* Empty object allows all objects */ + else if (x_json_object_get_count(value_object) < count) + return JSONFailure; /* Tested object mustn't have less name-value pairs than schema */ + for (i = 0; i < count; i++) { + key = x_json_object_get_name(schema_object, i); + temp_schema_value = x_json_object_get_value(schema_object, key); + temp_value = x_json_object_get_value(value_object, key); + if (temp_value == NULL) + return JSONFailure; + if (x_json_validate(temp_schema_value, temp_value) == JSONFailure) + return JSONFailure; + } + return JSONSuccess; + case JSONString: case JSONNumber: case JSONBoolean: case JSONNull: + return JSONSuccess; /* equality already tested before switch */ + case JSONError: default: + return JSONFailure; + } +} + +x_JSON_Status x_json_value_equals(const x_JSON_Value *a, const x_JSON_Value *b) { + x_JSON_Object *a_object = NULL, *b_object = NULL; + x_JSON_Array *a_array = NULL, *b_array = NULL; + const char *a_string = NULL, *b_string = NULL; + const char *key = NULL; + size_t a_count = 0, b_count = 0, i = 0; + x_JSON_Value_Type a_type, b_type; + a_type = x_json_value_get_type(a); + b_type = x_json_value_get_type(b); + if (a_type != b_type) { + return 0; + } + switch (a_type) { + case JSONArray: + a_array = x_json_value_get_array(a); + b_array = x_json_value_get_array(b); + a_count = x_json_array_get_count(a_array); + b_count = x_json_array_get_count(b_array); + if (a_count != b_count) { + return 0; + } + for (i = 0; i < a_count; i++) { + if (!x_json_value_equals(x_json_array_get_value(a_array, i), + x_json_array_get_value(b_array, i))) { + return 0; + } + } + return 1; + case JSONObject: + a_object = x_json_value_get_object(a); + b_object = x_json_value_get_object(b); + a_count = x_json_object_get_count(a_object); + b_count = x_json_object_get_count(b_object); + if (a_count != b_count) { + return 0; + } + for (i = 0; i < a_count; i++) { + key = x_json_object_get_name(a_object, i); + if (!x_json_value_equals(x_json_object_get_value(a_object, key), + x_json_object_get_value(b_object, key))) { + return 0; + } + } + return 1; + case JSONString: + a_string = x_json_value_get_string(a); + b_string = x_json_value_get_string(b); + return strcmp(a_string, b_string) == 0; + case JSONBoolean: + return x_json_value_get_boolean(a) == x_json_value_get_boolean(b); + case JSONNumber: + return fabs(x_json_value_get_number(a) - x_json_value_get_number(b)) < 0.000001; /* EPSILON */ + case JSONError: + return 1; + case JSONNull: + return 1; + default: + return 1; + } +} + +x_JSON_Value_Type x_json_type(const x_JSON_Value *value) { + return x_json_value_get_type(value); +} + +x_JSON_Object * x_json_object (const x_JSON_Value *value) { + return x_json_value_get_object(value); +} + +x_JSON_Array * x_json_array (const x_JSON_Value *value) { + return x_json_value_get_array(value); +} + +const char * x_json_string (const x_JSON_Value *value) { + return x_json_value_get_string(value); +} + +double x_json_number (const x_JSON_Value *value) { + return x_json_value_get_number(value); +} + +int x_json_boolean(const x_JSON_Value *value) { + return x_json_value_get_boolean(value); +} + +void x_json_set_allocation_functions(x_JSON_Malloc_Function malloc_fun, x_JSON_Free_Function free_fun) { + parson_malloc = malloc_fun; + parson_free = free_fun; +} diff --git a/c++/src/connect/parson.h b/c++/src/connect/parson.h new file mode 100644 index 00000000..e905f415 --- /dev/null +++ b/c++/src/connect/parson.h @@ -0,0 +1,223 @@ +/* + Parson ( http://kgabis.github.com/parson/ ) + Copyright (c) 2012 - 2016 Krzysztof Gabis + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#ifndef parson_parson_h +#define parson_parson_h + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include /* size_t */ + +/* Types and enums */ +typedef struct x_json_object_t x_JSON_Object; +typedef struct x_json_array_t x_JSON_Array; +typedef struct x_json_value_t x_JSON_Value; + +enum x_json_value_type { + JSONError = -1, + JSONNull = 1, + JSONString = 2, + JSONNumber = 3, + JSONObject = 4, + JSONArray = 5, + JSONBoolean = 6 +}; +typedef int x_JSON_Value_Type; + +enum x_json_result_t { + JSONSuccess = 0, + JSONFailure = -1 +}; +typedef int x_JSON_Status; + +typedef void * (*x_JSON_Malloc_Function)(size_t); +typedef void (*x_JSON_Free_Function)(void *); + +/* Call only once, before calling any other function from parson API. If not called, malloc and free + from stdlib will be used for all allocations */ +void x_json_set_allocation_functions(x_JSON_Malloc_Function malloc_fun, x_JSON_Free_Function free_fun); + +/* Parses first JSON value in a file, returns NULL in case of error */ +x_JSON_Value * x_json_parse_file(const char *filename); + +/* Parses first JSON value in a file and ignores comments (/ * * / and //), + returns NULL in case of error */ +x_JSON_Value * x_json_parse_file_with_comments(const char *filename); + +/* Parses first JSON value in a string, returns NULL in case of error */ +x_JSON_Value * x_json_parse_string(const char *string); + +/* Parses first JSON value in a string and ignores comments (/ * * / and //), + returns NULL in case of error */ +x_JSON_Value * x_json_parse_string_with_comments(const char *string); + +/* Serialization */ +size_t x_json_serialization_size(const x_JSON_Value *value); /* returns 0 on fail */ +x_JSON_Status x_json_serialize_to_buffer(const x_JSON_Value *value, char *buf, size_t buf_size_in_bytes); +x_JSON_Status x_json_serialize_to_file(const x_JSON_Value *value, const char *filename); +char * x_json_serialize_to_string(const x_JSON_Value *value); + +/* Pretty serialization */ +size_t x_json_serialization_size_pretty(const x_JSON_Value *value); /* returns 0 on fail */ +x_JSON_Status x_json_serialize_to_buffer_pretty(const x_JSON_Value *value, char *buf, size_t buf_size_in_bytes); +x_JSON_Status x_json_serialize_to_file_pretty(const x_JSON_Value *value, const char *filename); +char * x_json_serialize_to_string_pretty(const x_JSON_Value *value); + +void x_json_free_serialized_string(char *string); /* frees string from json_serialize_to_string and json_serialize_to_string_pretty */ + +/* Comparing */ +int x_json_value_equals(const x_JSON_Value *a, const x_JSON_Value *b); + +/* Validation + This is *NOT* JSON Schema. It validates json by checking if object have identically + named fields with matching types. + For example schema {"name":"", "age":0} will validate + {"name":"Joe", "age":25} and {"name":"Joe", "age":25, "gender":"m"}, + but not {"name":"Joe"} or {"name":"Joe", "age":"Cucumber"}. + In case of arrays, only first value in schema is checked against all values in tested array. + Empty objects ({}) validate all objects, empty arrays ([]) validate all arrays, + null validates values of every type. + */ +x_JSON_Status json_validate(const x_JSON_Value *schema, const x_JSON_Value *value); + +/* + * JSON Object + */ +x_JSON_Value * x_json_object_get_value (const x_JSON_Object *object, const char *name); +const char * x_json_object_get_string (const x_JSON_Object *object, const char *name); +x_JSON_Object * x_json_object_get_object (const x_JSON_Object *object, const char *name); +x_JSON_Array * x_json_object_get_array (const x_JSON_Object *object, const char *name); +double x_json_object_get_number (const x_JSON_Object *object, const char *name); /* returns 0 on fail */ +int x_json_object_get_boolean(const x_JSON_Object *object, const char *name); /* returns -1 on fail */ + +/* dotget functions enable addressing values with dot notation in nested objects, + just like in structs or c++/java/c# objects (e.g. objectA.objectB.value). + Because valid names in JSON can contain dots, some values may be inaccessible + this way. */ +x_JSON_Value * x_json_object_dotget_value (const x_JSON_Object *object, const char *name); +const char * x_json_object_dotget_string (const x_JSON_Object *object, const char *name); +x_JSON_Object * x_json_object_dotget_object (const x_JSON_Object *object, const char *name); +x_JSON_Array * x_json_object_dotget_array (const x_JSON_Object *object, const char *name); +double x_json_object_dotget_number (const x_JSON_Object *object, const char *name); /* returns 0 on fail */ +int x_json_object_dotget_boolean(const x_JSON_Object *object, const char *name); /* returns -1 on fail */ + +/* Functions to get available names */ +size_t x_json_object_get_count (const x_JSON_Object *object); +const char * x_json_object_get_name (const x_JSON_Object *object, size_t index); +x_JSON_Value * x_json_object_get_value_at(const x_JSON_Object *object, size_t index); + +/* Creates new name-value pair or frees and replaces old value with a new one. + * json_object_set_value does not copy passed value so it shouldn't be freed afterwards. */ +x_JSON_Status x_json_object_set_value(x_JSON_Object *object, const char *name, x_JSON_Value *value); +x_JSON_Status x_json_object_set_string(x_JSON_Object *object, const char *name, const char *string); +x_JSON_Status x_json_object_set_number(x_JSON_Object *object, const char *name, double number); +x_JSON_Status x_json_object_set_boolean(x_JSON_Object *object, const char *name, int boolean); +x_JSON_Status x_json_object_set_null(x_JSON_Object *object, const char *name); + +/* Works like dotget functions, but creates whole hierarchy if necessary. + * json_object_dotset_value does not copy passed value so it shouldn't be freed afterwards. */ +x_JSON_Status x_json_object_dotset_value(x_JSON_Object *object, const char *name, x_JSON_Value *value); +x_JSON_Status x_json_object_dotset_string(x_JSON_Object *object, const char *name, const char *string); +x_JSON_Status x_json_object_dotset_number(x_JSON_Object *object, const char *name, double number); +x_JSON_Status x_json_object_dotset_boolean(x_JSON_Object *object, const char *name, int boolean); +x_JSON_Status x_json_object_dotset_null(x_JSON_Object *object, const char *name); + +/* Frees and removes name-value pair */ +x_JSON_Status x_json_object_remove(x_JSON_Object *object, const char *name); + +/* Works like dotget function, but removes name-value pair only on exact match. */ +x_JSON_Status x_json_object_dotremove(x_JSON_Object *object, const char *key); + +/* Removes all name-value pairs in object */ +x_JSON_Status x_json_object_clear(x_JSON_Object *object); + +/* + *JSON Array + */ +x_JSON_Value * x_json_array_get_value (const x_JSON_Array *array, size_t index); +const char * x_json_array_get_string (const x_JSON_Array *array, size_t index); +x_JSON_Object * x_json_array_get_object (const x_JSON_Array *array, size_t index); +x_JSON_Array * x_json_array_get_array (const x_JSON_Array *array, size_t index); +double x_json_array_get_number (const x_JSON_Array *array, size_t index); /* returns 0 on fail */ +int x_json_array_get_boolean(const x_JSON_Array *array, size_t index); /* returns -1 on fail */ +size_t x_json_array_get_count (const x_JSON_Array *array); + +/* Frees and removes value at given index, does nothing and returns JSONFailure if index doesn't exist. + * Order of values in array may change during execution. */ +x_JSON_Status json_array_remove(x_JSON_Array *array, size_t i); + +/* Frees and removes from array value at given index and replaces it with given one. + * Does nothing and returns JSONFailure if index doesn't exist. + * json_array_replace_value does not copy passed value so it shouldn't be freed afterwards. */ +x_JSON_Status x_json_array_replace_value(x_JSON_Array *array, size_t i, x_JSON_Value *value); +x_JSON_Status x_json_array_replace_string(x_JSON_Array *array, size_t i, const char* string); +x_JSON_Status x_json_array_replace_number(x_JSON_Array *array, size_t i, double number); +x_JSON_Status x_json_array_replace_boolean(x_JSON_Array *array, size_t i, int boolean); +x_JSON_Status x_json_array_replace_null(x_JSON_Array *array, size_t i); + +/* Frees and removes all values from array */ +x_JSON_Status x_json_array_clear(x_JSON_Array *array); + +/* Appends new value at the end of array. + * json_array_append_value does not copy passed value so it shouldn't be freed afterwards. */ +x_JSON_Status x_json_array_append_value(x_JSON_Array *array, x_JSON_Value *value); +x_JSON_Status x_json_array_append_string(x_JSON_Array *array, const char *string); +x_JSON_Status x_json_array_append_number(x_JSON_Array *array, double number); +x_JSON_Status x_json_array_append_boolean(x_JSON_Array *array, int boolean); +x_JSON_Status x_json_array_append_null(x_JSON_Array *array); + +/* + *JSON Value + */ +x_JSON_Value * x_json_value_init_object (void); +x_JSON_Value * x_json_value_init_array (void); +x_JSON_Value * x_json_value_init_string (const char *string); /* copies passed string */ +x_JSON_Value * x_json_value_init_number (double number); +x_JSON_Value * x_json_value_init_boolean(int boolean); +x_JSON_Value * x_json_value_init_null (void); +x_JSON_Value * x_json_value_deep_copy (const x_JSON_Value *value); +void x_json_value_free (x_JSON_Value *value); + +x_JSON_Value_Type x_json_value_get_type (const x_JSON_Value *value); +x_JSON_Object * x_json_value_get_object (const x_JSON_Value *value); +x_JSON_Array * x_json_value_get_array (const x_JSON_Value *value); +const char * x_json_value_get_string (const x_JSON_Value *value); +double x_json_value_get_number (const x_JSON_Value *value); +int x_json_value_get_boolean(const x_JSON_Value *value); + +/* Same as above, but shorter */ +x_JSON_Value_Type x_json_type (const x_JSON_Value *value); +x_JSON_Object * x_json_object (const x_JSON_Value *value); +x_JSON_Array * x_json_array (const x_JSON_Value *value); +const char * x_json_string (const x_JSON_Value *value); +double x_json_number (const x_JSON_Value *value); +int x_json_boolean(const x_JSON_Value *value); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c++/src/connect/server.cpp b/c++/src/connect/server.cpp index 7fb6ff6e..a28f0c12 100644 --- a/c++/src/connect/server.cpp +++ b/c++/src/connect/server.cpp @@ -1,4 +1,4 @@ -/* $Id: server.cpp 467185 2015-05-11 14:50:34Z sadyrovr $ +/* $Id: server.cpp 506707 2016-07-11 15:26:50Z satskyse $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -54,11 +54,12 @@ static CSafeStatic s_ServerCatchExceptions; // IServer_MessageHandler implementation void IServer_MessageHandler::OnRead(void) { - CSocket &socket = GetSocket(); - CServer_Connection* conn = static_cast(&socket); - char read_buf[4096]; - size_t n_read; - EIO_Status status = socket.Read(read_buf, sizeof(read_buf), &n_read); + CSocket & socket = GetSocket(); + CServer_Connection * conn = static_cast(&socket); + char read_buf[4096]; + size_t n_read; + EIO_Status status = socket.Read(read_buf, sizeof(read_buf), + &n_read); switch (status) { case eIO_Success: break; @@ -69,19 +70,27 @@ void IServer_MessageHandler::OnRead(void) this->OnClose(IServer_ConnectionHandler::eClientClose); return; default: - // TODO: ??? OnError + string err_message("Error reading from the client socket ("); + + err_message += socket.GetPeerAddress() + "): " + + string(IO_StatusStr(status)) + "(" + + NStr::NumericToString(static_cast(status)) + ")"; + + this->OnError(err_message); return; } - int message_tail; - char *buf_ptr = read_buf; + + int message_tail; + char * buf_ptr = read_buf; for ( ;n_read > 0 && conn->type == eActiveSocket; ) { message_tail = this->CheckMessage(&m_Buffer, buf_ptr, n_read); + // TODO: what should we do if message_tail > n_read? if (message_tail < 0) { return; - } else { - this->OnMessage(m_Buffer); } + + this->OnMessage(m_Buffer); int consumed = int(n_read) - message_tail; buf_ptr += consumed; n_read -= consumed; @@ -117,12 +126,12 @@ CBlockingQueue_ForServer::Put(const TRequest& data) { CMutexGuard guard(m_Mutex); if (m_Queue.empty()) { -#ifdef NCBI_HAVE_CONDITIONAL_VARIABLE + #ifdef NCBI_HAVE_CONDITIONAL_VARIABLE m_GetCond.SignalAll(); -#else + #else m_GetSem.TryWait(); // is this still needed? m_GetSem.Post(); -#endif + #endif } TItemHandle handle(new CQueueItem(data)); m_Queue.push_back(handle); @@ -135,22 +144,23 @@ CBlockingQueue_ForServer::GetHandle(void) CMutexGuard guard(m_Mutex); while (m_Queue.empty()) { -#ifdef NCBI_HAVE_CONDITIONAL_VARIABLE + #ifdef NCBI_HAVE_CONDITIONAL_VARIABLE m_GetCond.WaitForSignal(m_Mutex); -#else + #else m_GetSem.TryWait(); m_GetSem.Post(); -#endif + #endif } TItemHandle handle(m_Queue.front()); m_Queue.pop_front(); -#ifndef NCBI_HAVE_CONDITIONAL_VARIABLE + + #ifndef NCBI_HAVE_CONDITIONAL_VARIABLE if (!m_Queue.empty()) { m_GetSem.TryWait(); m_GetSem.Post(); } -#endif + #endif guard.Release(); // avoid possible deadlocks from x_SetStatus handle->x_SetStatus(CQueueItemBase::eActive); @@ -195,7 +205,7 @@ CThreadInPool_ForServer::x_HandleOneRequest(bool catch_all) if (catch_all) { try { ProcessRequest(handle); - } catch (std::exception& e) { + } catch (const std::exception & e) { handle->MarkAsForciblyCaught(); NCBI_REPORT_EXCEPTION_X(9, "Exception from thread in pool: ", e); // throw; @@ -250,18 +260,6 @@ CPoolOfThreads_ForServer::CPoolOfThreads_ForServer(unsigned int max_threads, m_KilledAll(false) { m_ThreadCount.Set(0); - m_PutQueueNum.Set(0); - m_GetQueueNum.Set(0); - - // The original developer used malloc(...) here to allocate the required - // number of bytes for an array. It is unknown why that decision was made. - // Later on it was decided to replace malloc(...) with new to have a pure - // C++ style in the code. - m_Queues = (TQueue**) new char[m_MaxThreads * sizeof(m_Queues[0])]; - - for (TACValue i = 0; i < m_MaxThreads; ++i) { - m_Queues[i] = new TQueue(); - } } CPoolOfThreads_ForServer::~CPoolOfThreads_ForServer(void) @@ -272,17 +270,10 @@ CPoolOfThreads_ForServer::~CPoolOfThreads_ForServer(void) CAtomicCounter::TValue n = m_ThreadCount.Get(); if (n) { - ERR_POST_X(10, Warning << "CPoolOfThreads_ForServer::~CPoolOfThreads_ForServer: " - << n << " thread(s) still active"); - } else { - // It seems to be safe to destroy the allocated array if all the - // threads were stopped. - for (TACValue i = 0; i < m_MaxThreads; ++i) { - delete m_Queues[i]; - } - delete [] (char *)(m_Queues); + ERR_POST_X(10, Warning + << "CPoolOfThreads_ForServer::~CPoolOfThreads_ForServer: " + << n << " thread(s) still active"); } - // Just in case let's deliberately not destroy all queues. } void @@ -299,15 +290,13 @@ CPoolOfThreads_ForServer::Spawn(unsigned int num_threads) void CPoolOfThreads_ForServer::AcceptRequest(const TRequest& req) { - Uint4 q_num = Uint4(m_PutQueueNum.Add(1)) % m_MaxThreads; - m_Queues[q_num]->Put(req); + m_Queue.Put(req); } CPoolOfThreads_ForServer::TItemHandle CPoolOfThreads_ForServer::GetHandle(void) { - Uint4 q_num = Uint4(m_GetQueueNum.Add(1)) % m_MaxThreads; - return m_Queues[q_num]->GetHandle(); + return m_Queue.GetHandle(); } @@ -638,6 +627,12 @@ void CServer::AddListener(IServer_ConnectionFactory* factory, } +bool CServer::RemoveListener(unsigned short port) +{ + return m_ConnectionPool->RemoveListener(port); +} + + void CServer::SetParameters(const SServer_Parameters& new_params) { if (new_params.init_threads <= 0 || @@ -685,12 +680,10 @@ void CServer::x_DoRun(void) vector polls; size_t count; typedef vector TConnsList; - typedef vector > TReqsList; TConnsList timer_requests; TConnsList revived_conns; TConnsList to_close_conns; TConnsList to_delete_conns; - TReqsList to_add_reqs; STimeout timer_timeout; const STimeout* timeout; @@ -706,24 +699,22 @@ void CServer::x_DoRun(void) CRef req(conn_base->CreateRequest( evt, *m_ConnectionPool, m_Parameters->idle_timeout)); - to_add_reqs.push_back(req); + m_ThreadPool->AcceptRequest(req); } ITERATE(TConnsList, it, to_close_conns) { IServer_ConnectionBase* conn_base = *it; CRef req(conn_base->CreateRequest( eServIO_Inactivity, *m_ConnectionPool, m_Parameters->idle_timeout)); - to_add_reqs.push_back(req); + m_ThreadPool->AcceptRequest(req); } ITERATE(TConnsList, it, to_delete_conns) { IServer_ConnectionBase* conn_base = *it; CRef req(conn_base->CreateRequest( eServIO_Delete, *m_ConnectionPool, m_Parameters->idle_timeout)); - to_add_reqs.push_back(req); + m_ThreadPool->AcceptRequest(req); } - x_AddRequests(to_add_reqs); - to_add_reqs.clear(); timeout = m_Parameters->accept_timeout; @@ -767,17 +758,22 @@ void CServer::x_DoRun(void) IServer_ConnectionBase* conn_base = *it; CRef req(conn_base->CreateRequest( (EServIO_Event)-1, *m_ConnectionPool, timeout)); - to_add_reqs.push_back(req); + m_ThreadPool->AcceptRequest(req); } - x_AddRequests(to_add_reqs); - to_add_reqs.clear(); } continue; } m_ConnectionPool->SetAllActive(polls); ITERATE (vector, it, polls) { - if (!it->m_REvent) continue; + if (!it->m_REvent) + continue; + CTrigger * trigger = dynamic_cast(it->m_Pollable); + if (trigger) { + trigger->Reset(); + continue; + } + IServer_ConnectionBase* conn_base = dynamic_cast(it->m_Pollable); _ASSERT(conn_base); @@ -785,11 +781,8 @@ void CServer::x_DoRun(void) IOEventToServIOEvent(it->m_REvent), *m_ConnectionPool, m_Parameters->idle_timeout)); - if (req) - to_add_reqs.push_back(req); + m_ThreadPool->AcceptRequest(req); } - x_AddRequests(to_add_reqs); - to_add_reqs.clear(); } } @@ -802,7 +795,7 @@ void CServer::Run(void) if (s_ServerCatchExceptions->Get()) { try { x_DoRun(); - } catch (CException& ex) { + } catch (const CException & ex) { ERR_POST(ex); // Avoid collateral damage from destroying the thread pool // while worker threads are active (or, worse, initializing). @@ -846,23 +839,6 @@ void CServer::DeferConnectionProcessing(CSocket* sock) } -void CServer::Init() -{ -} - - -void CServer::Exit() -{ -} - - -void CServer::x_AddRequests(const vector >& reqs) -{ - ITERATE(vector >, it, reqs) { - m_ThreadPool->AcceptRequest(*it); - } -} - void CServer::AddConnectionToPool(CServer_Connection* conn) { if (!m_ConnectionPool->Add(conn, eInactiveSocket)) { @@ -881,6 +857,11 @@ void CServer::WakeUpPollCycle(void) m_ConnectionPool->PingControlConnection(); } +vector CServer::GetListenerPorts(void) +{ + return m_ConnectionPool->GetListenerPorts(); +} + ///////////////////////////////////////////////////////////////////////////// // SServer_Parameters implementation diff --git a/c++/src/connect/services/Makefile.xconnserv.lib b/c++/src/connect/services/Makefile.xconnserv.lib index b53185bf..52ff3b47 100644 --- a/c++/src/connect/services/Makefile.xconnserv.lib +++ b/c++/src/connect/services/Makefile.xconnserv.lib @@ -1,4 +1,4 @@ -# $Id: Makefile.xconnserv.lib 485672 2015-11-24 20:44:56Z sadyrovr $ +# $Id: Makefile.xconnserv.lib 520437 2016-11-28 18:35:09Z ivanov $ SRC = grid_worker ns_client_factory grid_worker_app \ grid_client grid_client_app \ @@ -11,7 +11,7 @@ SRC = grid_worker ns_client_factory grid_worker_app \ netschedule_api_reader netschedule_api_admin netschedule_api_getjob \ netschedule_key netschedule_api_expt \ netcache_key netcache_rw netcache_params netcache_api \ - netcache_api_admin \ + netcache_api_admin netcache_search \ netservice_protocol_parser util clparser \ json_over_uttp netstorage netstorage_rpc \ netstorageobjectloc netstorageobjectinfo netstorage_direct_nc \ diff --git a/c++/src/connect/services/grid_client.cpp b/c++/src/connect/services/grid_client.cpp index 4c9f4b37..34bda8c7 100644 --- a/c++/src/connect/services/grid_client.cpp +++ b/c++/src/connect/services/grid_client.cpp @@ -1,4 +1,4 @@ -/* $Id: grid_client.cpp 492603 2016-02-18 19:27:56Z ivanov $ +/* $Id: grid_client.cpp 492431 2016-02-17 17:05:04Z sadyrovr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/connect/services/grid_control_thread.cpp b/c++/src/connect/services/grid_control_thread.cpp index b88b68c4..3063da16 100644 --- a/c++/src/connect/services/grid_control_thread.cpp +++ b/c++/src/connect/services/grid_control_thread.cpp @@ -1,4 +1,4 @@ -/* $Id: grid_control_thread.cpp 491697 2016-02-08 18:44:39Z ivanov $ +/* $Id: grid_control_thread.cpp 491506 2016-02-05 16:08:02Z sadyrovr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/connect/services/grid_worker.cpp b/c++/src/connect/services/grid_worker.cpp index 647107e7..d0553942 100644 --- a/c++/src/connect/services/grid_worker.cpp +++ b/c++/src/connect/services/grid_worker.cpp @@ -1,4 +1,4 @@ -/* $Id: grid_worker.cpp 499332 2016-04-25 17:42:11Z ivanov $ +/* $Id: grid_worker.cpp 509503 2016-08-05 19:09:23Z fukanchi $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -420,31 +420,31 @@ void SGridWorkerNodeImpl::x_WNCoreInit() } } m_NSTimeout = reg.GetInt(kServerSec, - "job_wait_timeout", DEFAULT_NS_TIMEOUT, 0, IRegistry::eReturn); + "job_wait_timeout", DEFAULT_NS_TIMEOUT, 0, IRegistry::eErrPost); {{ string memlimitstr(reg.GetString(kServerSec, - "total_memory_limit", kEmptyStr, IRegistry::eReturn)); + "total_memory_limit", kEmptyStr)); if (!memlimitstr.empty()) m_TotalMemoryLimit = NStr::StringToUInt8_DataSize(memlimitstr); }} m_TotalTimeLimit = reg.GetInt(kServerSec, - "total_time_limit", 0, 0, IRegistry::eReturn); + "total_time_limit", 0, 0, IRegistry::eErrPost); m_StartupTime = time(0); CGridGlobals::GetInstance().SetReuseJobObject(reg.GetBool(kServerSec, - "reuse_job_object", false, 0, CNcbiRegistry::eReturn)); + "reuse_job_object", false, 0, CNcbiRegistry::eErrPost)); CGridGlobals::GetInstance().SetWorker(this); m_LogRequested = reg.GetBool(kServerSec, - "log", false, 0, IRegistry::eReturn); + "log", false, 0, IRegistry::eErrPost); m_ProgressLogRequested = reg.GetBool(kServerSec, - "log_progress", false, 0, IRegistry::eReturn); + "log_progress", false, 0, IRegistry::eErrPost); m_ThreadPoolTimeout = reg.GetInt(kServerSec, - "thread_pool_timeout", 30, 0, IRegistry::eReturn); + "thread_pool_timeout", 30, 0, IRegistry::eErrPost); } void SGridWorkerNodeImpl::x_StartWorkerThreads() @@ -456,7 +456,7 @@ void SGridWorkerNodeImpl::x_StartWorkerThreads() try { unsigned init_threads = m_App.GetConfig().GetInt("server", - "init_threads", 1, 0, IRegistry::eReturn); + "init_threads", 1, 0, IRegistry::eErrPost); m_ThreadPool->Spawn(init_threads <= m_MaxThreads ? init_threads : m_MaxThreads); @@ -543,7 +543,7 @@ int SGridWorkerNodeImpl::Run( #ifdef NCBI_OS_UNIX bool is_daemon = daemonize != eDefault ? daemonize == eOn : - reg.GetBool(kServerSec, "daemon", false, 0, CNcbiRegistry::eReturn); + reg.GetBool(kServerSec, "daemon", false, 0, CNcbiRegistry::eErrPost); #endif vector vhosts; @@ -571,17 +571,17 @@ int SGridWorkerNodeImpl::Run( } m_CommitJobInterval = reg.GetInt(kServerSec, "commit_job_interval", - COMMIT_JOB_INTERVAL_DEFAULT, 0, IRegistry::eReturn); + COMMIT_JOB_INTERVAL_DEFAULT, 0, IRegistry::eErrPost); if (m_CommitJobInterval == 0) m_CommitJobInterval = 1; m_CheckStatusPeriod = reg.GetInt(kServerSec, - "check_status_period", 2, 0, IRegistry::eReturn); + "check_status_period", 2, 0, IRegistry::eErrPost); if (m_CheckStatusPeriod == 0) m_CheckStatusPeriod = 1; m_DefaultPullbackTimeout = reg.GetInt(kServerSec, - "default_pullback_timeout", 0, 0, IRegistry::eReturn); + "default_pullback_timeout", 0, 0, IRegistry::eErrPost); if (reg.HasEntry(kServerSec, "wait_server_timeout")) { ERR_POST_X(52, "[" << kServerSec << @@ -671,7 +671,7 @@ int SGridWorkerNodeImpl::Run( #ifdef NCBI_OS_UNIX bool reliable_cleanup = reg.GetBool(kServerSec, - "reliable_cleanup", false, 0, CNcbiRegistry::eReturn); + "reliable_cleanup", false, 0, CNcbiRegistry::eErrPost); if (reliable_cleanup) { TPid child_pid = CProcess::Fork(); @@ -754,27 +754,27 @@ int SGridWorkerNodeImpl::Run( } m_JobsPerClientIP.ResetJobCounter((unsigned) reg.GetInt(kServerSec, - "max_jobs_per_client_ip", 0, 0, IRegistry::eReturn)); + "max_jobs_per_client_ip", 0, 0, IRegistry::eErrPost)); m_JobsPerSessionID.ResetJobCounter((unsigned) reg.GetInt(kServerSec, - "max_jobs_per_session_id", 0, 0, IRegistry::eReturn)); + "max_jobs_per_session_id", 0, 0, IRegistry::eErrPost)); CWNJobWatcher& watcher(CGridGlobals::GetInstance().GetJobWatcher()); watcher.SetMaxJobsAllowed(reg.GetInt(kServerSec, - "max_total_jobs", 0, 0, IRegistry::eReturn)); + "max_total_jobs", 0, 0, IRegistry::eErrPost)); watcher.SetMaxFailuresAllowed(reg.GetInt(kServerSec, - "max_failed_jobs", 0, 0, IRegistry::eReturn)); + "max_failed_jobs", 0, 0, IRegistry::eErrPost)); watcher.SetInfiniteLoopTime(reg.GetInt(kServerSec, - "infinite_loop_time", 0, 0, IRegistry::eReturn)); + "infinite_loop_time", 0, 0, IRegistry::eErrPost)); CGridGlobals::GetInstance().SetUDPPort( m_NSExecutor->m_NotificationHandler.GetPort()); IWorkerNodeIdleTask* task = NULL; unsigned idle_run_delay = reg.GetInt(kServerSec, - "idle_run_delay", 30, 0, IRegistry::eReturn); + "idle_run_delay", 30, 0, IRegistry::eErrPost); unsigned auto_shutdown = reg.GetInt(kServerSec, - "auto_shutdown_if_idle", 0, 0, IRegistry::eReturn); + "auto_shutdown_if_idle", 0, 0, IRegistry::eErrPost); if (idle_run_delay > 0) task = m_JobProcessorFactory->GetIdleTask(); @@ -813,7 +813,7 @@ int SGridWorkerNodeImpl::Run( LOG_POST_X(31, Info << "Shutting down..."); bool force_exit = reg.GetBool(kServerSec, - "force_exit", false, 0, CNcbiRegistry::eReturn); + "force_exit", false, 0, CNcbiRegistry::eErrPost); if (force_exit) { ERR_POST_X(45, "Force exit (worker threads will not be waited for)"); } else diff --git a/c++/src/connect/services/grid_worker_app.cpp b/c++/src/connect/services/grid_worker_app.cpp index 75c18f2e..6c5c1e6f 100644 --- a/c++/src/connect/services/grid_worker_app.cpp +++ b/c++/src/connect/services/grid_worker_app.cpp @@ -1,4 +1,4 @@ -/* $Id: grid_worker_app.cpp 491697 2016-02-08 18:44:39Z ivanov $ +/* $Id: grid_worker_app.cpp 491506 2016-02-05 16:08:02Z sadyrovr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/connect/services/grid_worker_impl.hpp b/c++/src/connect/services/grid_worker_impl.hpp index 76fb1814..4ce913ef 100644 --- a/c++/src/connect/services/grid_worker_impl.hpp +++ b/c++/src/connect/services/grid_worker_impl.hpp @@ -1,7 +1,7 @@ #ifndef CONNECT_SERVICES__GRID_WORKER_IMPL__HPP #define CONNECT_SERVICES__GRID_WORKER_IMPL__HPP -/* $Id: grid_worker_impl.hpp 488742 2016-01-05 15:56:22Z sadyrovr $ +/* $Id: grid_worker_impl.hpp 518714 2016-11-07 18:04:33Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -32,12 +32,13 @@ * Common NetSchedule Worker Node declarations */ -#include #include "wn_commit_thread.hpp" #include "wn_cleanup.hpp" #include "netschedule_api_impl.hpp" +#include + BEGIN_NCBI_SCOPE ///////////////////////////////////////////////////////////////////////////// @@ -273,7 +274,7 @@ struct SGridWorkerNodeImpl : public CObject private: CFastMutex m_Mutex; - hash_set m_Ids; + unordered_set m_Ids; }; SJobsInProgress m_JobsInProgress; @@ -345,6 +346,7 @@ private: bool CheckEntry( SEntry& entry, const string& prio_aff_list, + bool any_affinity, CNetScheduleJob& job, CNetScheduleAPI::EJobStatus* job_status); void ReturnJob(CNetScheduleJob& job); diff --git a/c++/src/connect/services/json_over_uttp.cpp b/c++/src/connect/services/json_over_uttp.cpp index 36c75262..8c37858e 100644 --- a/c++/src/connect/services/json_over_uttp.cpp +++ b/c++/src/connect/services/json_over_uttp.cpp @@ -1,4 +1,4 @@ -/* $Id: json_over_uttp.cpp 495785 2016-03-21 16:50:59Z ivanov $ +/* $Id: json_over_uttp.cpp 502217 2016-05-23 15:32:11Z sadyrovr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -40,6 +40,49 @@ BEGIN_NCBI_SCOPE +class CJsonParser +{ +public: + CJsonNode ParseObject(const string& ns_output) + { + m_Ch = (m_NSOutput = ns_output).c_str(); + + return ParseObject('\0'); + } + + CJsonNode ParseArray(const string& ns_output) + { + m_Ch = (m_NSOutput = ns_output).c_str(); + + return ParseArray('\0'); + } + + CJsonNode ParseJSON(const string& json); + +private: + size_t GetRemainder() const + { + return m_NSOutput.length() - (m_Ch - m_NSOutput.data()); + } + + size_t GetPosition() const + { + return m_Ch - m_NSOutput.data() + 1; + } + + string ParseString(size_t max_len); + Int8 ParseInt(size_t len); + double ParseDouble(size_t len); + bool MoreNodes(); + + CJsonNode ParseObject(char closing_char); + CJsonNode ParseArray(char closing_char); + CJsonNode ParseValue(); + + string m_NSOutput; + const char* m_Ch; +}; + const char* CJsonException::GetErrCodeString() const { switch (GetErrCode()) { @@ -911,6 +954,261 @@ string CJsonNode::Repr(TReprFlags flags) const return CNcbiOstrstreamToString(oss); } +#define INVALID_FORMAT_ERROR() \ + NCBI_THROW2(CStringException, eFormat, \ + (*m_Ch == '\0' ? "Unexpected end of output" : \ + "Syntax error in structured output"), \ + GetPosition()) + +CJsonNode CJsonParser::ParseJSON(const string& json) +{ + m_Ch = (m_NSOutput = json).c_str(); + + while (isspace((unsigned char) *m_Ch)) + ++m_Ch; + + CJsonNode root; + + switch (*m_Ch) { + case '[': + ++m_Ch; + root = ParseArray(']'); + break; + + case '{': + ++m_Ch; + root = ParseObject('}'); + break; + + default: + INVALID_FORMAT_ERROR(); + } + + while (isspace((unsigned char) *m_Ch)) + ++m_Ch; + + if (*m_Ch != '\0') { + INVALID_FORMAT_ERROR(); + } + + return root; +} + +string CJsonParser::ParseString(size_t max_len) +{ + size_t len; + string val(NStr::ParseQuoted(CTempString(m_Ch, max_len), &len)); + + m_Ch += len; + return val; +} + +Int8 CJsonParser::ParseInt(size_t len) +{ + Int8 val = NStr::StringToInt8(CTempString(m_Ch, len)); + + if (*m_Ch == '-') { + ++m_Ch; + --len; + } + if (*m_Ch == '0' && len > 1) { + NCBI_THROW2(CStringException, eFormat, + "Leading zeros are not allowed", GetPosition()); + } + + m_Ch += len; + return val; +} + +double CJsonParser::ParseDouble(size_t len) +{ + double val = NStr::StringToDouble(CTempString(m_Ch, len)); + + m_Ch += len; + return val; +} + +bool CJsonParser::MoreNodes() +{ + while (isspace((unsigned char) *m_Ch)) + ++m_Ch; + if (*m_Ch != ',') + return false; + while (isspace((unsigned char) *++m_Ch)) + ; + return true; +} + +CJsonNode CJsonParser::ParseObject(char closing_char) +{ + CJsonNode result(CJsonNode::NewObjectNode()); + + while (isspace((unsigned char) *m_Ch)) + ++m_Ch; + + if (*m_Ch == closing_char) { + ++m_Ch; + return result; + } + + while (*m_Ch == '\'' || *m_Ch == '"') { + // New attribute/value pair + string attr_name(ParseString(GetRemainder())); + + while (isspace((unsigned char) *m_Ch)) + ++m_Ch; + if (*m_Ch == ':' || *m_Ch == '=') + while (isspace((unsigned char) *++m_Ch)) + ; + + result.SetByKey(attr_name, ParseValue()); + + if (!MoreNodes()) { + if (*m_Ch != closing_char) + break; + ++m_Ch; + return result; + } + } + + INVALID_FORMAT_ERROR(); +} + +CJsonNode CJsonParser::ParseArray(char closing_char) +{ + CJsonNode result(CJsonNode::NewArrayNode()); + + while (isspace((unsigned char) *m_Ch)) + ++m_Ch; + + if (*m_Ch == closing_char) { + ++m_Ch; + return result; + } + + do + result.Append(ParseValue()); + while (MoreNodes()); + + if (*m_Ch == closing_char) { + ++m_Ch; + return result; + } + + INVALID_FORMAT_ERROR(); +} + +CJsonNode CJsonParser::ParseValue() +{ + size_t max_len = GetRemainder(); + size_t len = 0; + + switch (*m_Ch) { + /* Array */ + case '[': + ++m_Ch; + return ParseArray(']'); + + /* Object */ + case '{': + ++m_Ch; + return ParseObject('}'); + + /* String */ + case '\'': + case '"': + return CJsonNode::NewStringNode(ParseString(max_len)); + + /* Number */ + case '-': + // Check that there's at least one digit after the minus sign. + if (max_len <= 1 || !isdigit((unsigned char) m_Ch[1])) { + ++m_Ch; + break; + } + len = 1; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + // Skim through the integer part. + do + if (++len >= max_len) + return CJsonNode::NewIntegerNode(ParseInt(len)); + while (isdigit((unsigned char) m_Ch[len])); + + // Stumbled upon a non-digit character -- check + // if it's a fraction part or an exponent part. + switch (m_Ch[len]) { + case '.': + if (++len == max_len || !isdigit((unsigned char) m_Ch[len])) { + NCBI_THROW2(CStringException, eFormat, + "At least one digit after the decimal " + "point is required", GetPosition()); + } + for (;;) { + if (++len == max_len) + return CJsonNode::NewDoubleNode(ParseDouble(len)); + + if (!isdigit((unsigned char) m_Ch[len])) { + if (m_Ch[len] == 'E' || m_Ch[len] == 'e') + break; + + return CJsonNode::NewDoubleNode(ParseDouble(len)); + } + } + /* FALL THROUGH */ + + case 'E': + case 'e': + if (++len == max_len || + (m_Ch[len] == '-' || m_Ch[len] == '+' ? + ++len == max_len || + !isdigit((unsigned char) m_Ch[len]) : + !isdigit((unsigned char) m_Ch[len]))) { + m_Ch += len; + NCBI_THROW2(CStringException, eFormat, + "Invalid exponent specification", GetPosition()); + } + while (++len < max_len && isdigit((unsigned char) m_Ch[len])) + ; + return CJsonNode::NewDoubleNode(ParseDouble(len)); + + default: + return CJsonNode::NewIntegerNode(ParseInt(len)); + } + + /* Constant */ + case 'F': case 'f': case 'N': case 'n': + case 'T': case 't': case 'Y': case 'y': + while (len <= max_len && isalpha((unsigned char) m_Ch[len])) + ++len; + + { + CTempString val(m_Ch, len); + m_Ch += len; + return val == "null" ? CJsonNode::NewNullNode() : + CJsonNode::NewBooleanNode(NStr::StringToBool(val)); + } + } + + INVALID_FORMAT_ERROR(); +} + +CJsonNode CJsonNode::ParseObject(const string& json) +{ + return CJsonParser().ParseObject(json); +} + +CJsonNode CJsonNode::ParseArray(const string& json) +{ + return CJsonParser().ParseArray(json); +} + +CJsonNode CJsonNode::ParseJSON(const string& json) +{ + return CJsonParser().ParseJSON(json); +} + const char* CJsonOverUTTPException::GetErrCodeString() const { switch (GetErrCode()) { diff --git a/c++/src/connect/services/netcache_api.cpp b/c++/src/connect/services/netcache_api.cpp index 46660167..b5b41115 100644 --- a/c++/src/connect/services/netcache_api.cpp +++ b/c++/src/connect/services/netcache_api.cpp @@ -1,4 +1,4 @@ -/* $Id: netcache_api.cpp 497256 2016-04-05 15:59:16Z ivanov $ +/* $Id: netcache_api.cpp 520436 2016-11-28 18:34:35Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -174,6 +174,9 @@ void CNetCacheServerListener::OnInit(CObject* api_impl, } } } + + nc_impl->m_ProlongBlobLifetimeOnWrite = config->GetBool(config_section, + "prolong_blob_lifetime_on_write", CConfig::eErr_NoThrow, true); } else { nc_impl->m_TempDir = default_temp_dir; nc_impl->m_CacheInput = false; @@ -568,6 +571,7 @@ CNetServerConnection SNetCacheAPIImpl::InitiateWriteCmd( m_UseNextSubHitID.ProperCommand(); AppendClientIPSessionIDPasswordAgeHitID(&cmd, parameters); + if (!m_ProlongBlobLifetimeOnWrite) cmd.append(" flags=1"); CNetServer::SExecResult exec_result; diff --git a/c++/src/connect/services/netcache_api_impl.hpp b/c++/src/connect/services/netcache_api_impl.hpp index 382449b6..1d820fa0 100644 --- a/c++/src/connect/services/netcache_api_impl.hpp +++ b/c++/src/connect/services/netcache_api_impl.hpp @@ -1,7 +1,7 @@ #ifndef CONNECT_SERVICES___NETCACHE_API_IMPL__HPP #define CONNECT_SERVICES___NETCACHE_API_IMPL__HPP -/* $Id: netcache_api_impl.hpp 492602 2016-02-18 19:27:34Z ivanov $ +/* $Id: netcache_api_impl.hpp 520437 2016-11-28 18:35:09Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -33,6 +33,7 @@ #include "netcache_rw.hpp" #include "netservice_api_impl.hpp" +#include BEGIN_NCBI_SCOPE @@ -140,6 +141,7 @@ struct NCBI_XCONNECT_EXPORT SNetCacheAPIImpl : public CObject CCompoundIDPool m_CompoundIDPool; SUseNextSubHitID m_UseNextSubHitID; + bool m_ProlongBlobLifetimeOnWrite = true; }; struct SNetCacheAdminImpl : public CObject @@ -176,6 +178,18 @@ public: bool m_PrimaryServerCheck; }; +namespace grid { +namespace netcache { +namespace search { + +NCBI_XCONNECT_EXPORT CExpression operator+(CExpression l, CFields r); +NCBI_XCONNECT_EXPORT ostream& operator<<(ostream& os, CExpression expression); +NCBI_XCONNECT_EXPORT void operator<<(CBlobInfo& blob_info, string data); + +} +} +} + END_NCBI_SCOPE #endif /* CONNECT_SERVICES___NETCACHE_API_IMPL__HPP */ diff --git a/c++/src/connect/services/netcache_rw.cpp b/c++/src/connect/services/netcache_rw.cpp index 466ee4d1..0d3bafd4 100644 --- a/c++/src/connect/services/netcache_rw.cpp +++ b/c++/src/connect/services/netcache_rw.cpp @@ -1,4 +1,4 @@ -/* $Id: netcache_rw.cpp 496093 2016-03-23 18:15:45Z ivanov $ +/* $Id: netcache_rw.cpp 495903 2016-03-22 15:17:00Z sadyrovr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/connect/services/netcache_search.cpp b/c++/src/connect/services/netcache_search.cpp new file mode 100644 index 00000000..b4b2bd7e --- /dev/null +++ b/c++/src/connect/services/netcache_search.cpp @@ -0,0 +1,556 @@ +/* $Id: netcache_search.cpp 520437 2016-11-28 18:35:09Z ivanov $ + * =========================================================================== + * + * PUBLIC DOMAIN NOTICE + * National Center for Biotechnology Information + * + * This software/database is a "United States Government Work" under the + * terms of the United States Copyright Act. It was written as part of + * the author's official duties as a United States Government employee and + * thus cannot be copyrighted. This software/database is freely available + * to the public for use. The National Library of Medicine and the U.S. + * Government have not placed any restriction on its use or reproduction. + * + * Although all reasonable efforts have been taken to ensure the accuracy + * and reliability of the software and data, the NLM and the U.S. + * Government do not and cannot warrant the performance or results that + * may be obtained by using this software or data. The NLM and the U.S. + * Government disclaim all warranties, express or implied, including + * warranties of performance, merchantability or fitness for any particular + * purpose. + * + * Please cite the author in any work or product based on this material. + * + * =========================================================================== + * + * Author: Rafael Sadyrov + * + */ + + +#include + +#include +#include +#include +#include "netcache_api_impl.hpp" + +#include +#include +#include + + +namespace ncbi { +namespace grid { +namespace netcache { +namespace search { + +using namespace chrono; + +enum ETerm : size_t +{ + eKey, + eSubkey, + eCreatedAgo, + eCreated, + eExpiresIn, + eExpires, + eVersionExpiresIn, + eVersionExpires, + eSize, + + eNumberOfTerms +}; + +enum EComparison : size_t +{ + eGreaterOrEqual, + eEqual, + eLessThan, + + eNumberOfComparisons +}; + +struct SCondition +{ + SCondition(size_t key) : m_Key(key) {} + virtual ~SCondition() {} + + size_t Key() const { return m_Key; } + + virtual ostream& Output(ostream&) const = 0; + virtual void Merge(SCondition*) = 0; + + template + static SCondition* Create(TValue); + +private: + size_t m_Key; +}; + +ostream& operator<<(ostream& os, const SCondition& c) +{ + return c.Output(os); +} + +template +struct SConditionImpl : SCondition +{ + SConditionImpl(TValue value) : + SCondition(comparison + term * eNumberOfComparisons), + m_Value(value) + { + } + + ostream& Output(ostream& os) const override; + void Merge(SCondition*) override; + +private: + TValue m_Value; +}; + +const char* s_Term(ETerm term) +{ + switch (term) { + case eKey: return "key"; + case eSubkey: return "subkey"; + case eCreated: return "fcr_epoch"; + case eCreatedAgo: return "fcr_ago"; + case eExpires: return "fexp_epoch"; + case eExpiresIn: return "fexp_now"; + case eVersionExpires: return "fvexp_epoch"; + case eVersionExpiresIn: return "fvexp_now"; + case eSize: return "fsize"; + default: return nullptr; + } +} + +const char* s_Comparison(EComparison comparison) +{ + switch (comparison) { + case eLessThan: return "_lt"; + case eEqual: return ""; + case eGreaterOrEqual: return "_ge"; + default: return nullptr; + } +} + +template +string s_Value(TValue value) +{ + return to_string(value); +} + +template <> +string s_Value(string value) +{ + return value; +} + +template +ostream& SConditionImpl::Output(ostream& os) const +{ + return os << s_Term(term) << s_Comparison(comparison) << "=" << s_Value(m_Value); +} + +template +struct SMerge; + +template +struct SMerge +{ + SMerge(TValue& left, const TValue& right) + { + if (left > right) left = right; + } +}; + +template +struct SMerge +{ + SMerge(TValue& left, const TValue& right) + { + if (left < right) left = right; + } +}; + +template <> +struct SMerge +{ + SMerge(string&, const string&) + { + NCBI_THROW_FMT(CNetCacheException, eNotImplemented, + "Field '" << s_Term(eKey) << "' cannot be specified more than once"); + } +}; + +template +void SConditionImpl::Merge(SCondition* o) +{ + auto other = dynamic_cast(o); + _ASSERT(other); + + SMerge(m_Value, other->m_Value); +} + +template +SCondition* SCondition::Create(TValue value) +{ + return new SConditionImpl(value); +} + +struct SExpressionImpl +{ + list> conditions; +}; + +SExpression::~SExpression() +{ +} + +template +SExpression s_CreateBase(TValue value) +{ + auto condition = SCondition::Create(value); + + SExpression result; + result.impl.reset(new SExpressionImpl); + result.impl->conditions.emplace_back(condition); + return result; +} + +template +CExpression s_Create(TValue value) +{ + CExpression result; + result.base = s_CreateBase(value); + return result; +} + +chrono::seconds::rep s_GetSeconds(duration d) +{ + return duration_cast(d).count(); +} + +chrono::seconds::rep s_GetSeconds(time_point p) +{ + return s_GetSeconds(p.time_since_epoch()); +} + +CExpression operator==(KEY, string v) +{ + return s_Create(v); +} + +CExpression operator>=(CREATED, time_point v) +{ + return s_Create(s_GetSeconds(v)); +} + +CExpression operator< (CREATED, time_point v) +{ + return s_Create(s_GetSeconds(v)); +} + +CExpression operator>=(CREATED, duration v) +{ + return s_Create(s_GetSeconds(v)); +} + +CExpression operator< (CREATED, duration v) +{ + return s_Create(s_GetSeconds(v)); +} + +CExpression operator>=(EXPIRES, time_point v) +{ + return s_Create(s_GetSeconds(v)); +} + +CExpression operator< (EXPIRES, time_point v) +{ + return s_Create(s_GetSeconds(v)); +} + +CExpression operator>=(EXPIRES, duration v) +{ + return s_Create(s_GetSeconds(v)); +} + +CExpression operator< (EXPIRES, duration v) +{ + return s_Create(s_GetSeconds(v)); +} + +CExpression operator>=(VERSION_EXPIRES, time_point v) +{ + return s_Create(s_GetSeconds(v)); +} + +CExpression operator< (VERSION_EXPIRES, time_point v) +{ + return s_Create(s_GetSeconds(v)); +} + +CExpression operator>=(VERSION_EXPIRES, duration v) +{ + return s_Create(s_GetSeconds(v)); +} + +CExpression operator< (VERSION_EXPIRES, duration v) +{ + return s_Create(s_GetSeconds(v)); +} + +CExpression operator>=(SIZE, size_t v) +{ + return s_Create(v); +} + +CExpression operator< (SIZE, size_t v) +{ + return s_Create(v); +} + +void s_Merge(SExpression& l, SExpression& r) +{ + if (!l.impl) { l = r; return; } + if (!r.impl) return; + + auto& lc = l.impl->conditions; + auto& rc = r.impl->conditions; + auto li = lc.begin(); + auto ri = rc.begin(); + + while (li != lc.end() && ri != rc.end()) { + auto& lp = *li; + auto& rp = *ri; + + if (lp->Key() < rp->Key()) { + ++li; + } else if (lp->Key() > rp->Key()) { + auto old_ri = ri; + lc.splice(li, rc, old_ri, ++ri); + } else { + lp->Merge(rp.get()); + ++li; + ++ri; + } + } + + if (ri != rc.end()) { + lc.splice(lc.end(), rc, ri, rc.end()); + } +} + +CExpression operator&&(CExpression l, CExpression r) +{ + s_Merge(l.base, r.base); + return l; +} + +CExpression operator+(CExpression l, CFields r) +{ + s_Merge(l.base, r.base); + return l; +} + +ostream& operator<<(ostream& os, CExpression expression) +{ + if (!expression.base.impl) return os; + + for (auto& condition : expression.base.impl->conditions) { + os << " " << *condition; + } + + return os; +} + +// Mirrored versions +CExpression operator==(string v, KEY t) { return t == v; } +CExpression operator<=(time_point v, CREATED t) { return t >= v; } +CExpression operator> (time_point v, CREATED t) { return t < v; } +CExpression operator<=(duration v, CREATED t) { return t >= v; } +CExpression operator> (duration v, CREATED t) { return t < v; } +CExpression operator<=(time_point v, EXPIRES t) { return t >= v; } +CExpression operator> (time_point v, EXPIRES t) { return t < v; } +CExpression operator<=(duration v, EXPIRES t) { return t >= v; } +CExpression operator> (duration v, EXPIRES t) { return t < v; } +CExpression operator<=(time_point v, VERSION_EXPIRES t) { return t >= v; } +CExpression operator> (time_point v, VERSION_EXPIRES t) { return t < v; } +CExpression operator<=(duration v, VERSION_EXPIRES t) { return t >= v; } +CExpression operator> (duration v, VERSION_EXPIRES t) { return t < v; } +CExpression operator<=(size_t v, SIZE t) { return t >= v; } +CExpression operator> (size_t v, SIZE t) { return t < v; } + +// Cannot use zero, as corresponding condition would be ignored then +const chrono::seconds::rep kSmallestTimePoint = 1; +const size_t kLargestSize = numeric_limits::max(); + +CFields::CFields() +{ +} + +CFields::CFields(CREATED) + : base(s_CreateBase(kSmallestTimePoint)) +{ +} + +CFields::CFields(EXPIRES) + : base(s_CreateBase(kSmallestTimePoint)) +{ +} + +CFields::CFields(VERSION_EXPIRES) + : base(s_CreateBase(kSmallestTimePoint)) +{ +} + +CFields::CFields(SIZE) + : base(s_CreateBase(kLargestSize)) +{ +} + +CFields operator|(CFields l, CFields r) +{ + s_Merge(l.base, r.base); + return l; +} + +struct SBlobInfoImpl +{ + string key; + string subkey; + + SBlobInfoImpl(string key, string subkey, string data); + time_point operator[](CREATED); + time_point operator[](EXPIRES); + time_point operator[](VERSION_EXPIRES); + size_t operator[](SIZE); + + static SBlobInfoImpl* Create(string data); + +private: + void Parse(); + + const string m_Data; + bool m_Parsed; + CNullable m_Created; + CNullable m_Expires; + CNullable m_VersionExpires; + CNullable m_Size; +}; + +SBlobInfoImpl::SBlobInfoImpl(string k, string sk, string data) + : key(k), + subkey(sk), + m_Data(data), + m_Parsed(false) +{ +} + +time_point SBlobInfoImpl::operator[](CREATED) +{ + if (!m_Parsed) Parse(); + return m_Created.GetValue(); +} + +time_point SBlobInfoImpl::operator[](EXPIRES) +{ + if (!m_Parsed) Parse(); + return m_Expires.GetValue(); +} + +time_point SBlobInfoImpl::operator[](VERSION_EXPIRES) +{ + if (!m_Parsed) Parse(); + return m_VersionExpires.GetValue(); +} + +size_t SBlobInfoImpl::operator[](SIZE) +{ + if (!m_Parsed) Parse(); + return m_Size.GetValue(); +} + +const string kSeparator = "\t"; + +void SBlobInfoImpl::Parse() +{ + vector fields; + + NStr::Split(m_Data, kSeparator, fields); + + for (auto& field : fields) { + string name, value; + NStr::SplitInTwo(field, "=", name, value); + if (name == "cr_time") { + m_Created = time_point(seconds(stoll(value))); + } else if (name == "exp") { + m_Expires = time_point(seconds(stoll(value))); + } else if (name == "ver_dead") { + m_VersionExpires = time_point(seconds(stoll(value))); + } else if (name == "size") { + m_Size = stoull(value); + } else { + NCBI_THROW_FMT(CNetCacheException, eInvalidServerResponse, + "Unknown field '" << name << "' in response '" << m_Data << "'"); + } + } + + m_Parsed = true; +} + +void operator<<(CBlobInfo& blob_info, string data) +{ + string cache, key, subkey, remaining; + NStr::SplitInTwo(data, kSeparator, cache, remaining); + NStr::SplitInTwo(remaining, kSeparator, key, remaining); + NStr::SplitInTwo(remaining, kSeparator, subkey, remaining); + blob_info.base.impl.reset(new SBlobInfoImpl(key, subkey, remaining)); +} + +SBlobInfo::~SBlobInfo() +{ +} + +string CBlobInfo::operator[](KEY) const +{ + if (!base.impl) return string(); + return base.impl->key; +} + +string CBlobInfo::operator[](SUBKEY) const +{ + if (!base.impl) return string(); + return base.impl->subkey; +} + +time_point CBlobInfo::operator[](CREATED created) const +{ + if (!base.impl) return time_point(); + return (*base.impl)[created]; +} + +time_point CBlobInfo::operator[](EXPIRES expires) const +{ + if (!base.impl) return time_point(); + return (*base.impl)[expires]; +} + +time_point CBlobInfo::operator[](VERSION_EXPIRES version_expires) const +{ + if (!base.impl) return time_point(); + return (*base.impl)[version_expires]; +} + +size_t CBlobInfo::operator[](SIZE size) const +{ + if (!base.impl) return size_t(); + return (*base.impl)[size]; +} + +} +} +} +} diff --git a/c++/src/connect/services/neticache_client.cpp b/c++/src/connect/services/neticache_client.cpp index 04ff6368..3f14c070 100644 --- a/c++/src/connect/services/neticache_client.cpp +++ b/c++/src/connect/services/neticache_client.cpp @@ -1,4 +1,4 @@ -/* $Id: neticache_client.cpp 498373 2016-04-15 17:20:10Z ivanov $ +/* $Id: neticache_client.cpp 520437 2016-11-28 18:35:09Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -51,6 +51,7 @@ #include #include +#include #define MAX_ICACHE_CACHE_NAME_LENGTH 64 #define MAX_ICACHE_KEY_LENGTH 256 @@ -248,6 +249,7 @@ CNetServerConnection SNetICacheClientImpl::InitiateWriteCmd( cmd.append(" confirm=1"); m_UseNextSubHitID.ProperCommand(); AppendClientIPSessionIDPasswordAgeHitID(&cmd, parameters); + if (!m_ProlongBlobLifetimeOnWrite) cmd.append(" flags=1"); return ChooseServerAndExec(cmd, nc_writer->GetKey(), false, parameters).conn; @@ -1105,6 +1107,37 @@ void CNetICacheClient::SetEventHandler(INetEventHandler* event_handler) m_Impl->GetListener()->m_EventHandler = event_handler; } +vector CNetICacheClient::Search( + CNetICacheClient::CExpression expression, + CNetICacheClient::CFields filter) +{ + const auto parameters = &m_Impl->m_DefaultParameters; + const auto cache_name = NStr::PrintableString(parameters->GetCacheName()); + string ids; + m_Impl->AppendClientIPSessionIDPasswordAgeHitID(&ids, parameters); + ostringstream oss; + oss << "IC(" << cache_name << ") BLIST2" << expression + filter << ids; + + CNetServerMultilineCmdOutput output( + m_Impl->ChooseServerAndExec( + oss.str(), + kEmptyStr, + true, + &m_Impl->m_DefaultParameters)); + + output->SetNetCacheCompatMode(); + string line; + vector result; + + while (output.ReadLine(line) && !line.empty()) { + CBlobInfo blob_info; + blob_info << line; + result.push_back(blob_info); + } + + return result; +} + void CNetICacheClientExt::ProlongBlobLifetime(const string& key, const CTimeout& ttl, const CNamedParameterList* optional) { diff --git a/c++/src/connect/services/netschedule_api.cpp b/c++/src/connect/services/netschedule_api.cpp index c8b408e4..67dbf74d 100644 --- a/c++/src/connect/services/netschedule_api.cpp +++ b/c++/src/connect/services/netschedule_api.cpp @@ -1,4 +1,4 @@ -/* $Id: netschedule_api.cpp 498273 2016-04-14 17:59:04Z ivanov $ +/* $Id: netschedule_api.cpp 514423 2016-09-21 17:22:32Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -687,8 +687,6 @@ void CNetScheduleServerListener::OnInit( SNetScheduleAPIImpl::VerifyQueueNameAlphabet(queue_ref); } - ns_impl->m_AffinityPreference = CNetScheduleExecutor::eAnyJob; - const list embedded_synonyms{"use_embedded_input"}; bool use_affinities_value; @@ -724,43 +722,7 @@ void CNetScheduleServerListener::OnInit( embedded.ReadOnce(); if (use_affinities.ReadOnce() && use_affinities_value) { - ns_impl->m_AffinityPreference = config->GetBool(module, - "claim_new_affinities", CConfig::eErr_NoThrow, false) ? - CNetScheduleExecutor::eClaimNewPreferredAffs : - config->GetBool(module, - "process_any_job", CConfig::eErr_NoThrow, false) ? - CNetScheduleExecutor::ePreferredAffsOrAnyJob : - CNetScheduleExecutor::ePreferredAffinities; - - string affinity_list = config->GetString(module, - "affinity_list", CConfig::eErr_NoThrow, kEmptyStr); - - if (!affinity_list.empty()) { - NStr::Split(affinity_list, ", ", ns_impl->m_AffinityList, - NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate); - ITERATE(list, it, ns_impl->m_AffinityList) { - SNetScheduleAPIImpl::VerifyAffinityAlphabet(*it); - } - } - - string affinity_ladder = config->GetString(module, - "affinity_ladder", CConfig::eErr_NoThrow, kEmptyStr); - list affinities; - NStr::Split(affinity_ladder, ", ", affinities, - NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate); - - if (!affinities.empty()) { - list::const_iterator it = affinities.begin(); - affinity_list = *it; - for (;;) { - ns_impl->m_AffinityLadder.push_back( - make_pair(*it, affinity_list)); - if (++it == affinities.end()) - break; - affinity_list += ','; - affinity_list += *it; - } - } + ns_impl->InitAffinities(config, module); } job_group.ReadOnce(); @@ -898,28 +860,17 @@ static const char* const s_NetScheduleConfigSections[] = { SNetScheduleAPIImpl::SNetScheduleAPIImpl( CConfig* config, const string& section, const string& service_name, const string& client_name, - const string& queue_name) : + const string& queue_name, bool wn, bool try_config) : m_Service(new SNetServiceImpl("NetScheduleAPI", client_name, - new CNetScheduleServerListener)), + new CNetScheduleServerListener(wn, try_config))), m_Queue(queue_name), + m_AffinityPreference(CNetScheduleExecutor::eAnyJob), m_JobTtl(0) { m_Service->Init(this, service_name, config, section, s_NetScheduleConfigSections); } -SNetScheduleAPIImpl::SNetScheduleAPIImpl( - const string& service_name, const string& client_name, - const string& queue_name, bool wn_compatible) : - m_Service(new SNetServiceImpl("NetScheduleAPI", client_name, - new CNetScheduleServerListener(wn_compatible), wn_compatible)), - m_Queue(queue_name), - m_JobTtl(0) -{ - m_Service->Init(this, service_name, - NULL, kEmptyStr, s_NetScheduleConfigSections); -} - SNetScheduleAPIImpl::SNetScheduleAPIImpl( SNetServerInPool* server, SNetScheduleAPIImpl* parent) : m_Service(new SNetServiceImpl(server, parent->m_Service)), @@ -1429,6 +1380,75 @@ void SNetScheduleAPIImpl::SetAuthParam(const string& param_name, UpdateAuthString(); } +void SNetScheduleAPIImpl::InitAffinities(CConfig* config, const string& section) +{ + const bool claim_new_affinities = config->GetBool(section, + "claim_new_affinities", CConfig::eErr_NoThrow, false); + + const bool process_any_job = config->GetBool(section, + "process_any_job", CConfig::eErr_NoThrow, false); + + const string affinity_list = config->GetString(section, + "affinity_list", CConfig::eErr_NoThrow, kEmptyStr); + + const string affinity_ladder = config->GetString(section, + "affinity_ladder", CConfig::eErr_NoThrow, kEmptyStr); + + if (affinity_ladder.empty()) { + + if (claim_new_affinities) { + m_AffinityPreference = CNetScheduleExecutor::eClaimNewPreferredAffs; + + } else if (process_any_job) { + m_AffinityPreference = CNetScheduleExecutor::ePreferredAffsOrAnyJob; + + } else { + m_AffinityPreference = CNetScheduleExecutor::ePreferredAffinities; + } + + if (affinity_list.empty()) return; + + NStr::Split(affinity_list, ", ", m_AffinityList, + NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate); + + for (auto& affinity : m_AffinityList) { + VerifyAffinityAlphabet(affinity); + } + + return; + } + + // Sanity checks + if (claim_new_affinities) { + NCBI_THROW(CConfigException, eInvalidParameter, + "'affinity_ladder' cannot be used with 'claim_new_affinities'"); + } + if (!affinity_list.empty()) { + NCBI_THROW(CConfigException, eInvalidParameter, + "'affinity_ladder' cannot be used with 'affinity_list'"); + } + + if (!process_any_job) { + m_AffinityPreference = CNetScheduleExecutor::eExplicitAffinitiesOnly; + } + + list affinities; + NStr::Split(affinity_ladder, ", ", affinities, + NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate); + + if (affinities.empty()) return; + + string affinity_step; + + for (auto& affinity : affinities) { + VerifyAffinityAlphabet(affinity); + + if (!affinity_step.empty()) affinity_step += ','; + affinity_step += affinity; + m_AffinityLadder.emplace_back(affinity, affinity_step); + } +} + /////////////////////////////////////////////////////////////////////////////// /// @internal @@ -1550,14 +1570,16 @@ CNetScheduleAPI::TInstance CNetScheduleAPIExt::CreateWnCompat(const string& service_name, const string& client_name) { - return new SNetScheduleAPIImpl(service_name, client_name, kEmptyStr, true); + return new SNetScheduleAPIImpl(nullptr, kEmptyStr, + service_name, client_name, kEmptyStr, true, false); } CNetScheduleAPI::TInstance CNetScheduleAPIExt::CreateNoCfgLoad(const string& service_name, const string& client_name, const string& queue_name) { - return new SNetScheduleAPIImpl(service_name, client_name, queue_name, false); + return new SNetScheduleAPIImpl(nullptr, kEmptyStr, + service_name, client_name, queue_name, false, false); } diff --git a/c++/src/connect/services/netschedule_api_admin.cpp b/c++/src/connect/services/netschedule_api_admin.cpp index 6f0418a6..429b8a96 100644 --- a/c++/src/connect/services/netschedule_api_admin.cpp +++ b/c++/src/connect/services/netschedule_api_admin.cpp @@ -1,4 +1,4 @@ -/* $Id: netschedule_api_admin.cpp 492599 2016-02-18 19:26:29Z ivanov $ +/* $Id: netschedule_api_admin.cpp 492051 2016-02-11 17:22:40Z sadyrovr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/connect/services/netschedule_api_executor.cpp b/c++/src/connect/services/netschedule_api_executor.cpp index be05cdb2..442cca36 100644 --- a/c++/src/connect/services/netschedule_api_executor.cpp +++ b/c++/src/connect/services/netschedule_api_executor.cpp @@ -1,4 +1,4 @@ -/* $Id: netschedule_api_executor.cpp 486255 2015-12-02 17:51:03Z sadyrovr $ +/* $Id: netschedule_api_executor.cpp 518714 2016-11-07 18:04:33Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -192,6 +192,8 @@ static bool s_DoParseGetJobResponse( return true; } +string s_GET2(CNetScheduleExecutor::EJobAffinityPreference affinity_preference); + bool g_ParseGetJobResponse(CNetScheduleJob& job, const string& response) { if (response.empty()) @@ -354,66 +356,26 @@ bool SNetScheduleExecutorImpl::ExecGET(SNetServerImpl* server, return true; } -bool SNetScheduleExecutorImpl::x_GetJobWithAffinityList(SNetServerImpl* server, - const CDeadline* timeout, CNetScheduleJob& job, - CNetScheduleExecutor::EJobAffinityPreference affinity_preference, - const string& affinity_list) -{ - string cmd(CNetScheduleNotificationHandler::MkBaseGETCmd( - affinity_preference, affinity_list)); - - m_NotificationHandler.CmdAppendTimeoutGroupAndClientInfo(cmd, - timeout, m_JobGroup); - - return ExecGET(server, cmd, job); -} - bool SNetScheduleExecutorImpl::x_GetJobWithAffinityLadder( SNetServerImpl* server, const CDeadline& timeout, - const string& prio_aff_list, CNetScheduleJob& job) + const string& prio_aff_list, bool any_affinity, CNetScheduleJob& job) { - if (prio_aff_list.empty()) - return x_GetJobWithAffinityList(server, &timeout, job, - m_AffinityPreference, kEmptyStr); + // Ask for any affinity only when requested and configured + // (it's not requested when we have a job already). + const auto affinity_preference = any_affinity ? m_AffinityPreference : + CNetScheduleExecutor::eExplicitAffinitiesOnly; - // If prioritized_aff flag is supported (NS v4.22.0+) - CRef server_props = - CNetScheduleServerListener::x_GetServerProperties(server); + string cmd(s_GET2(affinity_preference)); + const bool have_affinities = !prio_aff_list.empty(); - if (server_props->version.IsUpCompatible(CVersionInfo(4, 22, 0))) { - string cmd("GET2 wnode_aff=0 any_aff=0 aff="); - cmd += prio_aff_list; + if (have_affinities) cmd += " aff=" + prio_aff_list; - m_NotificationHandler.CmdAppendTimeoutGroupAndClientInfo(cmd, - &timeout, m_JobGroup); - - cmd.append(" prioritized_aff=1"); - return ExecGET(server, cmd, job); - } - - // XXX: Compatibility mode. - // TODO: Can be thrown out after all NS serves are updated to version 4.22.0+ - list affinity_tokens; - NStr::Split(prio_aff_list, ",", affinity_tokens, - NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate); - - string affinity_list; - list::const_iterator it = affinity_tokens.begin(); - - while (it != affinity_tokens.end()) { - affinity_list += *it; - const bool last_try = ++it == affinity_tokens.end(); - - if (x_GetJobWithAffinityList(server, last_try ? &timeout : NULL, - job, CNetScheduleExecutor::eExplicitAffinitiesOnly, - affinity_list)) { - return true; - } + m_NotificationHandler.CmdAppendTimeoutGroupAndClientInfo(cmd, + &timeout, m_JobGroup); - affinity_list += ','; - } + if (have_affinities) cmd += " prioritized_aff=1"; - return false; + return ExecGET(server, cmd, job); } bool CNetScheduleExecutor::GetJob(CNetScheduleJob& job, @@ -477,32 +439,31 @@ bool CNetScheduleExecutor::GetJob(CNetScheduleJob& job, } } -string CNetScheduleNotificationHandler::MkBaseGETCmd( - CNetScheduleExecutor::EJobAffinityPreference affinity_preference, - const string& affinity_list) +string s_GET2(CNetScheduleExecutor::EJobAffinityPreference affinity_preference) { - string cmd; - switch (affinity_preference) { case CNetScheduleExecutor::ePreferredAffsOrAnyJob: - cmd = "GET2 wnode_aff=1 any_aff=1"; - break; + return "GET2 wnode_aff=1 any_aff=1"; case CNetScheduleExecutor::ePreferredAffinities: - cmd = "GET2 wnode_aff=1 any_aff=0"; - break; + return "GET2 wnode_aff=1 any_aff=0"; case CNetScheduleExecutor::eClaimNewPreferredAffs: - cmd = "GET2 wnode_aff=1 any_aff=0 exclusive_new_aff=1"; - break; + return "GET2 wnode_aff=1 any_aff=0 exclusive_new_aff=1"; case CNetScheduleExecutor::eAnyJob: - cmd = "GET2 wnode_aff=0 any_aff=1"; - break; + return "GET2 wnode_aff=0 any_aff=1"; - case CNetScheduleExecutor::eExplicitAffinitiesOnly: - cmd = "GET2 wnode_aff=0 any_aff=0"; + default: + return "GET2 wnode_aff=0 any_aff=0"; } +} + +string CNetScheduleNotificationHandler::MkBaseGETCmd( + CNetScheduleExecutor::EJobAffinityPreference affinity_preference, + const string& affinity_list) +{ + string cmd(s_GET2(affinity_preference)); if (!affinity_list.empty()) { list affinity_tokens; diff --git a/c++/src/connect/services/netschedule_api_getjob.cpp b/c++/src/connect/services/netschedule_api_getjob.cpp index 16b5fb55..f6262f87 100644 --- a/c++/src/connect/services/netschedule_api_getjob.cpp +++ b/c++/src/connect/services/netschedule_api_getjob.cpp @@ -1,4 +1,4 @@ -/* $Id: netschedule_api_getjob.cpp 476303 2015-08-17 19:03:16Z sadyrovr $ +/* $Id: netschedule_api_getjob.cpp 518714 2016-11-07 18:04:33Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -64,19 +64,6 @@ typedef list TServers; typedef list TTimeline; typedef TTimeline::iterator TIterator; -// TODO: This can be replaced by lambda after we migrate to C++11 -template -struct SEntryHasMoreJobs -{ - TImpl& impl; - SEntryHasMoreJobs(TImpl& i) : impl(i) {} - - bool operator()(const CNetScheduleGetJob::SEntry& entry) - { - return impl.MoreJobs(entry); - } -}; - template class CAnyAffinityJob { @@ -92,7 +79,7 @@ public: void Interrupt() {} TIterator Begin() { return m_Timeline.begin(); } TIterator Next(bool) { return m_Timeline.begin(); } - const string& Affinity(bool&) const { return kEmptyStr; } + const string& Affinity() const { return kEmptyStr; } bool Done() { return true; } bool HasJob() const { return false; } @@ -151,7 +138,7 @@ public: return ++ret; } - const string& Affinity(bool& all_affinities) const + const string& Affinity() const { // Must not happen, since otherwise Done() has returned true already _ASSERT(m_JobPriority); @@ -161,11 +148,9 @@ public: if (HasJob()) { // Only affinities that are higher that current job's one - all_affinities = false; return affinity_ladder[m_JobPriority - 1].second; } else { // All affinities - all_affinities = true; return affinity_ladder.back().second; } } @@ -196,10 +181,18 @@ public: } } while (priority-- > 0); - // Should not happen - LOG_POST(Error << "Got a job " << job.job_id << - " with unexpected affinity " << job.affinity); - m_JobPriority = numeric_limits::max(); + // Whether affinities not from the ladder are allowed + if (m_GetJobImpl.m_API->m_AffinityPreference == + CNetScheduleExecutor::eAnyJob) { + // Make it the least-priority + m_JobPriority = affinity_ladder.size(); + } else { + // Should not happen + LOG_POST(Error << "Got a job " << job.job_id << + " with unexpected affinity " << job.affinity); + m_JobPriority = numeric_limits::max(); + } + return false; } @@ -253,11 +246,11 @@ CNetScheduleGetJob::EResult CNetScheduleGetJobImpl::GetJobImmediately(TJo try { // Get prioritized affinity list and - // a flag whether the list contains all possible affinities - bool all_affinities = true; - const string& prio_aff_list(holder.Affinity(all_affinities)); + // a flag whether any affinity job is appropriate + const string& prio_aff_list = holder.Affinity(); + const bool any_affinity = !holder.HasJob(); - if (m_Impl.CheckEntry(*i, prio_aff_list, + if (m_Impl.CheckEntry(*i, prio_aff_list, any_affinity, holder.job, holder.job_status)) { if (i == m_ImmediateActions.begin()) { increment = true; @@ -280,7 +273,7 @@ CNetScheduleGetJob::EResult CNetScheduleGetJobImpl::GetJobImmediately(TJo // No job has been returned by this server; // query the server later. i->deadline = CDeadline(m_Impl.m_Timeout, 0); - i->all_affinities = all_affinities; + i->all_affinities_checked = any_affinity; m_ScheduledActions.splice(m_ScheduledActions.end(), m_ImmediateActions, i); } @@ -329,9 +322,13 @@ CNetScheduleGetJob::EResult CNetScheduleGetJobImpl::GetJobImpl( return ret; } + auto entry_has_more_jobs = [&](const SEntry& entry) { + return m_Impl.MoreJobs(entry); + }; + // If MoreJobs() returned false for all entries of m_ScheduledActions if (find_if(m_ScheduledActions.begin(), m_ScheduledActions.end(), - SEntryHasMoreJobs(m_Impl)) == m_ScheduledActions.end()) { + entry_has_more_jobs) == m_ScheduledActions.end()) { return eNoJobs; } @@ -444,7 +441,7 @@ void CNetScheduleGetJobImpl::ReturnNotFullyCheckedServers() TIterator i = m_ScheduledActions.begin(); while (i != m_ScheduledActions.end()) { - if (i->all_affinities) { + if (i->all_affinities_checked) { ++i; } else { m_ImmediateActions.splice(m_ImmediateActions.end(), diff --git a/c++/src/connect/services/netschedule_api_getjob.hpp b/c++/src/connect/services/netschedule_api_getjob.hpp index 13e68e76..67fafd7d 100644 --- a/c++/src/connect/services/netschedule_api_getjob.hpp +++ b/c++/src/connect/services/netschedule_api_getjob.hpp @@ -1,7 +1,7 @@ #ifndef CONN_SERVICES___NETSCHEDULE_API_GETJOB__HPP #define CONN_SERVICES___NETSCHEDULE_API_GETJOB__HPP -/* $Id: netschedule_api_getjob.hpp 476303 2015-08-17 19:03:16Z sadyrovr $ +/* $Id: netschedule_api_getjob.hpp 518714 2016-11-07 18:04:33Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -70,13 +70,13 @@ struct CNetScheduleGetJob { SServerAddress server_address; CDeadline deadline; - bool all_affinities; + bool all_affinities_checked; bool more_jobs; SEntry(const SServerAddress& a, bool j = true) : server_address(a), deadline(0, 0), - all_affinities(true), + all_affinities_checked(true), more_jobs(j) { } diff --git a/c++/src/connect/services/netschedule_api_impl.hpp b/c++/src/connect/services/netschedule_api_impl.hpp index 52e37dba..b3d14ee3 100644 --- a/c++/src/connect/services/netschedule_api_impl.hpp +++ b/c++/src/connect/services/netschedule_api_impl.hpp @@ -1,7 +1,7 @@ #ifndef CONN_SERVICES___NETSCHEDULE_API_IMPL__HPP #define CONN_SERVICES___NETSCHEDULE_API_IMPL__HPP -/* $Id: netschedule_api_impl.hpp 498273 2016-04-14 17:59:04Z ivanov $ +/* $Id: netschedule_api_impl.hpp 518714 2016-11-07 18:04:33Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -150,20 +150,22 @@ private: enum EMode { fWnCompatible = (0 << 0), fNonWnCompatible = (1 << 0), - fConfigLoading = (1 << 1) | fNonWnCompatible, + fConfigLoading = (1 << 1), + fWorkerNode = fWnCompatible, + fNetSchedule = fNonWnCompatible, }; typedef int TMode; -public: - CNetScheduleServerListener() : - m_ClientType(CNetScheduleAPI::eCT_Auto), - m_Mode(fConfigLoading) + static TMode GetMode(bool wn, bool try_config) { + if (wn) return fWorkerNode; + if (try_config) return fNetSchedule | fConfigLoading; + return fNetSchedule; } - CNetScheduleServerListener(bool wn_compatible) : - m_ClientType(CNetScheduleAPI::eCT_Auto), - m_Mode(wn_compatible ? fWnCompatible : fNonWnCompatible) +public: + CNetScheduleServerListener(bool wn, bool try_config) : + m_Mode(GetMode(wn, try_config)) { } @@ -194,7 +196,7 @@ public: // preferred affinities from two threads. CFastMutex m_AffinitySubmissionMutex; - CNetScheduleAPI::EClientType m_ClientType; + CNetScheduleAPI::EClientType m_ClientType = CNetScheduleAPI::eCT_Auto; private: const TMode m_Mode; @@ -282,10 +284,7 @@ struct SNetScheduleAPIImpl : public CObject { SNetScheduleAPIImpl(CConfig* config, const string& section, const string& service_name, const string& client_name, - const string& queue_name); - - SNetScheduleAPIImpl(const string& service_name, const string& client_name, - const string& queue_name, bool wn_compatible); + const string& queue_name, bool wn = false, bool try_config = true); // Special constructor for CNetScheduleAPI::GetServer(). SNetScheduleAPIImpl(SNetServerInPool* server, SNetScheduleAPIImpl* parent); @@ -362,6 +361,7 @@ struct SNetScheduleAPIImpl : public CObject void UseOldStyleAuth(); void SetAuthParam(const string& param_name, const string& param_value); CCompoundIDPool GetCompoundIDPool() { return m_CompoundIDPool; } + void InitAffinities(CConfig* config, const string& section); CNetService m_Service; @@ -399,7 +399,7 @@ struct SNetScheduleSubmitterImpl : public CObject { SNetScheduleSubmitterImpl(CNetScheduleAPI::TInstance ns_api_impl); - string SubmitJobImpl(CNetScheduleJob& job, unsigned short udp_port, + string SubmitJobImpl(CNetScheduleNewJob& job, unsigned short udp_port, unsigned wait_time, CNetServer* server = NULL); void FinalizeRead(const char* cmd_start, @@ -440,14 +440,10 @@ struct SNetScheduleExecutorImpl : public CObject string MkSETAFFCmd(); bool ExecGET(SNetServerImpl* server, const string& get_cmd, CNetScheduleJob& job); - bool x_GetJobWithAffinityList(SNetServerImpl* server, - const CDeadline* timeout, - CNetScheduleJob& job, - CNetScheduleExecutor::EJobAffinityPreference affinity_preference, - const string& affinity_list); bool x_GetJobWithAffinityLadder(SNetServerImpl* server, const CDeadline& timeout, const string& prio_aff_list, + bool any_affinity, CNetScheduleJob& job); void ExecWithOrWithoutRetry(const CNetScheduleJob& job, const string& cmd); @@ -537,6 +533,7 @@ private: bool CheckEntry( SEntry& entry, const string& prio_aff_list, + bool any_affinity, CNetScheduleJob& job, CNetScheduleAPI::EJobStatus* job_status); void ReturnJob(CNetScheduleJob& job); diff --git a/c++/src/connect/services/netschedule_api_reader.cpp b/c++/src/connect/services/netschedule_api_reader.cpp index 63be99ee..36b9e123 100644 --- a/c++/src/connect/services/netschedule_api_reader.cpp +++ b/c++/src/connect/services/netschedule_api_reader.cpp @@ -1,4 +1,4 @@ -/* $Id: netschedule_api_reader.cpp 492591 2016-02-18 19:23:34Z ivanov $ +/* $Id: netschedule_api_reader.cpp 518714 2016-11-07 18:04:33Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -102,6 +102,7 @@ static bool s_ParseReadJobResponse(const string& response, bool SNetScheduleJobReaderImpl::CImpl::CheckEntry( SEntry& entry, const string& prio_aff_list, + bool any_affinity, CNetScheduleJob& job, CNetScheduleAPI::EJobStatus* job_status) { @@ -116,7 +117,16 @@ bool SNetScheduleJobReaderImpl::CImpl::CheckEntry( cmd.append(m_Affinity); } else if (!prio_aff_list.empty()) { prioritized_aff = true; - cmd.append("any_aff=0 aff="); + + // Ask for any affinity only when requested and configured + // (it's not requested when we have a job already). + if (any_affinity && + m_API->m_AffinityPreference == CNetScheduleExecutor::eAnyJob) { + cmd.append("any_aff=1 aff="); + } else { + cmd.append("any_aff=0 aff="); + } + cmd.append(prio_aff_list); } else { cmd.append("any_aff=1"); diff --git a/c++/src/connect/services/netschedule_api_submitter.cpp b/c++/src/connect/services/netschedule_api_submitter.cpp index cbe974a2..e1b66404 100644 --- a/c++/src/connect/services/netschedule_api_submitter.cpp +++ b/c++/src/connect/services/netschedule_api_submitter.cpp @@ -1,4 +1,4 @@ -/* $Id: netschedule_api_submitter.cpp 492602 2016-02-18 19:27:34Z ivanov $ +/* $Id: netschedule_api_submitter.cpp 507304 2016-07-18 16:15:49Z sadyrovr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -47,7 +47,7 @@ BEGIN_NCBI_SCOPE #define FORCED_SST_INTERVAL_NANOSEC 500 * 1000 * 1000 ////////////////////////////////////////////////////////////////////////////// -static void s_SerializeJob(string& cmd, const CNetScheduleJob& job, +static void s_SerializeJob(string& cmd, const CNetScheduleNewJob& job, unsigned short udp_port, unsigned wait_time) { cmd.push_back('"'); @@ -82,12 +82,12 @@ void static s_CheckInputSize(const string& input, size_t max_input_size) } } -string CNetScheduleSubmitter::SubmitJob(CNetScheduleJob& job) +string CNetScheduleSubmitter::SubmitJob(CNetScheduleNewJob& job) { return m_Impl->SubmitJobImpl(job, 0, 0); } -string SNetScheduleSubmitterImpl::SubmitJobImpl(CNetScheduleJob& job, +string SNetScheduleSubmitterImpl::SubmitJobImpl(CNetScheduleNewJob& job, unsigned short udp_port, unsigned wait_time, CNetServer* server) { size_t max_input_size = m_API->GetServerParams().max_input_size; diff --git a/c++/src/connect/services/netservice_api.cpp b/c++/src/connect/services/netservice_api.cpp index 1fdf3d52..edfbae33 100644 --- a/c++/src/connect/services/netservice_api.cpp +++ b/c++/src/connect/services/netservice_api.cpp @@ -1,4 +1,4 @@ -/* $Id: netservice_api.cpp 497256 2016-04-05 15:59:16Z ivanov $ +/* $Id: netservice_api.cpp 512527 2016-08-31 18:05:30Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -419,7 +419,8 @@ void SNetServiceImpl::Init(CObject* api_impl, const string& service_name, m_ServiceName = service_name; NStr::TruncateSpacesInPlace(m_ServiceName); - if (config) { + // Do not override explicitly set client name + if (config && m_ClientName.empty()) { m_ClientName = config->GetString(section, "client_name", CConfig::eErr_NoThrow); diff --git a/c++/src/connect/services/netservice_api_impl.hpp b/c++/src/connect/services/netservice_api_impl.hpp index 520a1f32..5c50460b 100644 --- a/c++/src/connect/services/netservice_api_impl.hpp +++ b/c++/src/connect/services/netservice_api_impl.hpp @@ -1,7 +1,7 @@ #ifndef CONNECT_SERVICES___NETSERVICE_API_IMPL__HPP #define CONNECT_SERVICES___NETSERVICE_API_IMPL__HPP -/* $Id: netservice_api_impl.hpp 497257 2016-04-05 15:59:52Z ivanov $ +/* $Id: netservice_api_impl.hpp 497092 2016-04-04 15:52:44Z sadyrovr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/connect/services/netstorage.cpp b/c++/src/connect/services/netstorage.cpp index 2dc0645c..9c3a6c68 100644 --- a/c++/src/connect/services/netstorage.cpp +++ b/c++/src/connect/services/netstorage.cpp @@ -1,4 +1,4 @@ -/* $Id: netstorage.cpp 499028 2016-04-21 15:25:58Z ivanov $ +/* $Id: netstorage.cpp 505978 2016-06-30 15:57:38Z sadyrovr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -159,9 +159,9 @@ CNetStorageObject CNetStorage::Open(const string& object_loc, } string CNetStorage::Relocate(const string& object_loc, - TNetStorageFlags flags) + TNetStorageFlags flags, TNetStorageProgressCb cb) { - return m_Impl->Relocate(object_loc, flags); + return m_Impl->Relocate(object_loc, flags, cb); } bool CNetStorage::Exists(const string& object_loc) @@ -189,10 +189,11 @@ CNetStorageObject CNetStorageByKey::Open(const string& unique_key, } string CNetStorageByKey::Relocate(const string& unique_key, - TNetStorageFlags flags, TNetStorageFlags old_flags) + TNetStorageFlags flags, TNetStorageFlags old_flags, + TNetStorageProgressCb cb) { SNetStorage::SLimits::Check(unique_key); - return m_Impl->Relocate(unique_key, flags, old_flags); + return m_Impl->Relocate(unique_key, flags, old_flags, cb); } bool CNetStorageByKey::Exists(const string& key, TNetStorageFlags flags) diff --git a/c++/src/connect/services/netstorage_direct_nc.cpp b/c++/src/connect/services/netstorage_direct_nc.cpp index 8bae92f7..2a44199f 100644 --- a/c++/src/connect/services/netstorage_direct_nc.cpp +++ b/c++/src/connect/services/netstorage_direct_nc.cpp @@ -1,4 +1,4 @@ -/* $Id: netstorage_direct_nc.cpp 493320 2016-02-25 19:43:11Z ivanov $ +/* $Id: netstorage_direct_nc.cpp 504524 2016-06-15 23:50:37Z sadyrovr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -220,7 +220,10 @@ void SNetStorage_NetCacheBlob::SetExpiration(const CTimeout& ttl) ": infinite ttl for NetCache blobs is not implemented"); } - m_NetCacheAPI.ProlongBlobLifetime(m_BlobKey, (unsigned)ttl.GetAsDouble()); + try { + m_NetCacheAPI.ProlongBlobLifetime(m_BlobKey, (unsigned)ttl.GetAsDouble()); + } + NETSTORAGE_CONVERT_NETCACHEEXCEPTION("on setting ttl " + m_BlobKey) } string SNetStorage_NetCacheBlob::FileTrack_Path() diff --git a/c++/src/connect/services/netstorage_direct_nc.hpp b/c++/src/connect/services/netstorage_direct_nc.hpp index 2db4425b..146b3daf 100644 --- a/c++/src/connect/services/netstorage_direct_nc.hpp +++ b/c++/src/connect/services/netstorage_direct_nc.hpp @@ -1,7 +1,7 @@ #ifndef CONNECT_SERVICES__NETSTORAGE_DIRECT_NC__HPP #define CONNECT_SERVICES__NETSTORAGE_DIRECT_NC__HPP -/* $Id: netstorage_direct_nc.hpp 493320 2016-02-25 19:43:11Z ivanov $ +/* $Id: netstorage_direct_nc.hpp 493146 2016-02-24 17:38:53Z sadyrovr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/connect/services/netstorage_rpc.cpp b/c++/src/connect/services/netstorage_rpc.cpp index ed5179d4..54f6bfb5 100644 --- a/c++/src/connect/services/netstorage_rpc.cpp +++ b/c++/src/connect/services/netstorage_rpc.cpp @@ -1,4 +1,4 @@ -/* $Id: netstorage_rpc.cpp 499028 2016-04-21 15:25:58Z ivanov $ +/* $Id: netstorage_rpc.cpp 505978 2016-06-30 15:57:38Z sadyrovr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -756,7 +756,7 @@ CNetStorageObject SNetStorageRPC::Create(TNetStorageFlags flags) m_UseNextSubHitID.ProperCommand(); CJsonNode request(MkStdRequest("CREATE")); - x_SetStorageFlags(request, flags); + x_SetStorageFlags(request, GetFlags(flags)); CNetServerConnection conn; @@ -765,7 +765,7 @@ CNetStorageObject SNetStorageRPC::Create(TNetStorageFlags flags) return new SNetStorageObjectRPC(this, request, conn, SNetStorageObjectRPC::eByGeneratedID, - object_loc, flags, SNetStorageObjectRPC::eWriting); + object_loc, 0, SNetStorageObjectRPC::eWriting); } CNetStorageObject SNetStorageRPC::Open(const string& object_loc) @@ -779,7 +779,7 @@ CNetStorageObject SNetStorageRPC::Open(const string& object_loc) } string SNetStorageRPC::Relocate(const string& object_loc, - TNetStorageFlags flags) + TNetStorageFlags flags, TNetStorageProgressCb /*cb*/) { if (x_NetCacheMode(object_loc)) NCBI_THROW_FMT(CNetStorageException, eNotSupported, object_loc << @@ -794,6 +794,8 @@ string SNetStorageRPC::Relocate(const string& object_loc, request.SetByKey("NewLocation", new_location); + // TODO: CXX-8302 + return Exchange(GetServiceFromLocator(object_loc), request).GetString("ObjectLoc"); } @@ -808,8 +810,15 @@ bool SNetStorageRPC::Exists(const string& object_loc) CJsonNode request(MkObjectRequest("EXISTS", object_loc)); - return Exchange(GetServiceFromLocator(object_loc), - request).GetBoolean("Exists"); + try { + return Exchange(GetServiceFromLocator(object_loc), + request).GetBoolean("Exists"); + } + catch (CNetStorageException& e) { + if (e.GetErrCode() != CNetStorageException::eExpired) throw; + } + + return false; } ENetStorageRemoveResult SNetStorageRPC::Remove(const string& object_loc) @@ -828,10 +837,18 @@ ENetStorageRemoveResult SNetStorageRPC::Remove(const string& object_loc) m_UseNextSubHitID.ProperCommand(); CJsonNode request(MkObjectRequest("DELETE", object_loc)); - CJsonNode response(Exchange(GetServiceFromLocator(object_loc), request)); - CJsonNode not_found(response.GetByKeyOrNull("NotFound")); - return not_found && not_found.AsBoolean() ? eNSTRR_NotFound : eNSTRR_Removed; + try { + CJsonNode response(Exchange(GetServiceFromLocator(object_loc), request)); + CJsonNode not_found(response.GetByKeyOrNull("NotFound")); + + return not_found && not_found.AsBoolean() ? eNSTRR_NotFound : eNSTRR_Removed; + } + catch (CNetStorageException& e) { + if (e.GetErrCode() != CNetStorageException::eExpired) throw; + } + + return eNSTRR_NotFound; } class CJsonOverUTTPExecHandler : public INetServerExecHandler @@ -967,7 +984,7 @@ CJsonNode SNetStorageRPC::MkObjectRequest(const string& request_type, user_key.SetString("UniqueID", unique_key); new_request.SetByKey("UserKey", user_key); - x_SetStorageFlags(new_request, flags); + x_SetStorageFlags(new_request, GetFlags(flags)); return new_request; } @@ -1416,12 +1433,13 @@ struct SNetStorageByKeyRPC : public SNetStorageByKeyImpl TNetStorageFlags default_flags); virtual CNetStorageObject Open(const string& unique_key, - TNetStorageFlags flags = 0); + TNetStorageFlags flags); virtual string Relocate(const string& unique_key, - TNetStorageFlags flags, TNetStorageFlags old_flags = 0); - virtual bool Exists(const string& key, TNetStorageFlags flags = 0); + TNetStorageFlags flags, TNetStorageFlags old_flags, + TNetStorageProgressCb cb); + virtual bool Exists(const string& key, TNetStorageFlags flags); virtual ENetStorageRemoveResult Remove(const string& key, - TNetStorageFlags flags = 0); + TNetStorageFlags flags); #ifdef NCBI_GRID_XSITE_CONN_SUPPORT void AllowXSiteConnections() { m_NetStorageRPC->AllowXSiteConnections(); } @@ -1450,7 +1468,8 @@ CNetStorageObject SNetStorageByKeyRPC::Open(const string& unique_key, } string SNetStorageByKeyRPC::Relocate(const string& unique_key, - TNetStorageFlags flags, TNetStorageFlags old_flags) + TNetStorageFlags flags, TNetStorageFlags old_flags, + TNetStorageProgressCb /*cb*/) { m_NetStorageRPC->m_UseNextSubHitID.ProperCommand(); CJsonNode request(m_NetStorageRPC->MkObjectRequest( @@ -1462,6 +1481,8 @@ string SNetStorageByKeyRPC::Relocate(const string& unique_key, request.SetByKey("NewLocation", new_location); + // TODO: CXX-8302 + return m_NetStorageRPC->Exchange(m_NetStorageRPC->m_Service, request).GetString("ObjectLoc"); } @@ -1470,8 +1491,15 @@ bool SNetStorageByKeyRPC::Exists(const string& key, TNetStorageFlags flags) { CJsonNode request(m_NetStorageRPC->MkObjectRequest("EXISTS", key, flags)); - return m_NetStorageRPC->Exchange(m_NetStorageRPC->m_Service, - request).GetBoolean("Exists"); + try { + return m_NetStorageRPC->Exchange(m_NetStorageRPC->m_Service, + request).GetBoolean("Exists"); + } + catch (CNetStorageException& e) { + if (e.GetErrCode() != CNetStorageException::eExpired) throw; + } + + return false; } ENetStorageRemoveResult SNetStorageByKeyRPC::Remove(const string& key, @@ -1480,12 +1508,19 @@ ENetStorageRemoveResult SNetStorageByKeyRPC::Remove(const string& key, m_NetStorageRPC->m_UseNextSubHitID.ProperCommand(); CJsonNode request(m_NetStorageRPC->MkObjectRequest("DELETE", key, flags)); - CJsonNode response( - m_NetStorageRPC->Exchange(m_NetStorageRPC->m_Service, request)); + try { + CJsonNode response( + m_NetStorageRPC->Exchange(m_NetStorageRPC->m_Service, request)); + + CJsonNode not_found(response.GetByKeyOrNull("NotFound")); - CJsonNode not_found(response.GetByKeyOrNull("NotFound")); + return not_found && not_found.AsBoolean() ? eNSTRR_NotFound : eNSTRR_Removed; + } + catch (CNetStorageException& e) { + if (e.GetErrCode() != CNetStorageException::eExpired) throw; + } - return not_found && not_found.AsBoolean() ? eNSTRR_NotFound : eNSTRR_Removed; + return eNSTRR_NotFound; } struct SNetStorageAdminImpl : public CObject diff --git a/c++/src/connect/services/netstorage_rpc.hpp b/c++/src/connect/services/netstorage_rpc.hpp index 7903a54b..83c2a699 100644 --- a/c++/src/connect/services/netstorage_rpc.hpp +++ b/c++/src/connect/services/netstorage_rpc.hpp @@ -1,7 +1,7 @@ #ifndef CONNECT_SERVICES__NETSTORAGE_RPC__HPP #define CONNECT_SERVICES__NETSTORAGE_RPC__HPP -/* $Id: netstorage_rpc.hpp 499028 2016-04-21 15:25:58Z ivanov $ +/* $Id: netstorage_rpc.hpp 505978 2016-06-30 15:57:38Z sadyrovr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -44,9 +44,10 @@ struct SNetStorageRPC : public SNetStorageImpl { SNetStorageRPC(const TConfig& config, TNetStorageFlags default_flags); - virtual CNetStorageObject Create(TNetStorageFlags flags = 0); + virtual CNetStorageObject Create(TNetStorageFlags flags); virtual CNetStorageObject Open(const string& object_loc); - virtual string Relocate(const string& object_loc, TNetStorageFlags flags); + virtual string Relocate(const string& object_loc, TNetStorageFlags flags, + TNetStorageProgressCb cb); virtual bool Exists(const string& object_loc); virtual ENetStorageRemoveResult Remove(const string& object_loc); @@ -80,7 +81,15 @@ struct SNetStorageRPC : public SNetStorageImpl return service; } + TNetStorageFlags GetFlags(TNetStorageFlags flags) const + { + return flags ? flags : m_DefaultFlags; + } + +private: TNetStorageFlags m_DefaultFlags; + +public: CNetService m_Service; const TConfig m_Config; diff --git a/c++/src/connect/services/netstorageobjectinfo.cpp b/c++/src/connect/services/netstorageobjectinfo.cpp index 09d2a75c..672d0fe7 100644 --- a/c++/src/connect/services/netstorageobjectinfo.cpp +++ b/c++/src/connect/services/netstorageobjectinfo.cpp @@ -1,4 +1,4 @@ -/* $Id: netstorageobjectinfo.cpp 499845 2016-04-28 16:13:50Z ivanov $ +/* $Id: netstorageobjectinfo.cpp 516423 2016-10-13 14:58:14Z sadyrovr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -129,11 +129,22 @@ private: template <> CTime SLazyInitData::GetTime() { - const char* const kISO8601TimeFormat = "Y-M-DTh:m:s.ro"; - if (st_info) { if (CJsonNode ctime = st_info.GetByKeyOrNull("ctime")) { - return CTime(ctime.AsString(), kISO8601TimeFormat).ToLocalTime(); + const string ctime_string = ctime.AsString(); + + // TODO: + // Remove code related to old format after + // all NetStorage servers upgraded to contain CXX-8230. + try { + return CTime(ctime_string, "Y-M-DTh:m:s.rZ").ToLocalTime(); + } + catch (CTimeException& ex) { + if (ex.GetErrCode() != CTimeException::eFormat) throw; + + // Try old format. + return CTime(ctime_string, "Y-M-DTh:m:s.ro").ToLocalTime(); + } } } diff --git a/c++/src/connect/services/netstorageobjectloc.cpp b/c++/src/connect/services/netstorageobjectloc.cpp index 11062aaa..f3a91cff 100644 --- a/c++/src/connect/services/netstorageobjectloc.cpp +++ b/c++/src/connect/services/netstorageobjectloc.cpp @@ -1,4 +1,4 @@ -/* $Id: netstorageobjectloc.cpp 499845 2016-04-28 16:13:50Z ivanov $ +/* $Id: netstorageobjectloc.cpp 499705 2016-04-27 17:58:55Z sadyrovr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/connect/services/ns_output_parser.cpp b/c++/src/connect/services/ns_output_parser.cpp index c34c8b31..71777ee0 100644 --- a/c++/src/connect/services/ns_output_parser.cpp +++ b/c++/src/connect/services/ns_output_parser.cpp @@ -1,4 +1,4 @@ -/* $Id: ns_output_parser.cpp 479861 2015-09-23 21:07:21Z sadyrovr $ +/* $Id: ns_output_parser.cpp 502215 2016-05-23 15:27:45Z sadyrovr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -36,246 +36,6 @@ BEGIN_NCBI_SCOPE -#define INVALID_FORMAT_ERROR() \ - NCBI_THROW2(CStringException, eFormat, \ - (*m_Ch == '\0' ? "Unexpected end of NetSchedule output" : \ - "Syntax error in structured NetSchedule output"), \ - GetPosition()) - -CJsonNode CNetScheduleStructuredOutputParser::ParseJSON(const string& json) -{ - m_Ch = (m_NSOutput = json).c_str(); - - while (isspace((unsigned char) *m_Ch)) - ++m_Ch; - - CJsonNode root; - - switch (*m_Ch) { - case '[': - ++m_Ch; - root = ParseArray(']'); - break; - - case '{': - ++m_Ch; - root = ParseObject('}'); - break; - - default: - INVALID_FORMAT_ERROR(); - } - - while (isspace((unsigned char) *m_Ch)) - ++m_Ch; - - if (*m_Ch != '\0') { - INVALID_FORMAT_ERROR(); - } - - return root; -} - -string CNetScheduleStructuredOutputParser::ParseString(size_t max_len) -{ - size_t len; - string val(NStr::ParseQuoted(CTempString(m_Ch, max_len), &len)); - - m_Ch += len; - return val; -} - -Int8 CNetScheduleStructuredOutputParser::ParseInt(size_t len) -{ - Int8 val = NStr::StringToInt8(CTempString(m_Ch, len)); - - if (*m_Ch == '-') { - ++m_Ch; - --len; - } - if (*m_Ch == '0' && len > 1) { - NCBI_THROW2(CStringException, eFormat, - "Leading zeros are not allowed", GetPosition()); - } - - m_Ch += len; - return val; -} - -double CNetScheduleStructuredOutputParser::ParseDouble(size_t len) -{ - double val = NStr::StringToDouble(CTempString(m_Ch, len)); - - m_Ch += len; - return val; -} - -bool CNetScheduleStructuredOutputParser::MoreNodes() -{ - while (isspace((unsigned char) *m_Ch)) - ++m_Ch; - if (*m_Ch != ',') - return false; - while (isspace((unsigned char) *++m_Ch)) - ; - return true; -} - -CJsonNode CNetScheduleStructuredOutputParser::ParseObject(char closing_char) -{ - CJsonNode result(CJsonNode::NewObjectNode()); - - while (isspace((unsigned char) *m_Ch)) - ++m_Ch; - - if (*m_Ch == closing_char) { - ++m_Ch; - return result; - } - - while (*m_Ch == '\'' || *m_Ch == '"') { - // New attribute/value pair - string attr_name(ParseString(GetRemainder())); - - while (isspace((unsigned char) *m_Ch)) - ++m_Ch; - if (*m_Ch == ':' || *m_Ch == '=') - while (isspace((unsigned char) *++m_Ch)) - ; - - result.SetByKey(attr_name, ParseValue()); - - if (!MoreNodes()) { - if (*m_Ch != closing_char) - break; - ++m_Ch; - return result; - } - } - - INVALID_FORMAT_ERROR(); -} - -CJsonNode CNetScheduleStructuredOutputParser::ParseArray(char closing_char) -{ - CJsonNode result(CJsonNode::NewArrayNode()); - - while (isspace((unsigned char) *m_Ch)) - ++m_Ch; - - if (*m_Ch == closing_char) { - ++m_Ch; - return result; - } - - do - result.Append(ParseValue()); - while (MoreNodes()); - - if (*m_Ch == closing_char) { - ++m_Ch; - return result; - } - - INVALID_FORMAT_ERROR(); -} - -CJsonNode CNetScheduleStructuredOutputParser::ParseValue() -{ - size_t max_len = GetRemainder(); - size_t len = 0; - - switch (*m_Ch) { - /* Array */ - case '[': - ++m_Ch; - return ParseArray(']'); - - /* Object */ - case '{': - ++m_Ch; - return ParseObject('}'); - - /* String */ - case '\'': - case '"': - return CJsonNode::NewStringNode(ParseString(max_len)); - - /* Number */ - case '-': - // Check that there's at least one digit after the minus sign. - if (max_len <= 1 || !isdigit((unsigned char) m_Ch[1])) { - ++m_Ch; - break; - } - len = 1; - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - // Skim through the integer part. - do - if (++len >= max_len) - return CJsonNode::NewIntegerNode(ParseInt(len)); - while (isdigit((unsigned char) m_Ch[len])); - - // Stumbled upon a non-digit character -- check - // if it's a fraction part or an exponent part. - switch (m_Ch[len]) { - case '.': - if (++len == max_len || !isdigit((unsigned char) m_Ch[len])) { - NCBI_THROW2(CStringException, eFormat, - "At least one digit after the decimal " - "point is required", GetPosition()); - } - for (;;) { - if (++len == max_len) - return CJsonNode::NewDoubleNode(ParseDouble(len)); - - if (!isdigit((unsigned char) m_Ch[len])) { - if (m_Ch[len] == 'E' || m_Ch[len] == 'e') - break; - - return CJsonNode::NewDoubleNode(ParseDouble(len)); - } - } - /* FALL THROUGH */ - - case 'E': - case 'e': - if (++len == max_len || - (m_Ch[len] == '-' || m_Ch[len] == '+' ? - ++len == max_len || - !isdigit((unsigned char) m_Ch[len]) : - !isdigit((unsigned char) m_Ch[len]))) { - m_Ch += len; - NCBI_THROW2(CStringException, eFormat, - "Invalid exponent specification", GetPosition()); - } - while (++len < max_len && isdigit((unsigned char) m_Ch[len])) - ; - return CJsonNode::NewDoubleNode(ParseDouble(len)); - - default: - return CJsonNode::NewIntegerNode(ParseInt(len)); - } - - /* Constant */ - case 'F': case 'f': case 'N': case 'n': - case 'T': case 't': case 'Y': case 'y': - while (len <= max_len && isalpha((unsigned char) m_Ch[len])) - ++len; - - { - CTempString val(m_Ch, len); - m_Ch += len; - return val == "null" ? CJsonNode::NewNullNode() : - CJsonNode::NewBooleanNode(NStr::StringToBool(val)); - } - } - - INVALID_FORMAT_ERROR(); -} - CAttrListParser::ENextAttributeType CAttrListParser::NextAttribute( CTempString* attr_name, string* attr_value, size_t* attr_column) { diff --git a/c++/src/connect/services/srv_connections.cpp b/c++/src/connect/services/srv_connections.cpp index 990256b4..45f91d98 100644 --- a/c++/src/connect/services/srv_connections.cpp +++ b/c++/src/connect/services/srv_connections.cpp @@ -1,4 +1,4 @@ -/* $Id: srv_connections.cpp 495142 2016-03-15 14:04:30Z ivanov $ +/* $Id: srv_connections.cpp 494943 2016-03-11 20:01:22Z sadyrovr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/connect/services/tmp_wn_info.cpp b/c++/src/connect/services/tmp_wn_info.cpp index 13c63c4f..1c5762a6 100644 --- a/c++/src/connect/services/tmp_wn_info.cpp +++ b/c++/src/connect/services/tmp_wn_info.cpp @@ -1,4 +1,4 @@ -/* $Id: tmp_wn_info.cpp 486255 2015-12-02 17:51:03Z sadyrovr $ +/* $Id: tmp_wn_info.cpp 504536 2016-06-16 12:42:34Z kazimird $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -124,13 +124,19 @@ CJsonNode g_GetWorkerNodeInfo(CNetScheduleAPI api) s_GetWorkerNodes(api, worker_nodes); ITERATE(list, wn_info, worker_nodes) { - CNetScheduleAPI wn_api(wn_info->host + ':' + - NStr::NumericToString(wn_info->port), - api->m_Service->GetClientName(), - kEmptyStr); - - result.SetByKey(wn_info->prog, s_WorkerNodeInfoToJson( - wn_api.GetService().Iterate().GetServer())); + string wn_address = wn_info->host + ':' + + NStr::NumericToString(wn_info->port); + try { + CNetScheduleAPI wn_api(wn_address, + api->m_Service->GetClientName(), + kEmptyStr); + + result.SetByKey(wn_info->prog, s_WorkerNodeInfoToJson( + wn_api.GetService().Iterate().GetServer())); + } + catch (CException& e) { + LOG_POST(Error << e); + } } return result; diff --git a/c++/src/connect/services/wn_main_loop.cpp b/c++/src/connect/services/wn_main_loop.cpp index 37b58f4d..1cc2c710 100644 --- a/c++/src/connect/services/wn_main_loop.cpp +++ b/c++/src/connect/services/wn_main_loop.cpp @@ -1,4 +1,4 @@ -/* $Id: wn_main_loop.cpp 489744 2016-01-15 16:50:24Z sadyrovr $ +/* $Id: wn_main_loop.cpp 518714 2016-11-07 18:04:33Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -702,12 +702,13 @@ bool CMainLoopThread::CImpl::MoreJobs(const SEntry& /*entry*/) bool CMainLoopThread::CImpl::CheckEntry( SEntry& entry, const string& prio_aff_list, + bool any_affinity, CNetScheduleJob& job, CNetScheduleAPI::EJobStatus* /*job_status*/) { CNetServer server(m_API.GetService()->GetServer(entry.server_address)); return m_WorkerNode->m_NSExecutor->x_GetJobWithAffinityLadder(server, - m_Timeout, prio_aff_list, job); + m_Timeout, prio_aff_list, any_affinity, job); } void CMainLoopThread::CImpl::ReturnJob(CNetScheduleJob& job) diff --git a/c++/src/corelib/ddumpable.cpp b/c++/src/corelib/ddumpable.cpp index 12c92d32..7dc2f26b 100644 --- a/c++/src/corelib/ddumpable.cpp +++ b/c++/src/corelib/ddumpable.cpp @@ -1,4 +1,4 @@ -/* $Id: ddumpable.cpp 493118 2016-02-24 15:43:33Z ivanov $ +/* $Id: ddumpable.cpp 493042 2016-02-23 19:38:23Z gouriano $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/corelib/env_reg.cpp b/c++/src/corelib/env_reg.cpp index a90dc98a..ce503b57 100644 --- a/c++/src/corelib/env_reg.cpp +++ b/c++/src/corelib/env_reg.cpp @@ -1,4 +1,4 @@ -/* $Id: env_reg.cpp 495404 2016-03-17 13:28:04Z ivanov $ +/* $Id: env_reg.cpp 507064 2016-07-14 15:29:09Z elisovdn $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -247,7 +247,7 @@ bool CEnvironmentRegistry::x_Set(const string& section, const string& name, bool CEnvironmentRegistry::x_Unset(const string& section, const string& name, - TFlags flags) + TFlags /*flags*/) { bool result = false; ITERATE (TPriorityMap, it, m_PriorityMap) { @@ -346,6 +346,7 @@ bool CNcbiEnvRegMapper::EnvToReg(const string& env, string& section, if (uu_pos == NPOS || uu_pos == env.size() - 2) { return false; } + /* Parse section and entry names from the variable */ if (env[kPfxLen] == '_') { // regular entry section = env.substr(kPfxLen + 1, uu_pos - kPfxLen - 1); name = env.substr(uu_pos + 2); @@ -355,6 +356,14 @@ bool CNcbiEnvRegMapper::EnvToReg(const string& env, string& section, name[0] = '.'; section = env.substr(uu_pos + 2); } + if (!IRegistry::IsNameSection(section, 0)) { + LOG_POST(Info << "Invalid registry section name in environment " + "variable " << env); + } + if (!IRegistry::IsNameEntry(name, 0)) { + LOG_POST(Info << "Invalid registry entry name in environment " + "variable " << env); + } NStr::ReplaceInPlace(section, "_DOT_", "."); NStr::ReplaceInPlace(name, "_DOT_", "."); return true; diff --git a/c++/src/corelib/expr.cpp b/c++/src/corelib/expr.cpp index 69d5056c..8fd323c9 100644 --- a/c++/src/corelib/expr.cpp +++ b/c++/src/corelib/expr.cpp @@ -1,4 +1,4 @@ -/* $Id: expr.cpp 408848 2013-08-02 13:32:46Z ivanov $ +/* $Id: expr.cpp 500405 2016-05-04 15:18:35Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -779,7 +779,7 @@ void CExprParser::Parse(const char* str) } } - int n_args = 1; + n_args = 1; while (sm_lpr[m_OStack[m_o_sp-1]] >= sm_rpr[oper]) { int cop = m_OStack[--m_o_sp]; diff --git a/c++/src/corelib/ncbi_cookies.cpp b/c++/src/corelib/ncbi_cookies.cpp index b7843d7f..03863b68 100644 --- a/c++/src/corelib/ncbi_cookies.cpp +++ b/c++/src/corelib/ncbi_cookies.cpp @@ -1,4 +1,4 @@ -/* $Id: ncbi_cookies.cpp 486111 2015-12-01 17:17:39Z grichenk $ +/* $Id: ncbi_cookies.cpp 517040 2016-10-20 11:22:39Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -80,7 +80,6 @@ CHttpCookie::CHttpCookie(const CTempString& name, const CTempString& path) : m_Name(name), m_Value(value), - m_Domain(domain), m_Path(path), m_Expires(CTime::eEmpty, CTime::eGmt), m_Secure(false), @@ -89,6 +88,7 @@ CHttpCookie::CHttpCookie(const CTempString& name, m_Accessed(CTime::eCurrent, CTime::eGmt), m_HostOnly(false) { + SetDomain(domain); // store canonical domain if ( m_Name.empty() ) { NCBI_THROW(CHttpCookieException, eValue, "Empty cookie name"); } @@ -469,9 +469,10 @@ bool CHttpCookie::Parse(const CTempString& str) m_Secure = false; m_HttpOnly = false; m_Extension.clear(); + m_HostOnly = false; + // Update the creation and access time to current. m_Created.SetCurrent(); m_Accessed.SetCurrent(); - m_HostOnly = false; string err_msg; size_t pos = str.find(';'); @@ -502,10 +503,6 @@ bool CHttpCookie::Parse(const CTempString& str) m_Value = m_Value.substr(1, m_Value.size() - 2); } - // Update the creation and access time. - m_Created.SetCurrent(); - m_Accessed.SetCurrent(); - if ( attr_str.empty() ) { return true; } @@ -525,7 +522,8 @@ bool CHttpCookie::Parse(const CTempString& str) // Assume all values are valid. If they are not, exception // will be thrown on an attempt to write the cookie. if ( NStr::EqualNocase(name, "domain") ) { - m_Domain = NStr::ToLower(value); + m_Domain = value; + NStr::ToLower(m_Domain); if ( NStr::EndsWith(m_Domain, '.') ) { // Ignore domain if it ends with '.' m_Domain.clear(); @@ -637,7 +635,7 @@ bool CHttpCookie::MatchDomain(const string& host) const return host == m_Domain; } size_t pos = h.find(m_Domain); - // Domain matching: cookie_domain must be identical to host, + // Domain matching: cookie domain must be identical to host, // or be a suffix of host and the last char before the suffix // must be '.'. if (pos == NPOS || diff --git a/c++/src/corelib/ncbi_param.cpp b/c++/src/corelib/ncbi_param.cpp index f585f0b9..d9dc4740 100644 --- a/c++/src/corelib/ncbi_param.cpp +++ b/c++/src/corelib/ncbi_param.cpp @@ -1,4 +1,4 @@ -/* $Id: ncbi_param.cpp 468199 2015-05-21 13:10:41Z grichenk $ +/* $Id: ncbi_param.cpp 500405 2016-05-04 15:18:35Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -164,10 +164,10 @@ bool NCBI_XNCBI_EXPORT g_GetConfigFlag(const char* section, CMutexGuard guard(CNcbiApplication::GetInstanceMutex()); CNcbiApplication* app = CNcbiApplication::Instance(); if ( app && app->HasLoadedConfig() ) { - const string& str = app->GetConfig().Get(section, variable); - if ( !str.empty() ) { + const string& s = app->GetConfig().Get(section, variable); + if ( !s.empty() ) { try { - bool value = s_StringToBool(str); + bool value = s_StringToBool(s); #ifdef _DEBUG if ( is_config_dump ) { s_ConfigDump = value; @@ -228,16 +228,16 @@ int NCBI_XNCBI_EXPORT g_GetConfigInt(const char* section, if ( s_CanDumpConfig() ) { if ( section && *section ) { DUMP_CONFIG(11, "NCBI_CONFIG: int variable" - " [" << section << "]" - " " << variable << - " = " << value << - " from env var " << + " [" << section << "]" + " " << variable << + " = " << value << + " from env var " << s_GetEnvVarName(section, variable, env_var_name)); } else { DUMP_CONFIG(12, "NCBI_CONFIG: int variable " - " " << variable << - " = " << value << + " " << variable << + " = " << value << " from env var"); } } @@ -253,16 +253,16 @@ int NCBI_XNCBI_EXPORT g_GetConfigInt(const char* section, CMutexGuard guard(CNcbiApplication::GetInstanceMutex()); CNcbiApplication* app = CNcbiApplication::Instance(); if ( app && app->HasLoadedConfig() ) { - const string& str = app->GetConfig().Get(section, variable); - if ( !str.empty() ) { + const string& s = app->GetConfig().Get(section, variable); + if ( !s.empty() ) { try { - int value = NStr::StringToInt(str); + int value = NStr::StringToInt(s); #ifdef _DEBUG if ( s_CanDumpConfig() ) { DUMP_CONFIG(10, "NCBI_CONFIG: int variable" - " [" << section << "]" - " " << variable << - " = " << value << + " [" << section << "]" + " " << variable << + " = " << value << " from registry"); } #endif @@ -338,18 +338,18 @@ double NCBI_XNCBI_EXPORT g_GetConfigDouble(const char* section, CMutexGuard guard(CNcbiApplication::GetInstanceMutex()); CNcbiApplication* app = CNcbiApplication::Instance(); if ( app && app->HasLoadedConfig() ) { - const string& str = app->GetConfig().Get(section, variable); - if ( !str.empty() ) { + const string& s = app->GetConfig().Get(section, variable); + if ( !s.empty() ) { try { - double value = NStr::StringToDouble(str, + double value = NStr::StringToDouble(s, NStr::fDecimalPosixOrLocal | NStr::fAllowLeadingSpaces | NStr::fAllowTrailingSpaces); #ifdef _DEBUG if ( s_CanDumpConfig() ) { DUMP_CONFIG(10, "NCBI_CONFIG: double variable" - " [" << section << "]" - " " << variable << - " = " << value << + " [" << section << "]" + " " << variable << + " = " << value << " from registry"); } #endif @@ -417,18 +417,18 @@ string NCBI_XNCBI_EXPORT g_GetConfigString(const char* section, CMutexGuard guard(CNcbiApplication::GetInstanceMutex()); CNcbiApplication* app = CNcbiApplication::Instance(); if ( app && app->HasLoadedConfig() ) { - const string& value = app->GetConfig().Get(section, variable); - if ( !value.empty() ) { + const string& v = app->GetConfig().Get(section, variable); + if ( !v.empty() ) { #ifdef _DEBUG if ( s_CanDumpConfig() ) { DUMP_CONFIG(15, "NCBI_CONFIG: str variable" - " [" << section << "]" - " " << variable << + " [" << section << "]" + " " << variable << " = \"" << value << "\"" " from registry"); } #endif - return value; + return v; } } } diff --git a/c++/src/corelib/ncbi_stack.cpp b/c++/src/corelib/ncbi_stack.cpp index a79b67ac..bad71b4f 100644 --- a/c++/src/corelib/ncbi_stack.cpp +++ b/c++/src/corelib/ncbi_stack.cpp @@ -1,4 +1,4 @@ -/* $Id: ncbi_stack.cpp 463583 2015-03-30 18:05:28Z vasilche $ +/* $Id: ncbi_stack.cpp 500861 2016-05-09 16:32:20Z grichenk $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -58,8 +58,15 @@ BEGIN_NCBI_SCOPE string CStackTrace::SStackFrameInfo::AsString(void) const { - return module + " " + file + ":" + NStr::UInt8ToString(line) + " " + func + - " offset=0x" + NStr::UInt8ToString(offs, 0, 16); + return module + " " + file + ":" + NStr::NumericToString(line) + " " + func + + " offset=0x" + NStr::NumericToString(offs, 0, 16) + +// On Windows PtrToString does not add 0x prefix, while on Linux it does. +#if defined NCBI_OS_MSWIN + " addr=0x" + +#else + " addr=" + +#endif + NStr::PtrToString(addr); } diff --git a/c++/src/corelib/ncbi_stack_linux.cpp b/c++/src/corelib/ncbi_stack_linux.cpp index bfbe2823..c6dafb76 100644 --- a/c++/src/corelib/ncbi_stack_linux.cpp +++ b/c++/src/corelib/ncbi_stack_linux.cpp @@ -1,4 +1,4 @@ -/* $Id: ncbi_stack_linux.cpp 488254 2015-12-29 13:56:26Z ivanov $ +/* $Id: ncbi_stack_linux.cpp 500861 2016-05-09 16:32:20Z grichenk $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -80,7 +80,14 @@ void CStackTraceImpl::Expand(CStackTrace::TStack& stack) info.offs = 0; info.line = 0; - string::size_type pos = sym.find_first_of("("); + string::size_type pos = sym.find_last_of("["); + if (pos != string::npos) { + string::size_type epos = sym.find_first_of("]", pos + 1); + if (epos != string::npos) { + info.addr = NStr::StringToPtr(sym.substr(pos + 1, epos - pos - 1)); + } + } + pos = sym.find_first_of("("); if (pos != string::npos) { info.module = sym.substr(0, pos); sym.erase(0, pos + 1); diff --git a/c++/src/corelib/ncbi_stack_solaris.cpp b/c++/src/corelib/ncbi_stack_solaris.cpp index 2be75354..20a00f99 100644 --- a/c++/src/corelib/ncbi_stack_solaris.cpp +++ b/c++/src/corelib/ncbi_stack_solaris.cpp @@ -1,4 +1,4 @@ -/* $Id: ncbi_stack_solaris.cpp 104013 2007-05-15 19:27:33Z grichenk $ +/* $Id: ncbi_stack_solaris.cpp 500861 2016-05-09 16:32:20Z grichenk $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -65,7 +65,7 @@ extern "C" int s_StackWalker(uintptr_t int_ptr, int, void* data) { CStackTrace::TStack* stack_trace = (CStackTrace::TStack*)data; - CStackTrace::SStackFrameInfo sf_info; + CStackTrace::SStackFrameInfo sf_info((void*)int_ptr); Dl_info info; if (dladdr((void*)int_ptr, &info)) { sf_info.func = info.dli_sname; diff --git a/c++/src/corelib/ncbi_stack_win32.cpp b/c++/src/corelib/ncbi_stack_win32.cpp index 234f805f..b69b5753 100644 --- a/c++/src/corelib/ncbi_stack_win32.cpp +++ b/c++/src/corelib/ncbi_stack_win32.cpp @@ -1,4 +1,4 @@ -/* $Id: ncbi_stack_win32.cpp 403742 2013-06-18 15:26:09Z grichenk $ +/* $Id: ncbi_stack_win32.cpp 500861 2016-05-09 16:32:20Z grichenk $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -538,7 +538,7 @@ void CStackTraceImpl::Expand(CStackTrace::TStack& stack) try { ITERATE(TStack, it, m_Stack) { - CStackTrace::SStackFrameInfo sf_info; + CStackTrace::SStackFrameInfo sf_info((void*)it->AddrPC.Offset); sf_info.func = ""; if ( !SymGetSymFromAddr(curr_proc, diff --git a/c++/src/corelib/ncbi_stack_win64.cpp b/c++/src/corelib/ncbi_stack_win64.cpp index a14ef554..5ce5a55e 100644 --- a/c++/src/corelib/ncbi_stack_win64.cpp +++ b/c++/src/corelib/ncbi_stack_win64.cpp @@ -1,4 +1,4 @@ -/* $Id: ncbi_stack_win64.cpp 456287 2015-01-09 14:29:15Z grichenk $ +/* $Id: ncbi_stack_win64.cpp 500861 2016-05-09 16:32:20Z grichenk $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -416,7 +416,7 @@ void CStackTraceImpl::Expand(CStackTrace::TStack& stack) try { ITERATE(TStack, it, m_Stack) { - CStackTrace::SStackFrameInfo sf_info; + CStackTrace::SStackFrameInfo sf_info((void*)it->AddrPC.Offset); sf_info.func = ""; if ( !SymGetSymFromAddr64(curr_proc, it->AddrPC.Offset, &offs64, pSym) ) { diff --git a/c++/src/corelib/ncbi_system.cpp b/c++/src/corelib/ncbi_system.cpp index 2e26c1ec..f01663b4 100644 --- a/c++/src/corelib/ncbi_system.cpp +++ b/c++/src/corelib/ncbi_system.cpp @@ -1,4 +1,4 @@ -/* $Id: ncbi_system.cpp 488254 2015-12-29 13:56:26Z ivanov $ +/* $Id: ncbi_system.cpp 500405 2016-05-04 15:18:35Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -1084,7 +1084,12 @@ extern void SuppressSystemMessageBox(TSuppressSystemMessageBox mode) SetUnhandledExceptionFilter(_SEH_Handler); } s_DoneSuppressSystemMessageBox = true; -#endif //NCBI_OS_MSWIN + +#else + // dummy, to avoid compilation warning + mode = 0; + +#endif } diff --git a/c++/src/corelib/ncbi_url.cpp b/c++/src/corelib/ncbi_url.cpp index d96e61e5..4e9101b3 100644 --- a/c++/src/corelib/ncbi_url.cpp +++ b/c++/src/corelib/ncbi_url.cpp @@ -1,4 +1,4 @@ -/* $Id: ncbi_url.cpp 500588 2016-05-05 17:18:11Z ivanov $ +/* $Id: ncbi_url.cpp 518082 2016-10-31 17:19:46Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -337,6 +337,8 @@ CUrl& CUrl::operator=(const CUrl& url) m_OrigArgs = url.m_OrigArgs; if ( url.m_ArgsList.get() ) { m_ArgsList.reset(new CUrlArgs(*url.m_ArgsList)); + } else { + m_ArgsList.reset(); } } return *this; diff --git a/c++/src/corelib/ncbiapp.cpp b/c++/src/corelib/ncbiapp.cpp index 6f674300..6ab34acc 100644 --- a/c++/src/corelib/ncbiapp.cpp +++ b/c++/src/corelib/ncbiapp.cpp @@ -1,4 +1,4 @@ -/* $Id: ncbiapp.cpp 492326 2016-02-16 19:38:11Z ivanov $ +/* $Id: ncbiapp.cpp 518670 2016-11-07 15:25:48Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -39,6 +39,9 @@ #include #include #include +#ifdef HAVE_COMMON_NCBI_BUILD_VER_H +# include +#endif #include "ncbisys.hpp" #if defined(NCBI_OS_MSWIN) @@ -101,7 +104,8 @@ CNcbiApplication* CNcbiApplication::Instance(void) CNcbiApplication::CNcbiApplication(const SBuildInfo& build_info) : m_ConfigLoaded(false), - m_LogFile(0) + m_LogFile(0), + m_LogOptions(0) { // Initialize UID and start timer GetDiagContext().GetUID(); @@ -328,6 +332,118 @@ void CNcbiApplication::x_TryInit(EAppDiagStream diag, } } +#define NCBI_LOG_PARAM(type,Name,NAME) \ +/* Logging of environment variables: space separated list of names which \ + should be logged after each request start. */\ +NCBI_PARAM_DECL (type, Log, LogApp ## Name); \ +NCBI_PARAM_DEF_EX(type, Log, LogApp ## Name, false, \ + eParam_NoThread, DIAG_LOG_APP_ ## NAME); \ +typedef NCBI_PARAM_TYPE(Log, LogApp ## Name) TLogApp ## Name; + + +NCBI_LOG_PARAM(bool, Environment, ENVIRONMENT) +NCBI_LOG_PARAM(bool, EnvironmentOnStop, ENVIRONMENT_ON_STOP) +NCBI_LOG_PARAM(bool, Registry, REGISTRY) +NCBI_LOG_PARAM(bool, RegistryOnStop, REGISTRY_ON_STOP) +NCBI_LOG_PARAM(bool, Arguments, ARGUMENTS) +NCBI_LOG_PARAM(bool, Path, PATH) +NCBI_LOG_PARAM(bool, RunContext, RUN_CONTEXT) + + +enum ELogOptionsEvent { + eStartEvent = 0x01, ///< right before AppMain() + eStopEvent = 0x02, ///< right after AppMain() + eOtherEvent = 0x03 ///< any case is fine +}; + + +/// Flags to switch what to log +enum ELogOptions { + fLogAppEnvironment = 0x01, ///< log app environment on app start + fLogAppEnvironmentStop = 0x02, ///< log app environment on app stop + fLogAppRegistry = 0x04, ///< log app registry on app start + fLogAppRegistryStop = 0x08, ///< log app registry on app stop + fLogAppArguments = 0x10, ///< log app arguments + fLogAppPath = 0x20, ///< log app executable path +}; + + +void CNcbiApplication::x_ReadLogOptions() +{ + /* Log all */ + if ( TLogAppRunContext::GetDefault() ) { + m_LogOptions = 0x7f; // all on + return; + } + + /* Log registry */ + m_LogOptions |= TLogAppRegistry::GetDefault() ? fLogAppRegistry : 0; + m_LogOptions |= + TLogAppRegistryOnStop::GetDefault() ? fLogAppRegistryStop : 0; + + /* Log environment */ + m_LogOptions |= TLogAppEnvironment::GetDefault() ? fLogAppEnvironment : 0; + m_LogOptions |= + TLogAppEnvironmentOnStop::GetDefault() ? fLogAppEnvironmentStop : 0; + + /* Log arguments */ + m_LogOptions |= TLogAppArguments::GetDefault() ? fLogAppArguments : 0; + + /* Log path */ + m_LogOptions |= TLogAppPath::GetDefault() ? fLogAppPath : 0; +} + + +void CNcbiApplication::x_LogOptions(int /*ELogOptionsEvent*/ event) +{ + // Print environment values + if ( (m_LogOptions & fLogAppEnvironment && event & eStartEvent) || + (m_LogOptions & fLogAppEnvironmentStop && event & eStopEvent) ) { + CDiagContext_Extra extra = GetDiagContext().Extra(); + extra.Print("LogAppEnvironment", "true"); + list env_keys; + const CNcbiEnvironment& env = GetEnvironment(); + env.Enumerate(env_keys); + ITERATE(list, it, env_keys) { + const string& val = env.Get(*it); + extra.Print(*it, val); + } + } + + // Print registry values + if ( (m_LogOptions & fLogAppRegistry && event & eStartEvent) || + (m_LogOptions & fLogAppRegistryStop && event & eStopEvent) ) { + CDiagContext_Extra extra = GetDiagContext().Extra(); + extra.Print("LogAppRegistry", "true"); + list reg_sections; + const CNcbiRegistry& reg = GetConfig(); + reg.EnumerateSections(®_sections); + ITERATE(list, it, reg_sections) { + string section, name; + list section_entries; + reg.EnumerateEntries(*it, §ion_entries); + ITERATE(list, it_entry, section_entries) { + const string& val = reg.Get(*it, *it_entry); + string path = "[" + *it + "]" + *it_entry; + extra.Print(path, val); + } + } + } + + if ( m_LogOptions & fLogAppArguments && event & eStartEvent) { + CDiagContext_Extra extra = GetDiagContext().Extra(); + extra.Print("LogAppArguments", "true"); + string args_str; + extra.Print("Arguments", GetArgs().Print(args_str)); + } + + if ( m_LogOptions & fLogAppPath && event & eStartEvent) { + CDiagContext_Extra extra = GetDiagContext().Extra(); + extra.Print("LogAppPath", "true"); + extra.Print("Path", GetProgramExecutablePath()); + } +} + void CNcbiApplication::x_TryMain(EAppDiagStream diag, const char* conf, @@ -378,7 +494,8 @@ void CNcbiApplication::x_TryMain(EAppDiagStream diag, } *exit_code = 0; } - + x_ReadLogOptions(); + x_LogOptions(eStartEvent); // Run application if (*exit_code == 1) { GetDiagContext().SetGlobalAppState(eDiagAppState_AppRun); @@ -405,6 +522,7 @@ void CNcbiApplication::x_TryMain(EAppDiagStream diag, *exit_code = m_DryRun ? DryRun() : Run(); } } + x_LogOptions(eStopEvent); GetDiagContext().SetGlobalAppState(eDiagAppState_AppEnd); // Close application @@ -745,6 +863,24 @@ void CNcbiApplication::SetEnvironment(const string& name, const string& value) SetEnvironment().Set(name, value); } +void CNcbiApplication::SetVersionByBuild(int major) +{ + int minor = +#if defined(NCBI_SC_VERSION) + NCBI_SC_VERSION; +#else + 0; +#endif + int build_num = +#if defined(NCBI_TEAMCITY_BUILD_NUMBER) + NCBI_TEAMCITY_BUILD_NUMBER; +#else + 0; +#endif + + SetVersion(CVersionInfo(major, minor, build_num)); +} + void CNcbiApplication::SetVersion(const CVersionInfo& version) { diff --git a/c++/src/corelib/ncbiargs.cpp b/c++/src/corelib/ncbiargs.cpp index bc775092..9bb0822b 100644 --- a/c++/src/corelib/ncbiargs.cpp +++ b/c++/src/corelib/ncbiargs.cpp @@ -1,4 +1,4 @@ -/* $Id: ncbiargs.cpp 488569 2015-12-31 21:35:10Z vakatov $ +/* $Id: ncbiargs.cpp 500405 2016-05-04 15:18:35Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -2396,6 +2396,10 @@ void CArgDescriptions::AddNegatedFlagAlias(const string& alias, arg.release(); } +void CArgDescriptions::AddDependencyGroup(CArgDependencyGroup* dep_group) +{ + m_DependencyGroups.insert( CConstRef(dep_group)); +} void CArgDescriptions::SetConstraint(const string& name, const CArgAllow* constraint, @@ -3055,6 +3059,11 @@ void CArgDescriptions::x_PostCheck(CArgs& args, def_args.push_back(&arg); } + for (set< CConstRef >::const_iterator i = m_DependencyGroups.begin(); + i != m_DependencyGroups.end(); ++i) { + i->GetPointer()->Evaluate(args); + } + // Set default values (if available) for the arguments not defined // in the command line. ITERATE (list, it, def_args) { @@ -3582,6 +3591,15 @@ void CArgDescriptions::CPrintUsage::AddDetails(list& arr) const arr.push_back("OPTIONAL ARGUMENTS"); arr.splice(arr.end(), opt); } + + if (!m_desc.m_DependencyGroups.empty()) { + arr.push_back(kEmptyStr); + arr.push_back("DEPENDENCY GROUPS"); + for (set< CConstRef >::const_iterator i = m_desc.m_DependencyGroups.begin(); + i != m_desc.m_DependencyGroups.end(); ++i) { + i->GetPointer()->PrintUsage(arr, 0); + } + } } string& CArgDescriptions::PrintUsage(string& str, bool detailed) const @@ -3611,7 +3629,7 @@ string& CArgDescriptions::PrintUsage(string& str, bool detailed) const } CArgDescriptions::CPrintUsageXml::CPrintUsageXml(const CArgDescriptions& desc, CNcbiOstream& out) - : m_out(out) + : m_desc(desc), m_out(out) { m_out << "" << endl; m_out << "<" << "ncbi_application xmlns=\"ncbi:application\"" << endl @@ -3713,6 +3731,11 @@ void CArgDescriptions::CPrintUsageXml::PrintArguments(const CArgDescriptions& de } m_out << "" << endl; } + + for (set< CConstRef >::const_iterator i = m_desc.m_DependencyGroups.begin(); + i != m_desc.m_DependencyGroups.end(); ++i) { + i->GetPointer()->PrintUsageXml(m_out); + } m_out << "" << endl; } @@ -3973,25 +3996,25 @@ string& CCommandArgDescriptions::PrintUsage(string& str, bool detailed) const if ((m_Cmd_req & eNoSortGroups)==0) { cmdgroups.sort(); } - ITERATE( list, g, cmdgroups) { + ITERATE( list, gi, cmdgroups) { string grouptitle; bool titleprinted = false; - if (g->empty()) { + if (gi->empty()) { grouptitle = "Commands"; } else { - grouptitle = *g; + grouptitle = *gi; } - size_t group = x_GetCommandGroupIndex(*g); - ITERATE( list, d, cmds) { - map::const_iterator j = m_Groups.find(*d); + size_t group = x_GetCommandGroupIndex(*gi); + ITERATE( list, di, cmds) { + map::const_iterator j = m_Groups.find(*di); if (j != m_Groups.end() && j->second == group) { if (!titleprinted) { arr.push_back(kEmptyStr); arr.push_back(grouptitle + ":"); titleprinted = true; } - CPrintUsage y(*(m_Description.lower_bound(*d)->second)); - y.AddCommandDescription(arr, *d, &m_Aliases, max_cmd_len, detailed); + CPrintUsage y(*(m_Description.lower_bound(*di)->second)); + y.AddCommandDescription(arr, *di, &m_Aliases, max_cmd_len, detailed); } } ++group; @@ -3999,9 +4022,9 @@ string& CCommandArgDescriptions::PrintUsage(string& str, bool detailed) const } else { arr.push_back(kEmptyStr); arr.push_back("AVAILABLE COMMANDS:"); - ITERATE( list, d, cmds) { - CPrintUsage y(*(m_Description.find(*d)->second)); - y.AddCommandDescription(arr, *d, &m_Aliases, max_cmd_len, detailed); + ITERATE( list, di, cmds) { + CPrintUsage y(*(m_Description.find(*di)->second)); + y.AddCommandDescription(arr, *di, &m_Aliases, max_cmd_len, detailed); } } @@ -4022,6 +4045,7 @@ string& CCommandArgDescriptions::PrintUsage(string& str, bool detailed) const return str; } + void CCommandArgDescriptions::PrintUsageXml(CNcbiOstream& out) const { CPrintUsageXml x(*this,out); @@ -4597,6 +4621,236 @@ CArgAllow* CArgAllow_Doubles::Clone(void) const return clone; } + +///////////////////////////////////////////////////////////////////////////// + +CRef CArgDependencyGroup::Create( + const string& name, const string& description) +{ + CRef gr(new CArgDependencyGroup()); + gr->m_Name = name; + gr->m_Description = description; + return gr; +} + +CArgDependencyGroup::CArgDependencyGroup() + : m_MinMembers(0), m_MaxMembers(0) +{ +} + +CArgDependencyGroup::~CArgDependencyGroup(void) +{ +} + +CArgDependencyGroup& CArgDependencyGroup::SetMinMembers(size_t min_members) +{ + m_MinMembers = min_members; + return *this; +} + +CArgDependencyGroup& CArgDependencyGroup::SetMaxMembers(size_t max_members) +{ + m_MaxMembers = max_members; + return *this; +} + +CArgDependencyGroup& CArgDependencyGroup::Add(const string& arg_name, EInstantSet instant_set) +{ + m_Arguments[arg_name] = instant_set; + return *this; +} + +CArgDependencyGroup& CArgDependencyGroup::Add( + CArgDependencyGroup* dep_group, EInstantSet instant_set) +{ + m_Groups[ CConstRef(dep_group)] = instant_set; + return *this; +} + +void CArgDependencyGroup::Evaluate( const CArgs& args) const +{ + x_Evaluate(args, nullptr, nullptr); +} + +bool CArgDependencyGroup::x_Evaluate( const CArgs& args, string* arg_set, string* arg_unset) const +{ + bool top_level = !arg_set || !arg_unset; + bool has_instant_set = false; + size_t count_set = 0; + set names_set, names_unset; + string args_set, args_unset; + + for (map< CConstRef, EInstantSet>::const_iterator i = m_Groups.begin(); + i != m_Groups.end(); ++i) { + string msg_set, msg_unset; + if (i->first.GetPointer()->x_Evaluate(args, &msg_set, &msg_unset)) { + ++count_set; + has_instant_set = has_instant_set || (i->second == eInstantSet); + names_set.insert(msg_set); + } else { + names_unset.insert(msg_unset); + } + } + for (map::const_iterator i = m_Arguments.begin(); + i != m_Arguments.end(); ++i) { + if (args.Exist(i->first)) { + ++count_set; + has_instant_set = has_instant_set || (i->second == eInstantSet); + names_set.insert(i->first); + } else { + names_unset.insert(i->first); + } + } + size_t count_total = m_Groups.size() + m_Arguments.size(); + size_t count_max = m_MaxMembers != 0 ? m_MaxMembers : count_total; + + if (names_set.size() > 1) { + args_set = "(" + NStr::Join(names_set, ", ") + ")"; + } else if (names_set.size() == 1) { + args_set = *names_set.begin(); + } + + if (names_unset.size() > 1) { + args_unset = "(" + NStr::Join(names_unset, m_MinMembers <= 1 ? " | " : ", ") + ")"; + } else if (names_unset.size() == 1) { + args_unset = *names_unset.begin(); + } + + bool result = count_set != 0 || top_level; + if (result) { + if (count_set > count_max) { + string msg("Argument conflict: "); + msg += args_set + " may not be specified simultaneously"; + NCBI_THROW(CArgException, eConstraint, msg); + } + if (!has_instant_set && count_set < m_MinMembers) { + string msg("Argument has no value: "); + if (count_total != count_max) { + msg += (m_MinMembers - count_set > 1) ? "some" : "one"; + msg += " of "; + } + msg += args_unset + " must be specified"; + NCBI_THROW(CArgException,eNoValue, msg); + } + } + if (arg_set) { + *arg_set = args_set; + } + if (arg_unset) { + *arg_unset = args_unset; + } + return result; +} + +void CArgDependencyGroup::PrintUsage(list& arr, size_t offset) const +{ + arr.push_back(kEmptyStr); + string off(2*offset,' '); + string msg(off); + msg += m_Name + ": {"; + + bool first = true; + list instant; + for (map< CConstRef, EInstantSet>::const_iterator i = m_Groups.begin(); + i != m_Groups.end(); ++i) { + if (!first) { + msg += ","; + } + first = false; + msg += i->first.GetPointer()->m_Name; + if (i->second == eInstantSet) { + instant.push_back(i->first.GetPointer()->m_Name); + } + } + for (map::const_iterator i = m_Arguments.begin(); + i != m_Arguments.end(); ++i) { + if (!first) { + msg += ","; + } + first = false; + msg += i->first; + if (i->second == eInstantSet) { + instant.push_back(i->first); + } + } + msg += "}"; + arr.push_back(msg); + if (!m_Description.empty()) { + msg = off; + msg += m_Description; + arr.push_back(msg); + } + size_t count_total = m_Groups.size() + m_Arguments.size(); + size_t count_max = m_MaxMembers != 0 ? m_MaxMembers : count_total; + + msg = off + "in which "; + size_t count = m_MinMembers; + if (m_MinMembers == count_max) { + msg += "exactly "; + msg += NStr::NumericToString(m_MinMembers); + } else if (count_max == count_total && m_MinMembers != 0) { + msg += "at least "; + msg += NStr::NumericToString(m_MinMembers); + } else if (count_max != count_total && m_MinMembers == 0) { + msg += "no more than "; + msg += NStr::NumericToString(m_MaxMembers); + count = m_MaxMembers; + } else { + msg += NStr::NumericToString(m_MinMembers); + msg += " to "; + msg += NStr::NumericToString(m_MaxMembers); + count = m_MaxMembers; + } + msg += " element"; + if (count != 1) { + msg += "s"; + } + msg += " must be set"; + arr.push_back(msg); + + if (!instant.empty()) { + msg = off; + msg += "Instant set: "; + msg += NStr::Join(instant, ","); + arr.push_back(msg); + } + for (map< CConstRef, EInstantSet>::const_iterator i = m_Groups.begin(); + i != m_Groups.end(); ++i) { + i->first.GetPointer()->PrintUsage(arr, offset+1); + } +} + +void CArgDependencyGroup::PrintUsageXml(CNcbiOstream& out) const +{ + out << "<" << "dependencygroup" << ">" << endl; + out << "<" << "name" << ">" << m_Name << "" << endl; + out << "<" << "description" << ">" << m_Description << "" << endl; + + for (map< CConstRef, EInstantSet>::const_iterator i = m_Groups.begin(); + i != m_Groups.end(); ++i) { + out << "<" << "group"; + if (i->second == eInstantSet) { + out << " instantset=\"true\""; + } + out << ">" << i->first.GetPointer()->m_Name << "" << endl; + } + for (map::const_iterator i = m_Arguments.begin(); + i != m_Arguments.end(); ++i) { + out << "<" << "argument"; + if (i->second == eInstantSet) { + out << " instantset=\"true\""; + } + out << ">" << i->first << "" << endl; + } + out << "<" << "minmembers" << ">" << m_MinMembers << "" << endl; + out << "<" << "maxmembers" << ">" << m_MaxMembers << "" << endl; + for (map< CConstRef, EInstantSet>::const_iterator i = m_Groups.begin(); + i != m_Groups.end(); ++i) { + i->first.GetPointer()->PrintUsageXml(out); + } + out << "" << endl; +} + /////////////////////////////////////////////////////// // CArgException diff --git a/c++/src/corelib/ncbidiag.cpp b/c++/src/corelib/ncbidiag.cpp index 8d43805b..617bd3b6 100644 --- a/c++/src/corelib/ncbidiag.cpp +++ b/c++/src/corelib/ncbidiag.cpp @@ -1,4 +1,4 @@ -/* $Id: ncbidiag.cpp 500364 2016-05-04 12:04:46Z ivanov $ +/* $Id: ncbidiag.cpp 519554 2016-11-16 16:33:59Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -186,8 +186,13 @@ public: CTeeDiagHandler(CDiagHandler* orig, bool own_orig); virtual void Post(const SDiagMessage& mess); - // Don't post duplicates to console. - virtual void PostToConsole(const SDiagMessage& mess) {} + virtual void PostToConsole(const SDiagMessage& mess) + { + // Console manipulator ignores severity, so we have to always print + // the message to console and set NoTee flag to avoid duplicates. + CDiagHandler::PostToConsole(mess); + const_cast(mess).m_NoTee = true; + } virtual string GetLogName(void) { @@ -269,9 +274,43 @@ typedef NCBI_PARAM_TYPE(Diag, Log_Size_Limit) TLogSizeLimitParam; /////////////////////////////////////////////////////// // Output rate control parameters +class CLogRateLimit +{ +public: + typedef unsigned int TValue; + CLogRateLimit(void) : m_Value(kMax_UInt) {} + CLogRateLimit(TValue val) : m_Value(val) {} + + operator TValue(void) const + { + return m_Value; + } + + void Set(TValue val) + { + m_Value = val; + } + +private: + TValue m_Value; +}; + + +CNcbiIstream& operator>>(CNcbiIstream& in, CLogRateLimit& lim) +{ + lim.Set(kMax_UInt); + string s; + getline(in, s); + if ( !NStr::EqualNocase(s, "off") ) { + lim.Set(NStr::StringToNumeric(s)); + } + return in; +} + + // AppLog limit per period -NCBI_PARAM_DECL(unsigned int, Diag, AppLog_Rate_Limit); -NCBI_PARAM_DEF_EX(unsigned int, Diag, AppLog_Rate_Limit, 50000, +NCBI_PARAM_DECL(CLogRateLimit, Diag, AppLog_Rate_Limit); +NCBI_PARAM_DEF_EX(CLogRateLimit, Diag, AppLog_Rate_Limit, CLogRateLimit(50000), eParam_NoThread, DIAG_APPLOG_RATE_LIMIT); typedef NCBI_PARAM_TYPE(Diag, AppLog_Rate_Limit) TAppLogRateLimitParam; @@ -282,8 +321,8 @@ NCBI_PARAM_DEF_EX(unsigned int, Diag, AppLog_Rate_Period, 10, eParam_NoThread, typedef NCBI_PARAM_TYPE(Diag, AppLog_Rate_Period) TAppLogRatePeriodParam; // ErrLog limit per period -NCBI_PARAM_DECL(unsigned int, Diag, ErrLog_Rate_Limit); -NCBI_PARAM_DEF_EX(unsigned int, Diag, ErrLog_Rate_Limit, 5000, +NCBI_PARAM_DECL(CLogRateLimit, Diag, ErrLog_Rate_Limit); +NCBI_PARAM_DEF_EX(CLogRateLimit, Diag, ErrLog_Rate_Limit, CLogRateLimit(5000), eParam_NoThread, DIAG_ERRLOG_RATE_LIMIT); typedef NCBI_PARAM_TYPE(Diag, ErrLog_Rate_Limit) TErrLogRateLimitParam; @@ -294,8 +333,8 @@ NCBI_PARAM_DEF_EX(unsigned int, Diag, ErrLog_Rate_Period, 1, eParam_NoThread, typedef NCBI_PARAM_TYPE(Diag, ErrLog_Rate_Period) TErrLogRatePeriodParam; // TraceLog limit per period -NCBI_PARAM_DECL(unsigned int, Diag, TraceLog_Rate_Limit); -NCBI_PARAM_DEF_EX(unsigned int, Diag, TraceLog_Rate_Limit, 5000, +NCBI_PARAM_DECL(CLogRateLimit, Diag, TraceLog_Rate_Limit); +NCBI_PARAM_DEF_EX(CLogRateLimit, Diag, TraceLog_Rate_Limit, CLogRateLimit(5000), eParam_NoThread, DIAG_TRACELOG_RATE_LIMIT); typedef NCBI_PARAM_TYPE(Diag, TraceLog_Rate_Limit) TTraceLogRateLimitParam; @@ -369,8 +408,6 @@ NCBI_PARAM_DEF_EX(string, Log, LogRegistry, kEmptyStr, typedef NCBI_PARAM_TYPE(Log, LogRegistry) TLogRegistry; -// Are we using applog automatically (set by SetupDiag)? -static bool s_UsingAutoApplog = false; static bool s_FinishedSetupDiag = false; static bool s_MergeLinesSetBySetupDiag = false; @@ -1497,14 +1534,28 @@ CDiagContext::TUID CDiagContext::UpdateUID(TUID uid) const string CDiagContext::GetNextHitID(void) const { + return x_GetNextHitID(false); +} + + +string CDiagContext::x_GetNextHitID(bool is_default) const +{ + static CAtomicCounter s_HitIdCounter; + Uint8 hi = GetUID(); Uint4 b3 = Uint4((hi >> 32) & 0xFFFFFFFF); Uint4 b2 = Uint4(hi & 0xFFFFFFFF); CDiagContextThreadData& thr_data = CDiagContextThreadData::GetThreadData(); Uint8 tid = (thr_data.GetTID() & 0xFFFFFF) << 40; - Uint8 rid = Uint8(thr_data.GetRequestContext().GetRequestID() & 0xFFFFFF) << 16; - Uint8 us = (GetFastLocalTime().MicroSecond()/16) & 0xFFFF; + Uint8 rid; + if ( !is_default ) { + rid = ((Uint8)thr_data.GetRequestContext().GetRequestID() & 0xFFFFFF) << 16; + } + else { + rid = ((Uint8)0xFFFFFF) << 16; + } + Uint8 us = (Uint8)(s_HitIdCounter.Add(1) & 0xFFFF); Uint8 lo = tid | rid | us; Uint4 b1 = Uint4((lo >> 32) & 0xFFFFFFFF); Uint4 b0 = Uint4(lo & 0xFFFFFFFF); @@ -1514,6 +1565,12 @@ string CDiagContext::GetNextHitID(void) const } +string CDiagContext::GetDefaultHitID(void) const +{ + return x_GetDefaultHitID(eHitID_Create).GetHitId(); +} + + const string& CDiagContext::GetUsername(void) const { return m_Username->GetOriginalString(); @@ -2473,11 +2530,11 @@ void CDiagContext::x_LogHitID(void) const // Log the default hit id only when at application level. Otherwise // pospone it untill request-stop/app-stop. - if (m_LoggedHitId || !m_DefaultHitId.get() || m_DefaultHitId->empty() || + if (m_LoggedHitId || !m_DefaultHitId.get() || m_DefaultHitId->Empty() || !x_DiagAtApplicationLevel()) { return; } - Extra().Print(g_GetNcbiString(eNcbiStrings_PHID), *m_DefaultHitId); + Extra().Print(g_GetNcbiString(eNcbiStrings_PHID), m_DefaultHitId->GetHitId()); m_LoggedHitId = true; } @@ -2492,24 +2549,24 @@ void CDiagContext::x_LogHitID_WithLock(void) const bool CDiagContext::x_IsSetDefaultHitID(void) const { CFastMutexGuard guard(s_DefaultHidMutex); - return m_DefaultHitId.get() && !m_DefaultHitId->empty(); + return m_DefaultHitId.get() && !m_DefaultHitId->Empty(); } -string CDiagContext::x_GetDefaultHitID(EDefaultHitIDFlags flag) const +CSharedHitId CDiagContext::x_GetDefaultHitID(EDefaultHitIDFlags flag) const { CFastMutexGuard guard(s_DefaultHidMutex); - if (m_DefaultHitId.get() && !m_DefaultHitId->empty()) { + if (m_DefaultHitId.get() && !m_DefaultHitId->Empty()) { return *m_DefaultHitId; } if ( !m_DefaultHitId.get() ) { - m_DefaultHitId.reset(new string); + m_DefaultHitId.reset(new CSharedHitId()); } - if ( m_DefaultHitId->empty() ) { - *m_DefaultHitId = CRequestContext::SelectLastHitID( - TParamHttpHitId::GetDefault()); - if ( m_DefaultHitId->empty() ) { + if ( m_DefaultHitId->Empty() ) { + m_DefaultHitId->SetHitId(CRequestContext::SelectLastHitID( + TParamHttpHitId::GetDefault())); + if ( m_DefaultHitId->Empty() ) { string phid = CRequestContext::SelectLastHitID( TParamHitId::GetDefault()); if ( !phid.empty() ) { @@ -2546,12 +2603,14 @@ string CDiagContext::x_GetDefaultHitID(EDefaultHitIDFlags flag) const } } } - *m_DefaultHitId = phid; + m_DefaultHitId->SetHitId(phid); } - if (m_DefaultHitId->empty() && (flag == eHitID_Create)) { - *m_DefaultHitId = GetNextHitID(); + if (m_DefaultHitId->Empty() && (flag == eHitID_Create)) { + m_DefaultHitId->SetHitId(x_GetNextHitID(true)); } } + // Default hit id always uses shared sub-hit counter. + m_DefaultHitId->SetShared(); _ASSERT(!m_LoggedHitId); // Log hit id if at application level. x_LogHitID(); @@ -2563,9 +2622,11 @@ void CDiagContext::SetDefaultHitID(const string& hit_id) { CFastMutexGuard guard(s_DefaultHidMutex); if ( !m_DefaultHitId.get() ) { - m_DefaultHitId.reset(new string); + m_DefaultHitId.reset(new CSharedHitId()); } - *m_DefaultHitId = hit_id; + m_DefaultHitId->SetHitId(hit_id); + // Default hit id always uses shared sub-hit counter. + m_DefaultHitId->SetShared(); // Log new hit id when at application level. m_LoggedHitId = false; x_LogHitID(); @@ -2904,12 +2965,14 @@ void CDiagContext::DiscardMessages(void) // Diagnostics setup +static const char* kRootLog = "/log/"; + string GetDefaultLogLocation(CNcbiApplication& app) { static const char* kToolkitRcPath = "/etc/toolkitrc"; static const char* kWebDirToPort = "Web_dir_to_port"; - string log_path = "/log/"; + string log_path = kRootLog; string exe_path = CFile(app.GetProgramExecutablePath()).GetDir(); CNcbiIfstream is(kToolkitRcPath, ios::binary); @@ -2989,19 +3052,6 @@ void CDiagContext::x_FinalizeSetupDiag(void) } -// Helper function to set log file with forced splitting. -bool SetApplogFile(const string& file_name) -{ - bool old_split = s_UsingAutoApplog; - s_UsingAutoApplog = true; - bool res = SetLogFile(file_name); - if ( !res ) { - s_UsingAutoApplog = old_split; - } - return res; -} - - // Load string value from config if not null, or from the environment. static string s_GetLogConfigString(const CTempString name, const CTempString defval, @@ -3045,6 +3095,16 @@ void CDiagContext::SetupDiag(EAppDiagStream ds, const char* cmd_logfile) { CDiagLock lock(CDiagLock::eWrite); + + // Check severity level change status now. + // This used to be done in SetDiag(), but if the first logging event is an + // Extra(), new post format is enabled and post level is Trace, the initialization + // results in infinite recursion. To prevent this, call this as soon as possible, + // before any logging is done. + if ( CDiagBuffer::sm_PostSeverityChange == eDiagSC_Unknown ) { + CDiagBuffer::GetSeverityChangeEnabledFirstTime(); + } + CDiagContext& ctx = GetDiagContext(); // Initialize message collecting if (collect == eDCM_Init) { @@ -3053,8 +3113,6 @@ void CDiagContext::SetupDiag(EAppDiagStream ds, else if (collect == eDCM_InitNoLimit) { ctx.InitMessages(size_t(-1)); } - bool old_using_applog = s_UsingAutoApplog; - s_UsingAutoApplog = false; // Prevent splitting logs unless applog is used. /* The default order of checking possible log locations is: @@ -3186,6 +3244,12 @@ void CDiagContext::SetupDiag(EAppDiagStream ds, case eDS_ToStdlog: case eDS_Default: { + // When using applog, create separate log file for each + // user to avoid permission problems. + string euid; +#if defined(NCBI_OS_UNIX) + euid = "." + NStr::NumericToString(geteuid()); +#endif string log_base; string def_log_dir; {{ @@ -3197,12 +3261,12 @@ void CDiagContext::SetupDiag(EAppDiagStream ds, } }} if ( !log_base.empty() ) { - log_base = CFile(log_base).GetBase() + ".log"; + log_base = CFile(log_base).GetBase() + euid + ".log"; string log_name; // Try /log/ if ( !def_log_dir.empty() ) { log_name = CFile::ConcatPath(def_log_dir, log_base); - if ( SetApplogFile(log_name) ) { + if ( SetLogFile(log_name) ) { log_set = true; new_log_name = log_name; to_applog = true; @@ -3210,8 +3274,8 @@ void CDiagContext::SetupDiag(EAppDiagStream ds, } } // Try /log/srv if port is unknown or not writable - log_name = CFile::ConcatPath("/log/srv", log_base); - if ( SetApplogFile(log_name) ) { + log_name = CFile::ConcatPath(CFile::ConcatPath(kRootLog, "srv"), log_base); + if ( SetLogFile(log_name) ) { log_set = true; new_log_name = log_name; to_applog = true; @@ -3225,8 +3289,8 @@ void CDiagContext::SetupDiag(EAppDiagStream ds, break; } // Try to switch to /log/fallback/ - log_name = CFile::ConcatPath("/log/fallback/", log_base); - if ( SetApplogFile(log_name) ) { + log_name = CFile::ConcatPath(CFile::ConcatPath(kRootLog, "fallback"), log_base); + if ( SetLogFile(log_name) ) { log_set = true; new_log_name = log_name; to_applog = true; @@ -3234,7 +3298,8 @@ void CDiagContext::SetupDiag(EAppDiagStream ds, } // Try cwd/ for eDS_ToStdlog only if (ds == eDS_ToStdlog) { - log_name = CFile::ConcatPath(".", log_base); + // Don't include euid in file name when using cwd. + log_name = CFile::ConcatPath(".", CFile(log_base).GetBase() + ".log"); if ( SetLogFile(log_name, eDiagFile_All) ) { log_set = true; new_log_name = log_name; @@ -3253,17 +3318,17 @@ void CDiagContext::SetupDiag(EAppDiagStream ds, } } // No command line and no base name. - // Try to switch to /log/fallback/UNKNOWN + // Try to switch to /log/fallback/UNKNOWN. if (!log_set && log_base.empty()) { - static const char* kDefaultFallback = "/log/fallback/UNKNOWN"; - if ( SetApplogFile(kDefaultFallback) ) { + string default_fallback = CFile::ConcatPath(kRootLog, "fallback/UNKNOWN.log"); + if ( SetLogFile(default_fallback + euid) ) { log_set = true; - new_log_name = kDefaultFallback; + new_log_name = default_fallback; to_applog = true; break; } _TRACE_X(4, "Failed to set log file to " << - CFile::NormalizePath(kDefaultFallback)); + CFile::NormalizePath(default_fallback)); } const char* log_name = TTeeToStderr::GetDefault() ? kLogName_Tee : kLogName_Stderr; @@ -3285,7 +3350,6 @@ void CDiagContext::SetupDiag(EAppDiagStream ds, // Unlock severity level SetApplogSeverityLocked(false); if ( to_applog ) { - _ASSERT(s_UsingAutoApplog); ctx.SetOldPostFormat(false); SetDiagPostFlag(eDPF_MergeLines); s_MergeLinesSetBySetupDiag = true; @@ -3295,7 +3359,6 @@ void CDiagContext::SetupDiag(EAppDiagStream ds, SetApplogSeverityLocked(true); } else { - s_UsingAutoApplog = old_using_applog; if ( s_MergeLinesSetBySetupDiag ) { UnsetDiagPostFlag(eDPF_MergeLines); } @@ -3346,7 +3409,7 @@ CDiagContext::TCount CDiagContext::GetProcessPostNumber(EPostNumberIncrement inc bool CDiagContext::IsUsingRootLog(void) { - return GetLogFile().substr(0, 5) == "/log/"; + return GetLogFile().substr(0, 5) == kRootLog; } @@ -3610,11 +3673,6 @@ bool CDiagBuffer::SetDiag(const CNcbiDiag& diag) return false; } - // Check severity level change status - if ( sm_PostSeverityChange == eDiagSC_Unknown ) { - GetSeverityChangeEnabledFirstTime(); - } - EDiagSev sev = diag.GetSeverity(); bool is_console = (diag.GetPostFlags() & eDPF_IsConsole) > 0; if (!is_console && SeverityDisabled(sev)) { @@ -3762,7 +3820,6 @@ bool CDiagBuffer::GetTraceEnabledFirstTime(void) bool CDiagBuffer::GetSeverityChangeEnabledFirstTime(void) { - CDiagLock lock(CDiagLock::eWrite); if ( sm_PostSeverityChange != eDiagSC_Unknown ) { return sm_PostSeverityChange == eDiagSC_Enable; } @@ -5536,7 +5593,9 @@ extern void SetDiagHandler(CDiagHandler* handler, bool can_delete) ctx.Extra().Print("switch_diag_to", new_name); } } - if ( CDiagBuffer::sm_CanDeleteHandler ) + // Do not delete old handler if it's reinstalled (possibly just to change + // the ownership). + if (CDiagBuffer::sm_CanDeleteHandler && CDiagBuffer::sm_Handler != handler) delete CDiagBuffer::sm_Handler; if ( TTeeToStderr::GetDefault() ) { // Need to tee? @@ -5558,9 +5617,13 @@ extern bool IsSetDiagHandler(void) return (CDiagBuffer::sm_Handler != s_DefaultHandler); } -extern CDiagHandler* GetDiagHandler(bool take_ownership) +extern CDiagHandler* GetDiagHandler(bool take_ownership, + bool* current_ownership) { CDiagLock lock(CDiagLock::eRead); + if ( current_ownership ) { + *current_ownership = CDiagBuffer::sm_CanDeleteHandler; + } if (take_ownership) { _ASSERT(CDiagBuffer::sm_CanDeleteHandler); CDiagBuffer::sm_CanDeleteHandler = false; @@ -5891,7 +5954,7 @@ string CFileHandleDiagHandler::ComposeMessage(const SDiagMessage& msg, void CFileHandleDiagHandler::WriteMessage(const char* buf, size_t len, - EDiagFileType file_type) + EDiagFileType /*file_type*/) { // Period is longer than for CFileDiagHandler to prevent double-reopening // In async mode only one thread is writing messages and there's no need @@ -6121,19 +6184,33 @@ bool CFileDiagHandler::SetLogFile(const string& file_name, string trace_name = special ? adj_name : adj_name + ".trace"; string perf_name = special ? adj_name : adj_name + ".perf"; - if (!s_CreateHandler(err_name, err_handler)) - return false; - if (!s_CreateHandler(log_name, log_handler)) - return false; - if (!s_CreateHandler(trace_name, trace_handler)) - return false; - if (!s_CreateHandler(perf_name, perf_handler)) - return false; + if ( s_SplitLogFile ) { + if (!s_CreateHandler(err_name, err_handler)) + return false; + if (!s_CreateHandler(log_name, log_handler)) + return false; + if (!s_CreateHandler(trace_name, trace_handler)) + return false; + if (!s_CreateHandler(perf_name, perf_handler)) + return false; + + x_SetHandler(&m_Err, &m_OwnErr, err_handler.release(), true); + x_SetHandler(&m_Log, &m_OwnLog, log_handler.release(), true); + x_SetHandler(&m_Trace, &m_OwnTrace, trace_handler.release(), true); + x_SetHandler(&m_Perf, &m_OwnPerf, perf_handler.release(), true); + } + else { + if (!s_CreateHandler(file_name, err_handler)) + return false; + if (!s_CreateHandler(perf_name, perf_handler)) + return false; + + x_SetHandler(&m_Err, &m_OwnErr, err_handler.get(), true); + x_SetHandler(&m_Log, &m_OwnLog, err_handler.get(), true); + x_SetHandler(&m_Trace, &m_OwnTrace, err_handler.release(), true); + x_SetHandler(&m_Perf, &m_OwnPerf, perf_handler.release(), true); + } - x_SetHandler(&m_Err, &m_OwnErr, err_handler.release(), true); - x_SetHandler(&m_Log, &m_OwnLog, log_handler.release(), true); - x_SetHandler(&m_Trace, &m_OwnTrace, trace_handler.release(), true); - x_SetHandler(&m_Perf, &m_OwnPerf, perf_handler.release(), true); m_ReopenTimer->Restart(); break; } @@ -6248,10 +6325,10 @@ void CFileDiagHandler::Reopen(TReopenFlags flags) if ( m_Err ) { m_Err->Reopen(flags); } - if ( m_Log ) { + if ( m_Log && m_Log != m_Err ) { m_Log->Reopen(flags); } - if ( m_Trace ) { + if ( m_Trace && m_Trace != m_Log && m_Trace != m_Err ) { m_Trace->Reopen(flags); } if ( m_Perf ) { @@ -6744,8 +6821,7 @@ extern bool SetLogFile(const string& file_name, // Auto-split log file SetSplitLogFile(true); } - bool no_split = !(s_SplitLogFile || s_UsingAutoApplog); - if ( no_split ) { + if ( !s_SplitLogFile ) { if (file_type != eDiagFile_All) { ERR_POST_X(8, Info << "Failed to set log file for the selected event type: " @@ -6763,9 +6839,8 @@ extern bool SetLogFile(const string& file_name, } else { // output to file - auto_ptr fhandler( - new CFileHandleDiagHandler(file_name)); - if ( !fhandler->Valid() ) { + auto_ptr fhandler(new CFileDiagHandler()); + if ( !fhandler->SetLogFile(file_name, eDiagFile_All, quick_flush) ) { ERR_POST_X(9, Info << "Failed to initialize log: " << file_name); return false; } @@ -6776,22 +6851,33 @@ extern bool SetLogFile(const string& file_name, CFileDiagHandler* handler = dynamic_cast(GetDiagHandler()); if ( !handler ) { + bool old_ownership = false; CStreamDiagHandler_Base* sub_handler = - dynamic_cast(GetDiagHandler()); + dynamic_cast(GetDiagHandler(false, &old_ownership)); + if ( !sub_handler ) { + old_ownership = false; + } // Install new handler, try to re-use the old one auto_ptr fhandler(new CFileDiagHandler()); - // If we are going to set all three handlers, no need to save - // the old one. if ( sub_handler && file_type != eDiagFile_All) { - GetDiagHandler(true); // Take ownership! + // If we are going to set all handlers, no need to save the old one. + if ( old_ownership ) { + GetDiagHandler(true); // Take ownership! + } // Set all three handlers to the old one. - fhandler->SetSubHandler(sub_handler, eDiagFile_All, false); + fhandler->SetSubHandler(sub_handler, eDiagFile_All, old_ownership); } if ( fhandler->SetLogFile(file_name, file_type, quick_flush) ) { + // This will delete the old handler in case of eDiagFile_All. + // Otherwise the new handler will remember the ownership. SetDiagHandler(fhandler.release()); return true; } else { + // Restore the old handler's ownership if necessary. + if ( old_ownership ) { + SetDiagHandler(sub_handler, true); + } return false; } } diff --git a/c++/src/corelib/ncbidiag_p.hpp b/c++/src/corelib/ncbidiag_p.hpp index 28de8133..047e8f59 100644 --- a/c++/src/corelib/ncbidiag_p.hpp +++ b/c++/src/corelib/ncbidiag_p.hpp @@ -1,7 +1,7 @@ #ifndef CORELIB___NCBIDIAG_P__HPP #define CORELIB___NCBIDIAG_P__HPP -/* $Id: ncbidiag_p.hpp 456643 2015-01-14 13:08:34Z ivanov $ +/* $Id: ncbidiag_p.hpp 505891 2016-06-29 17:58:41Z gouriano $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -37,7 +37,7 @@ /// classes, and macros. /// /// More elaborate documentation could be found in: -/// http://www.ncbi.nlm.nih.gov/toolkit/doc/book/ch_core/#ch_core.diag +/// http://ncbi.github.io/cxx-toolkit/pages/ch_log #include #include diff --git a/c++/src/corelib/ncbienv.cpp b/c++/src/corelib/ncbienv.cpp index b13d6c09..65d62541 100644 --- a/c++/src/corelib/ncbienv.cpp +++ b/c++/src/corelib/ncbienv.cpp @@ -1,4 +1,4 @@ -/* $Id: ncbienv.cpp 477588 2015-08-31 18:03:35Z ucko $ +/* $Id: ncbienv.cpp 500965 2016-05-10 14:33:08Z elisovdn $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -100,7 +100,7 @@ void CNcbiEnvironment::Reset(const char* const* envp) ERR_POST_X(3, "CNcbiEnvironment: bad string '" << s << "'"); continue; } - m_Cache[string(s, eq)] = SEnvValue(eq + 1, kEmptyXCStr); + m_Cache[string(s, (size_t)(eq - s))] = SEnvValue(eq + 1, kEmptyXCStr); } } diff --git a/c++/src/corelib/ncbierror.cpp b/c++/src/corelib/ncbierror.cpp index 2cc2af97..dbf1215b 100644 --- a/c++/src/corelib/ncbierror.cpp +++ b/c++/src/corelib/ncbierror.cpp @@ -1,4 +1,4 @@ -/* $Id: ncbierror.cpp 373165 2012-08-27 14:27:55Z gouriano $ +/* $Id: ncbierror.cpp 511430 2016-08-22 15:25:37Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -139,44 +139,193 @@ CNcbiError::ECode CNcbiError::Code(void) const return m_Code; } -void CNcbiError::Set(ECode code, const CTempString& extra) + +CNcbiError* CNcbiError::x_Init(int err_code) { CNcbiError* e = NcbiError_GetOrCreate(); - e->m_Code = code; - e->m_Category = code < eUnknown ? eGeneric : eNcbi; - e->m_Native = code; - e->m_Extra = extra; + e->m_Code = ECode(err_code); + e->m_Category = err_code < eUnknown ? eGeneric : eNcbi; + e->m_Native = err_code; + e->m_Extra.clear(); + return e; } -void CNcbiError::SetErrno(int native_err_code, const CTempString& extra) + +template +CNcbiError* CNcbiError::x_Init(int err_code, Ty extra) { CNcbiError* e = NcbiError_GetOrCreate(); - e->m_Code = ECode(native_err_code); - e->m_Category = e->m_Code < eUnknown ? eGeneric : eNcbi; - e->m_Native = native_err_code; + e->m_Code = ECode(err_code); + e->m_Category = err_code < eUnknown ? eGeneric : eNcbi; + e->m_Native = err_code; e->m_Extra = extra; + return e; +} + + +void CNcbiError::Set(ECode code) +{ + x_Init((int)code); +} + + +void CNcbiError::Set(ECode code, const CTempString extra) +{ + x_Init((int)code, extra); +} + + +void CNcbiError::Set(ECode code, string&& extra) +{ + x_Init((int)code, extra); +} + + +void CNcbiError::Set(ECode code, const string& extra) +{ + x_Init((int)code, extra); +} + + +void CNcbiError::Set(ECode code, const char* extra) +{ + x_Init((int)code, extra); +} + + +void CNcbiError::SetErrno(int native_err_code) +{ + x_Init(native_err_code); +} + + +void CNcbiError::SetErrno(int native_err_code, const CTempString extra) +{ + x_Init(native_err_code, extra); +} + + +void CNcbiError::SetErrno(int native_err_code, string&& extra) +{ + x_Init(native_err_code, extra); +} + + +void CNcbiError::SetErrno(int native_err_code, const string& extra) +{ + x_Init(native_err_code, extra); +} + + +void CNcbiError::SetErrno(int native_err_code, const char* extra) +{ + x_Init(native_err_code, extra); +} + + +void CNcbiError::SetFromErrno(void) +{ + SetErrno(errno); } -void CNcbiError::SetFromErrno(const CTempString& extra) + + +void CNcbiError::SetFromErrno(const CTempString extra) { - SetErrno(errno,extra); + SetErrno(errno, extra); } + +void CNcbiError::SetFromErrno(string&& extra) +{ + SetErrno(errno, extra); +} + + +void CNcbiError::SetFromErrno(const string& extra) +{ + SetErrno(errno, extra); +} + + +void CNcbiError::SetFromErrno(const char* extra) +{ + SetErrno(errno, extra); +} + + + #if defined(NCBI_OS_MSWIN) -void CNcbiError::SetWindowsError( int native_err_code, const CTempString& extra) + +void CNcbiError::x_SetWindowsCodeCategory(CNcbiError* e) { - CNcbiError* e = NcbiError_GetOrCreate(); - e->m_Code = eNotSet; + e->m_Code = eNotSet; e->m_Category = eMsWindows; - e->m_Native = native_err_code; - e->m_Extra = extra; } -void CNcbiError::SetFromWindowsError( const CTempString& extra) + +void CNcbiError::SetWindowsError(int native_err_code) +{ + x_SetWindowsCodeCategory( x_Init(native_err_code) ); +} + + +void CNcbiError::SetWindowsError(int native_err_code, const CTempString extra) +{ + x_SetWindowsCodeCategory( x_Init(native_err_code, extra) ); +} + + +void CNcbiError::SetWindowsError(int native_err_code, string&& extra) +{ + x_SetWindowsCodeCategory( x_Init(native_err_code, extra) ); +} + + +void CNcbiError::SetWindowsError(int native_err_code, const string& extra) +{ + x_SetWindowsCodeCategory( x_Init(native_err_code, extra) ); +} + + +void CNcbiError::SetWindowsError(int native_err_code, const char* extra) +{ + x_SetWindowsCodeCategory( x_Init(native_err_code, extra) ); +} + + +void CNcbiError::SetFromWindowsError(void) +{ + SetWindowsError( GetLastError() ); +} + + +void CNcbiError::SetFromWindowsError(const CTempString extra) +{ + SetWindowsError( GetLastError(), extra ); +} + + +void CNcbiError::SetFromWindowsError(string&& extra) { SetWindowsError( GetLastError(), extra ); } + + +void CNcbiError::SetFromWindowsError(const string& extra) +{ + SetWindowsError( GetLastError(), extra ); +} + + +void CNcbiError::SetFromWindowsError(const char* extra) +{ + SetWindowsError( GetLastError(), extra ); +} + #endif + + ///////////////////////////////////////////////////////////////////////////// CNcbiOstream& operator<< (CNcbiOstream& str, const CNcbiError& err) diff --git a/c++/src/corelib/ncbifile.cpp b/c++/src/corelib/ncbifile.cpp index f7062b26..d5ac7ce0 100644 --- a/c++/src/corelib/ncbifile.cpp +++ b/c++/src/corelib/ncbifile.cpp @@ -1,4 +1,4 @@ -/* $Id: ncbifile.cpp 488254 2015-12-29 13:56:26Z ivanov $ +/* $Id: ncbifile.cpp 515654 2016-10-04 18:38:59Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -186,7 +186,7 @@ NCBI_PARAM_DEF_EX(bool, NCBI, FileAPILogging, DEFAULT_LOGGING_VALUE, int saved_error = errno; \ if (NCBI_PARAM_TYPE(NCBI, FileAPILogging)::GetDefault()) { \ ERR_POST(log_message << ": " << _T_STDSTRING(NcbiSys_strerror(saved_error))); \ - } \ + } \ errno = saved_error; \ } @@ -194,7 +194,7 @@ NCBI_PARAM_DEF_EX(bool, NCBI, FileAPILogging, DEFAULT_LOGGING_VALUE, { \ if (NCBI_PARAM_TYPE(NCBI, FileAPILogging)::GetDefault()) { \ ERR_POST(log_message); \ - } \ + } \ return false; \ } @@ -202,7 +202,7 @@ NCBI_PARAM_DEF_EX(bool, NCBI, FileAPILogging, DEFAULT_LOGGING_VALUE, { \ if (NCBI_PARAM_TYPE(NCBI, FileAPILogging)::GetDefault()) { \ ERR_POST(log_message); \ - } \ + } \ CNcbiError::Set(ncbierr, log_message); \ return false; \ } @@ -211,7 +211,7 @@ NCBI_PARAM_DEF_EX(bool, NCBI, FileAPILogging, DEFAULT_LOGGING_VALUE, { \ if (NCBI_PARAM_TYPE(NCBI, FileAPILogging)::GetDefault()) { \ ERR_POST(log_message); \ - } \ + } \ CNcbiError::SetFromWindowsError(log_message); \ return false; \ } @@ -698,6 +698,40 @@ string CDirEntry::CreateAbsolutePath(const string& path, ERelativeToWhat rtw) } +string CDirEntry::CreateAbsolutePath(const string& path, const string& rtw) +{ + if (IsAbsolutePath(path)) { + return path; + } + +#if defined(NCBI_OS_MSWIN) + if ( path.find(DISK_SEPARATOR) != NPOS ) { + NCBI_THROW(CFileException, eRelativePath, + "Path must not contain disk separator: " + path); + } + // Path started with slash + if (!path.empty() && (path[0] == '/' || path[0] == '\\')) { + // network path ? + if ( s_Win_IsNetworkPath(path) ) { + NCBI_THROW(CFileException, eRelativePath, + "Cannot use network path: " + path); + } + // relative to current drive only -- error + NCBI_THROW(CFileException, eRelativePath, + "Path can be used as relative to current drive only: " + path); + } +#endif + + if (!IsAbsolutePath(rtw)) { + NCBI_THROW(CFileException, eRelativePath, + "2nd parameter must represent absolute path: " + rtw); + } + return NormalizePath(ConcatPath(rtw, path)); + + +} + + string CDirEntry::ConvertToOSPath(const string& path) { // Not process empty or absolute path @@ -1908,6 +1942,10 @@ bool CDirEntry::SetTime(const CTime* modification, return true; #else // NCBI_OS_UNIX + + // Creation time doesn't used on Unix + creation = NULL; /* DUMMY, to avoid warnings */ + if ( !modification && !last_access /*&& !creation*/ ) { return true; } @@ -1917,9 +1955,9 @@ bool CDirEntry::SetTime(const CTime* modification, CTime x_modification, x_last_access; if ( !modification || !last_access ) { - if ( !GetTime(modification ? 0 : &x_modification, - last_access ? 0 : &x_last_access, - 0 /* creation */) ) { + if ( !GetTime(modification ? NULL : &x_modification, + last_access ? NULL : &x_last_access, + NULL /* creation */) ) { return false; } if (!modification) { @@ -1957,7 +1995,7 @@ bool CDirEntry::SetTime(const CTime* modification, if ((!modification || !last_access) && !GetTimeT(&x_modification, &x_last_access, - 0 /* creation */)) { + NULL /* creation */)) { return false; } @@ -2044,6 +2082,10 @@ bool CDirEntry::SetTimeT(const time_t* modification, return true; #else // NCBI_OS_UNIX + + // Creation time doesn't used on Unix + creation = NULL; /* DUMMY, to avoid warnings */ + if ( !modification && !last_access /*&& !creation*/ ) return true; @@ -2051,7 +2093,7 @@ bool CDirEntry::SetTimeT(const time_t* modification, if ((!modification || !last_access) && !GetTimeT(&x_modification, &x_last_access, - 0 /* creation */)) { + NULL /* creation */) ) { return false; } @@ -2464,16 +2506,17 @@ bool CDirEntry::Rename(const string& newname, TRenameFlags flags) // Can rename entries with different types? if ( F_ISSET(flags, fRF_EqualTypes) && (src_type != dst_type) ) { LOG_ERROR_AND_RETURN_NCBI("CDirEntry::Rename():" - " Both source and destination exist" - " and have different types: " - + src.GetPath() + " and " + dst.GetPath(), - CNcbiError::eOperationNotPermitted); + " Both source and destination exist" + " and have different types: " + + src.GetPath() + " and " + dst.GetPath(), + CNcbiError::eOperationNotPermitted); } // Can overwrite entry? if ( !F_ISSET(flags, fRF_Overwrite) ) { LOG_ERROR_AND_RETURN_NCBI("CDirEntry::Rename():" - " Destination path already exists: " - + dst.GetPath(), CNcbiError::eOperationNotPermitted); + " Destination path already exists: " + + dst.GetPath(), + CNcbiError::eOperationNotPermitted); } // Rename only if destination is older, otherwise just remove source if ( F_ISSET(flags, fRF_Update) && !src.IsNewer(dst.GetPath(), 0)) { @@ -2927,7 +2970,7 @@ fstream* CDirEntry::CreateTmpFile(const string& filename, #if defined(NCBI_OS_MSWIN) // Open file manually, because we cannot say to fstream // to use some specific flags for file opening. - // MS Windows should delete created file automaticaly + // MS Windows should delete created file automatically // after closing all opened file descriptors. // We cannot enable "only write" mode here, @@ -3606,6 +3649,18 @@ string CDir::GetTmpDir(void) } +string CDir::GetAppTmpDir(void) +{ + // Get application specific temporary directory name + string tmp = NCBI_PARAM_TYPE(NCBI, TmpDir)::GetThreadDefault(); + if (!tmp.empty()) { + return tmp; + } + // Use default TMP directory specified by OS + return CDir::GetTmpDir(); +} + + string CDir::GetCwd(void) { TXChar buf[4096]; @@ -5029,20 +5084,16 @@ Uint8 CFileUtil::GetTotalDiskSpace(const string& path) CFileDeleteList::~CFileDeleteList() { - ITERATE (TNames, name, m_Names) { - CDirEntry entry(*name); - if ( entry.IsDir()) { - CDir(*name).Remove(CDir::eRecursiveIgnoreMissing); - } else { - entry.Remove(); + ITERATE (TList, path, m_Paths) { + if (!CDirEntry(*path).Remove(CDirEntry::eRecursiveIgnoreMissing)) { + ERR_POST(Warning << "CFileDeleteList: failed to remove path: " << *path); } } } - -void CFileDeleteAtExit::Add(const string& entryname) +void CFileDeleteAtExit::Add(const string& path) { - s_DeleteAtExitFileList->Add(entryname); + s_DeleteAtExitFileList->Add(path); } const CFileDeleteList& CFileDeleteAtExit::GetDeleteList(void) @@ -5309,7 +5360,7 @@ string s_LastErrorMessage(void) CMemoryFileSegment::CMemoryFileSegment(SMemoryFileHandle& handle, SMemoryFileAttrs& attrs, - off_t offset, + TOffsetType offset, size_t length) : m_DataPtr(0), m_Offset(offset), m_Length(length), m_DataPtrReal(0), m_OffsetReal(offset), m_LengthReal(length) @@ -5488,7 +5539,7 @@ CMemoryFileMap::~CMemoryFileMap(void) } -void* CMemoryFileMap::Map(off_t offset, size_t length) +void* CMemoryFileMap::Map(TOffsetType offset, size_t length) { if ( !m_Handle || (m_Handle->hMap == kInvalidHandle) ) { // Special case. @@ -5801,7 +5852,7 @@ CMemoryFileMap::x_GetMemoryFileSegment(void* ptr) const CMemoryFile::CMemoryFile(const string& file_name, EMemMapProtect protect, EMemMapShare share, - off_t offset, + TOffsetType offset, size_t length, EOpenMode mode, Uint8 max_file_len) @@ -5816,7 +5867,7 @@ CMemoryFile::CMemoryFile(const string& file_name, } -void* CMemoryFile::Map(off_t offset, size_t length) +void* CMemoryFile::Map(TOffsetType offset, size_t length) { // Unmap if already mapped if ( m_Ptr ) { @@ -5844,7 +5895,7 @@ void* CMemoryFile::Extend(size_t length) // Get current mapped segment CMemoryFileSegment* segment = x_GetMemoryFileSegment(m_Ptr); - off_t offset = segment->GetOffset(); + TOffsetType offset = segment->GetOffset(); // Get file size Int8 file_size = GetFileSize(); @@ -6163,8 +6214,8 @@ void CFileIO::Open(const string& filename, default: _TROUBLE; }; - // -- Ignore 'share_mode' on UNIX. - //share_mode = eShare; + // Dummy, ignore 'share_mode' on UNIX + share_mode = eShare; // Try to open/create file m_Handle = open(filename.c_str(), flags, mode); @@ -6187,12 +6238,8 @@ void CFileIO::CreateTemporary(const string& dir, #if defined(NCBI_OS_MSWIN) || defined(NCBI_OS_UNIX) string x_dir = dir; if (x_dir.empty()) { - // Get application specific temporary directory name (see CParam) - x_dir = NCBI_PARAM_TYPE(NCBI, TmpDir)::GetThreadDefault(); - if (x_dir.empty()) { - // Use default TMP directory specified by OS - x_dir = CDir::GetTmpDir(); - } + // Get application specific temporary directory name + x_dir = CDir::GetAppTmpDir(); } if (!x_dir.empty()) { x_dir = CDirEntry::AddTrailingPathSeparator(x_dir); @@ -6774,11 +6821,11 @@ ERW_Result CFileReaderWriter::Flush(void) // Platform-dependent structure to store file locking information struct SLock { SLock(void) {}; - SLock(off_t off, size_t len) { + SLock(CFileLock::TOffsetType off, size_t len) { Reset(off, len); } #if defined(NCBI_OS_MSWIN) - void Reset(off_t off, size_t len) + void Reset(CFileLock::TOffsetType off, size_t len) { offset_lo = (DWORD)(off & 0xFFFFFFFF); offset_hi = (DWORD)((Int8(off) >> 32) & 0xFFFFFFFF); @@ -6798,7 +6845,7 @@ struct SLock { DWORD length_lo; DWORD length_hi; #elif defined(NCBI_OS_UNIX) - void Reset(off_t off, size_t len) { + void Reset(CFileLock::TOffsetType off, size_t len) { offset = off; length = len; } @@ -6809,7 +6856,7 @@ struct SLock { CFileLock::CFileLock(const string& filename, TFlags flags, EType type, - off_t offset, size_t length) + TOffsetType offset, size_t length) : m_Handle(kInvalidHandle), m_CloseHandle(false), m_Flags(flags), m_IsLocked(false), m_Lock(0) { @@ -6818,7 +6865,7 @@ CFileLock::CFileLock(const string& filename, TFlags flags, EType type, CFileLock::CFileLock(const char* filename, TFlags flags, EType type, - off_t offset, size_t length) + TOffsetType offset, size_t length) : m_Handle(kInvalidHandle), m_CloseHandle(false), m_Flags(flags), m_IsLocked(false), m_Lock(0) { @@ -6827,7 +6874,7 @@ CFileLock::CFileLock(const char* filename, TFlags flags, EType type, CFileLock::CFileLock(TFileHandle handle, TFlags flags, EType type, - off_t offset, size_t length) + TOffsetType offset, size_t length) : m_Handle(handle), m_CloseHandle(false), m_Flags(flags), m_IsLocked(false), m_Lock(0) { @@ -6836,7 +6883,7 @@ CFileLock::CFileLock(TFileHandle handle, TFlags flags, EType type, void CFileLock::x_Init(const char* filename, EType type, - off_t offset, size_t length) + TOffsetType offset, size_t length) { // Reset redundant flags F_CLEAN_REDUNDANT(fLockNow | fLockLater); @@ -6894,7 +6941,7 @@ CFileLock::~CFileLock() } -void CFileLock::Lock(EType type, off_t offset, size_t length) +void CFileLock::Lock(EType type, TOffsetType offset, size_t length) { // Remove previous lock if (m_IsLocked) { diff --git a/c++/src/corelib/ncbimtx.cpp b/c++/src/corelib/ncbimtx.cpp index 90365b1a..8e5614c6 100644 --- a/c++/src/corelib/ncbimtx.cpp +++ b/c++/src/corelib/ncbimtx.cpp @@ -1,4 +1,4 @@ -/* $Id: ncbimtx.cpp 469575 2015-06-05 16:41:20Z elisovdn $ +/* $Id: ncbimtx.cpp 505546 2016-06-27 13:14:02Z grichenk $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -1650,12 +1650,8 @@ void CSemaphore::Post(unsigned int count) "CSemaphore::Post() - " "attempt to exceed max_count and " "pthread_mutex_unlock() failed"); - xncbi_Validate(m_Sem->count <= kMax_UInt - count, - "CSemaphore::Post() - " - "would result in counter > MAX_UINT"); - xncbi_Validate(m_Sem->count + count <= m_Sem->max_count, + xncbi_Validate(false, "CSemaphore::Post() - attempt to exceed max_count"); - _TROUBLE; } // Signal some (or all) of the threads waiting on this semaphore @@ -2227,10 +2223,10 @@ void CConditionVariable::SignalSome(void) switch (res) { case EINVAL: NCBI_THROW(CConditionVariableException, eInvalidValue, - "WaitForSignal failed: invalid paramater"); + "SignalSome failed: invalid paramater"); default: NCBI_THROW(CConditionVariableException, eInvalidValue, - "WaitForSignal failed: unknown error"); + "SignalSome failed: unknown error"); } } #endif @@ -2247,10 +2243,10 @@ void CConditionVariable::SignalAll(void) switch (res) { case EINVAL: NCBI_THROW(CConditionVariableException, eInvalidValue, - "WaitForSignal failed: invalid paramater"); + "SignalAll failed: invalid paramater"); default: NCBI_THROW(CConditionVariableException, eInvalidValue, - "WaitForSignal failed: unknown error"); + "SignalAll failed: unknown error"); } } #endif diff --git a/c++/src/corelib/ncbireg.cpp b/c++/src/corelib/ncbireg.cpp index 635d9116..30d547fc 100644 --- a/c++/src/corelib/ncbireg.cpp +++ b/c++/src/corelib/ncbireg.cpp @@ -1,4 +1,4 @@ -/* $Id: ncbireg.cpp 495404 2016-03-17 13:28:04Z ivanov $ +/* $Id: ncbireg.cpp 507290 2016-07-18 15:24:29Z elisovdn $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -65,9 +65,7 @@ inline bool s_IsNameSectionSymbol(char ch, IRegistry::TFlags flags) } -// Check if "str" consists of alphanumeric and '_' only -// Treat the case of set fSectionlessEntries separately -static bool s_IsNameSection(const string& str, IRegistry::TFlags flags) +bool IRegistry::IsNameSection(const string& str, TFlags flags) { // Allow empty section name in case of fSectionlessEntries set if (str.empty() && !(flags & IRegistry::fSectionlessEntries) ) { @@ -82,22 +80,13 @@ static bool s_IsNameSection(const string& str, IRegistry::TFlags flags) return true; } -// Check if "str" consists of alphanumeric and '_' only -static bool s_IsNameEntry(const string& str, IRegistry::TFlags flags) -{ - // Do not allow empty entry name regardless of fSectionlessEntries - if (str.empty()) { - return false; - } - ITERATE (string, it, str) { - if (!s_IsNameSectionSymbol(*it, flags)) { - return false; - } - } - return true; +bool IRegistry::IsNameEntry(const string& str, TFlags flags) +{ + return IsNameSection(str, flags & ~IRegistry::fSectionlessEntries); } + // Convert "comment" from plain text to comment static const string s_ConvertComment(const string& comment, bool is_file_comment = false) @@ -279,13 +268,13 @@ const string& IRegistry::Get(const string& section, const string& name, flags |= fTPFlags; } string clean_section = NStr::TruncateSpaces(section); - if ( !s_IsNameSection(clean_section, flags) ) { + if ( !IsNameSection(clean_section, flags) ) { _TRACE("IRegistry::Get: bad section name \"" << NStr::PrintableString(section) << '\"'); return kEmptyStr; } string clean_name = NStr::TruncateSpaces(name); - if ( !s_IsNameEntry(clean_name, flags) ) { + if ( !IsNameEntry(clean_name, flags) ) { _TRACE("IRegistry::Get: bad entry name \"" << NStr::PrintableString(name) << '\"'); return kEmptyStr; @@ -306,7 +295,7 @@ bool IRegistry::HasEntry(const string& section, const string& name, flags |= fTPFlags; } string clean_section = NStr::TruncateSpaces(section); - if ( !s_IsNameSection(clean_section, flags) ) { + if ( !IsNameSection(clean_section, flags) ) { _TRACE("IRegistry::HasEntry: bad section name \"" << NStr::PrintableString(section) << '\"'); return false; @@ -314,7 +303,7 @@ bool IRegistry::HasEntry(const string& section, const string& name, string clean_name = NStr::TruncateSpaces(name); bool is_special_name = clean_name.empty() || clean_name == sm_InSectionCommentName; - if ( !is_special_name && !s_IsNameEntry(clean_name, flags) ) { + if ( !is_special_name && !IsNameEntry(clean_name, flags) ) { _TRACE("IRegistry::HasEntry: bad entry name \"" << NStr::PrintableString(name) << '\"'); return false; @@ -459,7 +448,7 @@ const string& IRegistry::GetComment(const string& section, const string& name, x_CheckFlags("IRegistry::GetComment", flags, (TFlags)fLayerFlags | fInternalSpaces | fSectionlessEntries); string clean_section = NStr::TruncateSpaces(section); - if ( !clean_section.empty() && !s_IsNameSection(clean_section, flags) ) { + if ( !clean_section.empty() && !IsNameSection(clean_section, flags) ) { _TRACE("IRegistry::GetComment: bad section name \"" << NStr::PrintableString(section) << '\"'); return kEmptyStr; @@ -467,7 +456,7 @@ const string& IRegistry::GetComment(const string& section, const string& name, string clean_name = NStr::TruncateSpaces(name); bool is_special_name = clean_name.empty() || clean_name == sm_InSectionCommentName; - if ( !is_special_name && !s_IsNameSection(clean_name, flags) ) { + if ( !is_special_name && !IsNameSection(clean_name, flags) ) { _TRACE("IRegistry::GetComment: bad entry name \"" << NStr::PrintableString(name) << '\"'); return kEmptyStr; @@ -490,7 +479,7 @@ void IRegistry::EnumerateInSectionComments(const string& section, _ASSERT(comments); comments->clear(); string clean_section = NStr::TruncateSpaces(section); - if (clean_section.empty() || !s_IsNameSection(clean_section, flags)) { + if (clean_section.empty() || !IsNameSection(clean_section, flags)) { _TRACE("IRegistry::EnumerateInSectionComments: bad section name \"" << NStr::PrintableString(section) << '\"'); return; @@ -530,7 +519,7 @@ void IRegistry::EnumerateEntries(const string& section, list* entries, _ASSERT(entries); entries->clear(); string clean_section = NStr::TruncateSpaces(section); - if ( !clean_section.empty() && !s_IsNameSection(clean_section, flags) ) { + if ( !clean_section.empty() && !IsNameSection(clean_section, flags) ) { _TRACE("IRegistry::EnumerateEntries: bad section name \"" << NStr::PrintableString(section) << '\"'); return; @@ -710,7 +699,7 @@ IRWRegistry* IRWRegistry::x_Read(CNcbiIstream& is, TFlags flags, NCBI_THROW2(CRegistryException, eSection, "Unnamed registry section" + in_path + ": `" + str + "'", line); - } else if ( !s_IsNameSection(section, flags) ) { + } else if ( !IsNameSection(section, flags) ) { NCBI_THROW2(CRegistryException, eSection, "Invalid registry section name" + in_path + ": `" + str + "'", line); @@ -730,7 +719,7 @@ IRWRegistry* IRWRegistry::x_Read(CNcbiIstream& is, TFlags flags, + ": '" + str + "'", line); } NStr::TruncateSpacesInPlace(name); - if ( !s_IsNameSection(name, flags) ) { + if ( !IsNameEntry(name, flags) ) { NCBI_THROW2(CRegistryException, eEntry, "Invalid registry entry name" + in_path + ": '" + str + "'", line); @@ -837,13 +826,13 @@ bool IRWRegistry::Set(const string& section, const string& name, fPersistent | fNoOverride | fTruncate | fInternalSpaces | fCountCleared | fSectionlessEntries); string clean_section = NStr::TruncateSpaces(section); - if ( !s_IsNameSection(clean_section, flags) ) { + if ( !IsNameSection(clean_section, flags) ) { _TRACE("IRWRegistry::Set: bad section name \"" << NStr::PrintableString(section) << '\"'); return false; } string clean_name = NStr::TruncateSpaces(name); - if ( !s_IsNameEntry(clean_name, flags) ) { + if ( !IsNameEntry(clean_name, flags) ) { _TRACE("IRWRegistry::Set: bad entry name \"" << NStr::PrintableString(name) << '\"'); return false; @@ -876,13 +865,13 @@ bool IRWRegistry::Unset(const string& section, const string& name, x_CheckFlags("IRWRegistry::Unset", flags, fTPFlags | fCountCleared | fSectionlessEntries); string clean_section = NStr::TruncateSpaces(section); - if ( !s_IsNameSection(clean_section, flags) ) { + if ( !IsNameSection(clean_section, flags) ) { _TRACE("IRWRegistry::Unset: bad section name \"" << NStr::PrintableString(section) << '\"'); return false; } string clean_name = NStr::TruncateSpaces(name); - if ( !s_IsNameEntry(clean_name, flags) ) { + if ( !IsNameEntry(clean_name, flags) ) { _TRACE("IRWRegistry::Unset: bad entry name \"" << NStr::PrintableString(name) << '\"'); return false; @@ -903,7 +892,7 @@ bool IRWRegistry::SetComment(const string& comment, const string& section, x_CheckFlags("IRWRegistry::SetComment", flags, fTransient | fNoOverride | fInternalSpaces | fCountCleared); string clean_section = NStr::TruncateSpaces(section); - if ( !clean_section.empty() && !s_IsNameSection(clean_section, flags) ) { + if ( !clean_section.empty() && !IsNameSection(clean_section, flags) ) { _TRACE("IRWRegistry::SetComment: bad section name \"" << NStr::PrintableString(section) << '\"'); return false; @@ -911,7 +900,7 @@ bool IRWRegistry::SetComment(const string& comment, const string& section, string clean_name = NStr::TruncateSpaces(name); bool is_special_name = clean_name.empty() || clean_name == sm_InSectionCommentName; - if ( !is_special_name && !s_IsNameEntry(clean_name, flags) ) { + if ( !is_special_name && !IsNameEntry(clean_name, flags) ) { _TRACE("IRWRegistry::SetComment: bad entry name \"" << NStr::PrintableString(name) << '\"'); return false; @@ -1030,7 +1019,7 @@ void CMemoryRegistry::x_Enumerate(const string& section, list& entries, " but with no fSections flag set"); ITERATE (TSections, it, m_Sections) { - if (s_IsNameSection(it->first, flags) + if (IsNameSection(it->first, flags) && HasEntry(it->first, kEmptyStr, flags)) { entries.push_back(it->first); } @@ -1046,7 +1035,7 @@ void CMemoryRegistry::x_Enumerate(const string& section, list& entries, TSections::const_iterator sit = m_Sections.find(section); if (sit != m_Sections.end()) { ITERATE (TEntries, it, sit->second.entries) { - if (s_IsNameSection(it->first, flags) + if (IsNameSection(it->first, flags) && ((flags & fCountCleared) != 0 || !it->second.value.empty() )) { entries.push_back(it->first); @@ -1974,7 +1963,8 @@ void CCompoundRWRegistry::x_Enumerate(const string& section, list& entries, TFlags flags) const { - set accum; + typedef set SetNoCase; + SetNoCase accum; REVERSE_ITERATE (CCompoundRegistry::TPriorityMap, it, m_AllRegistries->m_PriorityMap) { if ((flags & fJustCore) && (it->first < GetCoreCutoff())) { @@ -2001,7 +1991,7 @@ void CCompoundRWRegistry::x_Enumerate(const string& section, } } } - ITERATE (set, it, accum) { + ITERATE(SetNoCase, it, accum) { entries.push_back(*it); } } @@ -2031,7 +2021,7 @@ bool CCompoundRWRegistry::x_Set(const string& section, const string& name, TFlags flags2 = (flags & fPersistent) ? flags : (flags | fTransient); flags2 &= fLayerFlags; _TRACE('[' << section << ']' << name << " = " << value); - if ((flags & fNoOverride) && HasEntry(section, name, flags)) { + if ((flags & fNoOverride) && HasEntry(section, name, flags)) { return false; } if (value.empty()) { diff --git a/c++/src/corelib/ncbistr.cpp b/c++/src/corelib/ncbistr.cpp index 68e33369..b85d0a46 100644 --- a/c++/src/corelib/ncbistr.cpp +++ b/c++/src/corelib/ncbistr.cpp @@ -1,4 +1,4 @@ -/* $Id: ncbistr.cpp 491918 2016-02-10 14:52:43Z ivanov $ +/* $Id: ncbistr.cpp 511434 2016-08-22 15:26:41Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -347,36 +347,55 @@ bool NStr::IsUpper(const CTempString str) } -int NStr::StringToNonNegativeInt(const string& str) +int NStr::StringToNonNegativeInt(const CTempString str, TStringToNumFlags flags) { - int& errno_ref = errno; - if ( str.empty() ) { - CNcbiError::SetErrno(errno_ref = EINVAL, str); - return -1; - } - char ch = str[0]; - if ( !isdigit((unsigned char)ch) && (ch != '+') ) { - CNcbiError::SetErrno(errno_ref = EINVAL, str); - return -1; - } - char* endptr = 0; - const char* begptr = str.c_str(); - errno_ref = 0; - unsigned long value = strtoul(begptr, &endptr, 10); - if ( errno_ref ) { - CNcbiError::SetErrno(errno_ref, str); - return -1; + int error = 0, ret = -1; + size_t len = str.size(); + + if (!len) { + error = EINVAL; + } else { + size_t i = 0; + // skip leading '+' if any + if (str.data()[0] == '+' && len > 1) { + ++i; + } + unsigned v = 0; + for (; i < len; ++i) { + unsigned d = str.data()[i] - '0'; + if (d > 9) { + error = EINVAL; + break; + } + unsigned nv = v * 10 + d; + const unsigned kOverflowLimit = (INT_MAX - 9) / 10 + 1; + if (v >= kOverflowLimit) { + // possible overflow + if (v > kOverflowLimit || nv > INT_MAX) { + error = ERANGE; + break; + } + } + v = nv; + } + if (!error) { + ret = static_cast(v); + } } - else if ( !endptr || endptr == begptr || *endptr ) { - CNcbiError::SetErrno(errno_ref = EINVAL, str); - return -1; +/* + if (flags & fConvErr_NoErrno) { + return ret; } - else if ( value > (unsigned long) kMax_Int ) { - CNcbiError::SetErrno(errno_ref = ERANGE, str); - return -1; +*/ + errno = error; + if (error) { + if (flags & fConvErr_NoErrMessage) { + CNcbiError::SetErrno(error); + } else { + CNcbiError::SetErrno(error, str); + } } - errno_ref = 0; - return (int) value; + return ret; } @@ -388,15 +407,18 @@ class CS2N_Guard { public: CS2N_Guard(NStr::TStringToNumFlags flags, bool skip_if_zero) : + m_NoErrno(false), // m_NoErrno((flags & NStr::fConvErr_NoErrno) > 0), m_NoThrow((flags & NStr::fConvErr_NoThrow) > 0), m_SkipIfZero(skip_if_zero), m_Errno(0) {} ~CS2N_Guard(void) { - // Does the guard is used against the code that already set an errno? - // If the error code is not defined here, do not even try to check/set it. - if (!m_SkipIfZero || m_Errno) { - errno = m_Errno; + if (!m_NoErrno) { + // Does the guard is used against the code that already set an errno? + // If the error code is not defined here, do not even try to check/set it. + if (!m_SkipIfZero || m_Errno) { + errno = m_Errno; + } } } void Set(int errcode) { m_Errno = errcode; } @@ -410,6 +432,7 @@ public: string Message(const CTempString str, const char* to_type, const CTempString msg); private: + bool m_NoErrno; // do not set errno at all bool m_NoThrow; // do not throw an exception if TRUE bool m_SkipIfZero; // do not set errno if TRUE and m_Errno == 0 int m_Errno; // errno value to set @@ -447,8 +470,18 @@ string CS2N_Guard::Message(const CTempString str, const char* to_type, const CTe NCBI_THROW2(CStringException, eConvert, \ err_guard.Message(str, #to_type, msg), pos); \ } else { \ - CNcbiError::SetErrno(err_guard.Errno(), \ - err_guard.Message(str, #to_type, msg)); \ +/* \ + if (flags & NStr::fConvErr_NoErrno) { \ + / Error, but forced to return 0 / \ + return 0; \ + } \ +*/ \ + if (flags & NStr::fConvErr_NoErrMessage) { \ + CNcbiError::SetErrno(err_guard.Errno()); \ + } else { \ + CNcbiError::SetErrno(err_guard.Errno(), \ + err_guard.Message(str, #to_type, msg)); \ + } \ return 0; \ } \ } while (false) @@ -495,7 +528,7 @@ string CS2N_Guard::Message(const CTempString str, const char* to_type, const CTe } -int NStr::StringToInt(const CTempString str, TStringToNumFlags flags,int base) +int NStr::StringToInt(const CTempString str, TStringToNumFlags flags, int base) { S2N_CONVERT_GUARD_EX(flags); Int8 value = StringToInt8(str, flags, base); @@ -518,8 +551,7 @@ NStr::StringToUInt(const CTempString str, TStringToNumFlags flags, int base) } -long NStr::StringToLong(const CTempString str, TStringToNumFlags flags, - int base) +long NStr::StringToLong(const CTempString str, TStringToNumFlags flags, int base) { S2N_CONVERT_GUARD_EX(flags); Int8 value = StringToInt8(str, flags, base); @@ -626,7 +658,6 @@ void s_SkipAllowedSymbols(const CTempString str, // Check radix base. If it is zero, determine base using first chars // of the string. Update 'base' value. // Update 'ptr' to current position in the string. - static inline bool s_CheckRadix(const CTempString str, SIZE_TYPE& pos, int& base) { @@ -660,10 +691,8 @@ bool s_CheckRadix(const CTempString str, SIZE_TYPE& pos, int& base) } -Int8 NStr::StringToInt8(const CTempString str, TStringToNumFlags flags, - int base) +Int8 NStr::StringToInt8(const CTempString str, TStringToNumFlags flags, int base) { - _ASSERT(flags == 0 || flags > 32); S2N_CONVERT_GUARD(flags); // Current position in the string @@ -737,6 +766,7 @@ Int8 NStr::StringToInt8(const CTempString str, TStringToNumFlags flags, // Assign sign before the end pointer check n = sign ? -n : n; CHECK_ENDPTR(Int8); + return n; } @@ -744,13 +774,12 @@ Int8 NStr::StringToInt8(const CTempString str, TStringToNumFlags flags, Uint8 NStr::StringToUInt8(const CTempString str, TStringToNumFlags flags, int base) { - _ASSERT(flags == 0 || flags > 32); S2N_CONVERT_GUARD(flags); const TStringToNumFlags slow_flags = fMandatorySign|fAllowCommas|fAllowLeadingSymbols|fAllowTrailingSymbols; - if ( base == 10 && (flags & slow_flags) == 0 ) { + if ( base == 10 && (flags & slow_flags) == 0 ) { // fast conversion // Current position in the string @@ -1154,7 +1183,6 @@ double NStr::StringToDoublePosix(const char* ptr, char** endptr, TStringToNumFla static double s_StringToDouble(const char* str, size_t size, NStr::TStringToNumFlags flags) { - _ASSERT(flags == 0 || flags > 32); _ASSERT(str[size] == '\0'); if ((flags & NStr::fDecimalPosix) && (flags & NStr::fDecimalPosixOrLocal)) { NCBI_THROW2(CStringException, eBadArgs, @@ -1336,7 +1364,6 @@ Uint8 NStr::StringToUInt8_DataSize(const CTempString str, int base) { // We have a limited base range here - _ASSERT(flags == 0 || flags > 20); if ( base < 2 || base > 16 ) { NCBI_THROW2(CStringException, eConvert, "Bad numeric base '" + NStr::IntToString(base)+ "'", 0); @@ -1713,7 +1740,6 @@ static void s_SignedToString(string& out_str, void NStr::IntToString(string& out_str, int svalue, TNumToStringFlags flags, int base) { - _ASSERT(flags == 0 || flags > 32); if ( base < 2 || base > 36 ) { CNcbiError::SetErrno(errno = EINVAL); return; @@ -1731,7 +1757,6 @@ void NStr::IntToString(string& out_str, int svalue, void NStr::LongToString(string& out_str, long svalue, TNumToStringFlags flags, int base) { - _ASSERT(flags == 0 || flags > 32); if ( base < 2 || base > 36 ) { CNcbiError::SetErrno(errno = EINVAL); return; @@ -1751,12 +1776,10 @@ void NStr::ULongToString(string& out_str, TNumToStringFlags flags, int base) { - _ASSERT(flags == 0 || flags > 32); if ( base < 2 || base > 36 ) { CNcbiError::SetErrno(errno = EINVAL); return; } - const SIZE_TYPE kBufSize = CHAR_BIT * sizeof(value); char buffer[kBufSize]; char* pos = buffer + kBufSize; @@ -1912,7 +1935,6 @@ static char* s_PrintUint8(char* pos, void NStr::Int8ToString(string& out_str, Int8 svalue, TNumToStringFlags flags, int base) { - _ASSERT(flags == 0 || flags > 32); if ( base < 2 || base > 36 ) { CNcbiError::SetErrno(errno = EINVAL); return; @@ -1942,7 +1964,6 @@ void NStr::Int8ToString(string& out_str, Int8 svalue, void NStr::UInt8ToString(string& out_str, Uint8 value, TNumToStringFlags flags, int base) { - _ASSERT(flags == 0 || flags > 32); if ( base < 2 || base > 36 ) { CNcbiError::SetErrno(errno = EINVAL); return; @@ -2234,7 +2255,6 @@ void NStr::DoubleToString(string& out_str, double value, } - SIZE_TYPE NStr::DoubleToString(double value, unsigned int precision, char* buf, SIZE_TYPE buf_size, TNumToStringFlags flags) @@ -2653,10 +2673,9 @@ void NStr::PtrToString(string& out_str, const void* value) } -const void* NStr::StringToPtr(const CTempStringEx str) +const void* NStr::StringToPtr(const CTempStringEx str, TConvErrFlags flags) { - int& errno_ref = errno; - errno_ref = 0; + errno = 0; void *ptr = NULL; int res; if ( str.HasZeroAtEnd() ) { @@ -2665,7 +2684,11 @@ const void* NStr::StringToPtr(const CTempStringEx str) res = ::sscanf(string(str).c_str(), "%p", &ptr); } if (res != 1) { - CNcbiError::SetErrno(errno_ref = EINVAL, str); + if (flags & fConvErr_NoErrMessage) { + CNcbiError::SetErrno(errno = EINVAL); + } else { + CNcbiError::SetErrno(errno = EINVAL, str); + } return NULL; } return ptr; @@ -3658,7 +3681,7 @@ string NStr::Join(const set& arr, const CTempString delim) out.reset(new CNcbiOstrstream); \ } \ SIZE_TYPE n = (flags & fSS_NoMerge) ? n_spaces : 1; \ - for (SIZE_TYPE i = n; i > 0; i--) { \ + for (SIZE_TYPE j = n; j > 0; j--) { \ out->put(' '); \ } @@ -4763,7 +4786,7 @@ string NStr::ParseEscapes(const CTempString str, EEscSeqRange mode, char user_ch "' is out of range [0-255]", pos2); break; case eEscSeqRange_Errno: - CNcbiError::SetErrno(errno = ERANGE,str); + CNcbiError::SetErrno(errno = ERANGE, str); is_error = true; continue; case eEscSeqRange_User: diff --git a/c++/src/corelib/ncbitime.cpp b/c++/src/corelib/ncbitime.cpp index 689667fa..e378fd9e 100644 --- a/c++/src/corelib/ncbitime.cpp +++ b/c++/src/corelib/ncbitime.cpp @@ -1,4 +1,4 @@ -/* $Id: ncbitime.cpp 493937 2016-03-02 16:38:06Z ivanov $ +/* $Id: ncbitime.cpp 500405 2016-05-04 15:18:35Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -817,15 +817,15 @@ bool CTime::x_Init(const string& str, const CTimeFormat& format, EErrAction err_ SET_SEC(value); if ( *sss == '.' ) { ++sss; - char* s = value_str; + s = value_str; // Limit fraction of second to 9 digits max, // ignore all other digits in string if any. - for (size_t len = 9; - len && *sss && isdigit((unsigned char)(*sss)); --len) { + for (size_t n = 9; + n && *sss && isdigit((unsigned char)(*sss)); --n) { *s++ = *sss++; } *s = '\0'; - long value = NStr::StringToLong(value_str); + value = NStr::StringToLong(value_str); size_t n = strlen(value_str); // 'n' cannot have more then 9 (max for nanoseconds) - see above. _ASSERT(n <= 9); @@ -2433,8 +2433,8 @@ CTimeSpan::CTimeSpan(const string& str, const CTimeFormat& fmt) // if global format has not set. CTimeFormat* ptr = s_TlsFormatSpan.GetValue(); if (!ptr) { - CTimeFormat fmt(kDefaultFormatSpanIn); - x_Init(str, fmt); + CTimeFormat default_fmt(kDefaultFormatSpanIn); + x_Init(str, default_fmt); } else { x_Init(str, *ptr); } @@ -3965,7 +3965,7 @@ retry: int x_daylight = Daylight(); {{ // MT-Safe protect: use CTime locking mutex - CFastMutexGuard LOCK(s_TimeMutex); + CFastMutexGuard LOCK_TM(s_TimeMutex); x_timezone = TimeZone(); x_daylight = Daylight(); }} diff --git a/c++/src/corelib/request_ctx.cpp b/c++/src/corelib/request_ctx.cpp index 6c372354..5178b2f1 100644 --- a/c++/src/corelib/request_ctx.cpp +++ b/c++/src/corelib/request_ctx.cpp @@ -1,4 +1,4 @@ -/* $Id: request_ctx.cpp 493379 2016-02-26 15:41:32Z ivanov $ +/* $Id: request_ctx.cpp 508783 2016-08-01 16:05:01Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -53,7 +53,6 @@ CRequestContext::CRequestContext(TContextFlags flags) : m_RequestID(0), m_AppState(eDiagAppState_NotSet), m_LoggedHitID(false), - m_SubHitID(0), m_ReqStatus(0), m_ReqTimer(CStopWatch::eStop), m_BytesRd(0), @@ -81,7 +80,7 @@ CRequestContext::TCount CRequestContext::GetNextRequestID(void) void CRequestContext::x_LogHitID(bool ignore_app_state) const { - if (m_LoggedHitID || m_HitID.empty()) return; + if (m_LoggedHitID || m_HitID.Empty()) return; // ignore_app_state can be set by CDiagContext in case if hit-id // was set for request context only (no default one), but request @@ -93,7 +92,8 @@ void CRequestContext::x_LogHitID(bool ignore_app_state) const m_AppState != eDiagAppState_Request && m_AppState != eDiagAppState_RequestBegin && m_AppState != eDiagAppState_RequestEnd) return; - GetDiagContext().Extra().Print(g_GetNcbiString(eNcbiStrings_PHID), m_HitID); + GetDiagContext().Extra().Print(g_GetNcbiString(eNcbiStrings_PHID), + m_HitID.GetHitId()); m_LoggedHitID = true; } @@ -101,7 +101,7 @@ void CRequestContext::x_LogHitID(bool ignore_app_state) const const string& CRequestContext::SetHitID(void) { SetHitID(GetDiagContext().GetNextHitID()); - return m_HitID; + return m_HitID.GetHitId(); } @@ -109,12 +109,12 @@ string CRequestContext::x_GetHitID(CDiagContext::EDefaultHitIDFlags flag) const { if ( x_IsSetProp(eProp_HitID) ) { x_LogHitID(); - return m_HitID; + return m_HitID.GetHitId(); } - string phid = GetDiagContext().x_GetDefaultHitID(CDiagContext::eHitID_NoCreate); - if (!phid.empty()) { - const_cast(this)->SetHitID(phid); - return phid; + CSharedHitId phid = GetDiagContext().x_GetDefaultHitID(CDiagContext::eHitID_NoCreate); + if (!phid.Empty()) { + const_cast(this)->x_SetHitID(phid); + return phid.GetHitId(); } if (flag != CDiagContext::eHitID_NoCreate) { // If there's no hit id available, create (and log) a new one. @@ -291,6 +291,9 @@ static bool IsValidHitID(const string& hit) { return false; } } + // Hit id must be present before the first separator. + // Note that empty hit id is still allowed if there are no sub-hit ids. + if (sep_pos == 0) return false; if (sep_pos == NPOS) return true; // Separator found - make sure the rest of the id contains only separators // and valid sub-hit ids: a prefix consisting of allowed chars and some @@ -316,24 +319,26 @@ static bool IsValidHitID(const string& hit) { } -void CRequestContext::SetHitID(const string& hit) +void CRequestContext::x_SetHitID(const CSharedHitId& hit_id) { + const string& hit = hit_id.GetHitId(); if ( m_LoggedHitID ) { // Show warning when changing hit id after is has been logged. ERR_POST_X(28, Warning << "Changing hit ID after one has been logged. " "New hit id is: " << hit); } + if (m_HitID.GetHitId() == hit) return; + static CSafeStatic action; if ( !IsValidHitID(hit) ) { switch ( action->Get() ) { case eOnBadPHID_Ignore: return; case eOnBadPHID_AllowAndReport: - // Use Warning if bad hit id is acceptable. ERR_POST_X(27, Warning << "Bad hit ID format: " << hit); break; case eOnBadPHID_IgnoreAndReport: - ERR_POST_X(27, "Bad hit ID format: " << hit); + ERR_POST_X(27, Warning << "Bad hit ID format: " << hit); return; case eOnBadPHID_Throw: NCBI_THROW(CRequestContextException, eBadHit, @@ -344,38 +349,33 @@ void CRequestContext::SetHitID(const string& hit) } } x_SetProp(eProp_HitID); - if (m_HitID != hit) { - m_SubHitID = 0; - m_SubHitIDCache.clear(); - } - m_HitID = hit; + + m_SubHitIDCache.clear(); + m_HitID = hit_id; m_LoggedHitID = false; x_LogHitID(); } -void CRequestContext::x_UpdateSubHitID(bool increment) +void CRequestContext::SetHitID(const string& hit) { - static CAtomicCounter s_DefaultSubHitCounter; + x_SetHitID(CSharedHitId(hit)); +} + +void CRequestContext::x_UpdateSubHitID(bool increment, CTempString prefix) +{ _ASSERT(IsSetHitID()); // Use global sub-hit counter for default hit id to prevent // duplicate phids in different threads. m_SubHitIDCache = GetHitID(); - unsigned int sub_hit_id; - if (m_SubHitIDCache == GetDiagContext().GetDefaultHitID()) { - sub_hit_id = (unsigned int)(increment ? s_DefaultSubHitCounter.Add(1) : - s_DefaultSubHitCounter.Get()); - } - else { - if ( increment ) ++m_SubHitID; - sub_hit_id = m_SubHitID; - } + unsigned int sub_hit_id = increment ? + m_HitID.GetNextSubHitId() : m_HitID.GetCurrentSubHitId(); // Cache the string so that C code can use it. - m_SubHitIDCache += "." + NStr::NumericToString(sub_hit_id); + m_SubHitIDCache += "." + prefix + NStr::NumericToString(sub_hit_id); } @@ -387,12 +387,11 @@ void CRequestContext::SetSessionID(const string& session) case eOnBadSID_Ignore: return; case eOnBadSID_AllowAndReport: - case eOnBadSID_IgnoreAndReport: - ERR_POST_X(26, "Bad session ID format: " << session); - if (action == eOnBadSID_IgnoreAndReport) { - return; - } + ERR_POST_X(26, Warning << "Bad session ID format: " << session); break; + case eOnBadSID_IgnoreAndReport: + ERR_POST_X(26, Warning << "Bad session ID format: " << session); + return; case eOnBadSID_Throw: NCBI_THROW(CRequestContextException, eBadSession, "Bad session ID format: " + session); @@ -505,9 +504,9 @@ CRef CRequestContext::Clone(void) const ret->m_AppState = m_AppState; ret->m_ClientIP = m_ClientIP; ret->m_SessionID.SetString(m_SessionID.GetOriginalString()); + m_HitID.SetShared(); ret->m_HitID = m_HitID; ret->m_LoggedHitID = m_LoggedHitID; - ret->m_SubHitID = m_SubHitID; ret->m_SubHitIDCache = m_SubHitIDCache; ret->m_Dtab = m_Dtab; ret->m_ReqStatus = m_ReqStatus; diff --git a/c++/src/corelib/stream_utils.cpp b/c++/src/corelib/stream_utils.cpp index 8489cac8..4fa623ff 100644 --- a/c++/src/corelib/stream_utils.cpp +++ b/c++/src/corelib/stream_utils.cpp @@ -1,4 +1,4 @@ -/* $Id: stream_utils.cpp 463570 2015-03-30 16:29:21Z lavr $ +/* $Id: stream_utils.cpp 504923 2016-06-20 20:21:48Z lavr $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -525,6 +525,13 @@ static streamsize s_Readsome(CNcbiIstream& is, return count; #else // Try to read data +# ifdef __llvm__ + // https://llvm.org/bugs/show_bug.cgi?id=28217 + if ( !is.good() ) { + is.setstate(is.rdstate() | NcbiFailbit); + return 0; // simulate construction of sentry in standard readsome() + } +# endif //__llvm__ streamsize n = x_Readsome(is, buf, buf_size); if (n != 0 || !is.good()) return n; diff --git a/c++/src/corelib/teamcity_boost.cpp b/c++/src/corelib/teamcity_boost.cpp index 45e1370d..0578c0d3 100644 --- a/c++/src/corelib/teamcity_boost.cpp +++ b/c++/src/corelib/teamcity_boost.cpp @@ -1,83 +1,106 @@ /* Copyright 2011 JetBrains s.r.o. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * - * $Id: teamcity_boost.cpp 488254 2015-12-29 13:56:26Z ivanov $ + * + * $Id: teamcity_boost.cpp 500448 2016-05-04 18:16:16Z ucko $ */ #include -#include #include #include #include -#include +#include +#include +#include + +// In 1.59.0, they changed the name of this enum value, so we have to this hacky thing... +#include +#if BOOST_VERSION >= 105900 + #define TUT_CASE_IDENTIFIER boost::unit_test::TUT_CASE + #define CURRENT_TEST_NAME boost::unit_test_framework::framework::current_test_case().full_name() +#else + #define TUT_CASE_IDENTIFIER boost::unit_test::tut_case + #define CURRENT_TEST_NAME boost::unit_test_framework::framework::current_test_case().p_name +#endif #include "teamcity_messages.h" -/// -// NOTE: Using namespace boost::unit_test breaks GPIPE Static build!! -/// -//using namespace boost::unit_test; -using namespace std; - -namespace JetBrains { +namespace jetbrains { namespace teamcity { +const std::string ASSERT_CTX = "Assertion occurred in a following context:"; +const std::string FAILURE_CTX = "Failure occurred in a following context:"; // Custom formatter for TeamCity messages class TeamcityBoostLogFormatter: public boost::unit_test::unit_test_log_formatter { TeamcityMessages messages; std::string currentDetails; + std::string currentContextDetails; std::string flowId; public: TeamcityBoostLogFormatter(const std::string &_flowId); TeamcityBoostLogFormatter(); - void log_start(std::ostream&, boost::unit_test::counter_t test_cases_amount); - void log_finish(std::ostream&); - void log_build_info(std::ostream&); + virtual ~TeamcityBoostLogFormatter() {} + + virtual void log_start(std::ostream&, boost::unit_test::counter_t test_cases_amount); + virtual void log_finish(std::ostream&); + virtual void log_build_info(std::ostream&); - void test_unit_start(std::ostream&, boost::unit_test::test_unit const& tu); - void test_unit_finish(std::ostream&, + virtual void test_unit_start(std::ostream&, boost::unit_test::test_unit const& tu); + virtual void test_unit_finish(std::ostream&, boost::unit_test::test_unit const& tu, unsigned long elapsed); - void test_unit_skipped(std::ostream&, boost::unit_test::test_unit const& tu); + virtual void test_unit_skipped(std::ostream&, boost::unit_test::test_unit const& tu); + virtual void test_unit_skipped(std::ostream&, + boost::unit_test::test_unit const& tu, + boost::unit_test::const_string reason); - void log_exception(std::ostream&, + virtual void log_exception(std::ostream&, boost::unit_test::log_checkpoint_data const&, boost::unit_test::const_string explanation); + virtual void log_exception_start(std::ostream&, + boost::unit_test::log_checkpoint_data const&, + const boost::execution_exception&); + virtual void log_exception_finish(std::ostream&); - void log_entry_start(std::ostream&, - boost::unit_test::log_entry_data const&, + virtual void log_entry_start(std::ostream & out, + boost::unit_test::log_entry_data const & entry_data, log_entry_types let); - void log_entry_value(std::ostream&, boost::unit_test::const_string value); - void log_entry_finish(std::ostream&); + virtual void log_entry_value(std::ostream&, boost::unit_test::const_string value); + virtual void log_entry_finish(std::ostream&); + + virtual void entry_context_start(std::ostream&, boost::unit_test::log_level); + virtual void log_entry_context(std::ostream&, boost::unit_test::const_string); + virtual void entry_context_finish(std::ostream&); }; // Fake fixture to register formatter struct TeamcityFormatterRegistrar { TeamcityFormatterRegistrar() { - if (JetBrains::underTeamcity()) { - boost::unit_test::unit_test_log.set_formatter(new JetBrains::TeamcityBoostLogFormatter()); - boost::unit_test::unit_test_log.set_threshold_level(boost::unit_test::runtime_config::log_level()); + if (underTeamcity()) { + boost::unit_test::unit_test_log.set_formatter(new TeamcityBoostLogFormatter()); + boost::unit_test::unit_test_log.set_threshold_level + (RTCFG(but::log_level, LOG_LEVEL, log_level)); } } }; + BOOST_GLOBAL_FIXTURE(TeamcityFormatterRegistrar); // Formatter implementation -string toString(boost::unit_test::const_string bstr) { - stringstream ss; +static std::string toString(boost::unit_test::const_string bstr) { + std::stringstream ss; ss << bstr; @@ -92,19 +115,19 @@ TeamcityBoostLogFormatter::TeamcityBoostLogFormatter() : flowId(getFlowIdFromEnvironment()) {} -void TeamcityBoostLogFormatter::log_start(ostream &out, boost::unit_test::counter_t test_cases_amount) +void TeamcityBoostLogFormatter::log_start(std::ostream &/*out*/, boost::unit_test::counter_t /*test_cases_amount*/) {} -void TeamcityBoostLogFormatter::log_finish(ostream &out) +void TeamcityBoostLogFormatter::log_finish(std::ostream &/*out*/) {} -void TeamcityBoostLogFormatter::log_build_info(ostream &out) +void TeamcityBoostLogFormatter::log_build_info(std::ostream &/*out*/) {} -void TeamcityBoostLogFormatter::test_unit_start(ostream &out, boost::unit_test::test_unit const& tu) { +void TeamcityBoostLogFormatter::test_unit_start(std::ostream &out, boost::unit_test::test_unit const& tu) { messages.setOutput(out); - if (tu.p_type == boost::unit_test::tut_case) { + if (tu.p_type == TUT_CASE_IDENTIFIER) { messages.testStarted(tu.p_name, flowId); } else { messages.suiteStarted(tu.p_name, flowId); @@ -113,11 +136,11 @@ void TeamcityBoostLogFormatter::test_unit_start(ostream &out, boost::unit_test:: currentDetails.clear(); } -void TeamcityBoostLogFormatter::test_unit_finish(ostream &out, boost::unit_test::test_unit const& tu, unsigned long elapsed) { +void TeamcityBoostLogFormatter::test_unit_finish(std::ostream &out, boost::unit_test::test_unit const& tu, unsigned long elapsed) { messages.setOutput(out); boost::unit_test::test_results const& tr = boost::unit_test::results_collector.results(tu.p_id); - if (tu.p_type == boost::unit_test::tut_case) { + if (tu.p_type == TUT_CASE_IDENTIFIER) { if(!tr.passed()) { if(tr.p_skipped) { messages.testIgnored(tu.p_name, "ignored", flowId); @@ -134,27 +157,62 @@ void TeamcityBoostLogFormatter::test_unit_finish(ostream &out, boost::unit_test: } } -void TeamcityBoostLogFormatter::test_unit_skipped(ostream &out, boost::unit_test::test_unit const& tu) +void TeamcityBoostLogFormatter::test_unit_skipped(std::ostream &/*out*/, boost::unit_test::test_unit const& /*tu*/) {} -void TeamcityBoostLogFormatter::log_exception(ostream &out, boost::unit_test::log_checkpoint_data const&, boost::unit_test::const_string explanation) { - string what = toString(explanation); +void TeamcityBoostLogFormatter::test_unit_skipped(std::ostream &out, boost::unit_test::test_unit const& tu, boost::unit_test::const_string reason) +{ + messages.testIgnored(tu.p_name, toString(reason), flowId); +} + +void TeamcityBoostLogFormatter::log_exception(std::ostream &out, boost::unit_test::log_checkpoint_data const &, boost::unit_test::const_string explanation) { + std::string what = toString(explanation); - out << what << endl; + out << what << std::endl; currentDetails += what + "\n"; } -void TeamcityBoostLogFormatter::log_entry_start(ostream&, boost::unit_test::log_entry_data const&, log_entry_types let) -{} +void TeamcityBoostLogFormatter::log_exception_start(std::ostream &out, boost::unit_test::log_checkpoint_data const &data, const boost::execution_exception& excpt) { + log_exception(out, data, excpt.what()); +} + +void TeamcityBoostLogFormatter::log_exception_finish(std::ostream &/*out*/) {} -void TeamcityBoostLogFormatter::log_entry_value(ostream &out, boost::unit_test::const_string value) { + +void TeamcityBoostLogFormatter::log_entry_start(std::ostream & out, boost::unit_test::log_entry_data const & entry_data, log_entry_types /*let*/) +{ + std::stringstream ss(std::ios_base::out); + + out << entry_data.m_file_name << "(" << entry_data.m_line_num << "): "; + ss << entry_data.m_file_name << "(" << entry_data.m_line_num << "): "; + + currentDetails += ss.str(); +} + +void TeamcityBoostLogFormatter::log_entry_value(std::ostream &out, boost::unit_test::const_string value) { out << value; currentDetails += toString(value); } -void TeamcityBoostLogFormatter::log_entry_finish(ostream &out) { - out << endl; +void TeamcityBoostLogFormatter::log_entry_finish(std::ostream &out) { + out << std::endl; currentDetails += "\n"; } +void TeamcityBoostLogFormatter::entry_context_start(std::ostream &out, boost::unit_test::log_level l) { + const std::string& initial_msg = (l == boost::unit_test::log_successful_tests ? ASSERT_CTX : FAILURE_CTX); + out << initial_msg; + currentContextDetails = initial_msg; } + +void TeamcityBoostLogFormatter::log_entry_context(std::ostream &out, boost::unit_test::const_string ctx) { + out << "\n " << ctx; + currentContextDetails += "\n " + toString(ctx); +} + +void TeamcityBoostLogFormatter::entry_context_finish(std::ostream &out) { + out.flush(); + messages.testOutput(CURRENT_TEST_NAME, currentContextDetails, flowId, TeamcityMessages::StdErr); +} + +}} // namespace teamcity, jetbrains diff --git a/c++/src/corelib/teamcity_messages.cpp b/c++/src/corelib/teamcity_messages.cpp index 83dbbb59..85977ec3 100644 --- a/c++/src/corelib/teamcity_messages.cpp +++ b/c++/src/corelib/teamcity_messages.cpp @@ -12,43 +12,66 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * $Id: teamcity_messages.cpp 435791 2014-05-20 18:47:58Z camacho $ + * $Id: teamcity_messages.cpp 500881 2016-05-09 17:50:16Z ucko $ */ #include -#include -#include - #include "teamcity_messages.h" -using namespace std; +#include +#include -namespace JetBrains { +namespace jetbrains { +namespace teamcity { std::string getFlowIdFromEnvironment() { +#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)) && 0 + char *flowId = NULL; + size_t sz = 0; + std::string result; + if(!_dupenv_s(&flowId, &sz,"TEAMCITY_PROCESS_FLOW_ID")) { + result = flowId != NULL ? flowId : ""; + free(flowId); + } + + return result; +#else const char *flowId = getenv("TEAMCITY_PROCESS_FLOW_ID"); return flowId == NULL ? "" : flowId; +#endif } bool underTeamcity() { +#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)) && 0 + char *teamCityProjectName = 0; + size_t sz = 0; + bool result = false; + if(!_dupenv_s(&teamCityProjectName, &sz, "TEAMCITY_PROJECT_NAME")) { + result = teamCityProjectName != NULL; + free(teamCityProjectName); + } + + return result; +#else return getenv("TEAMCITY_PROJECT_NAME") != NULL; +#endif } TeamcityMessages::TeamcityMessages() -: m_out(&cout) +: m_out(&std::cout) {} -void TeamcityMessages::setOutput(ostream &out) { +void TeamcityMessages::setOutput(std::ostream &out) { m_out = &out; } -string TeamcityMessages::escape(string s) { - string result; - +std::string TeamcityMessages::escape(std::string s) { + std::string result; + for (size_t i = 0; i < s.length(); i++) { char c = s[i]; - + switch (c) { case '\n': result.append("|n"); break; case '\r': result.append("|r"); break; @@ -58,56 +81,60 @@ string TeamcityMessages::escape(string s) { default: result.append(&c, 1); } } - + return result; } -void TeamcityMessages::openMsg(const string &name) { - *m_out << "##teamcity[" << name; +void TeamcityMessages::openMsg(const std::string &name) { + // endl for http://jetbrains.net/tracker/issue/TW-4412 + *m_out << std::endl << "##teamcity[" << name; } void TeamcityMessages::closeMsg() { *m_out << "]"; // endl for http://jetbrains.net/tracker/issue/TW-4412 - *m_out << endl; - m_out->flush(); + *m_out << std::endl; } -void TeamcityMessages::writeProperty(string name, string value) { +void TeamcityMessages::writeProperty(std::string name, std::string value) { *m_out << " " << name << "='" << escape(value) << "'"; } -void TeamcityMessages::suiteStarted(string name, string flowid) { +void TeamcityMessages::suiteStarted(std::string name, std::string flowid) { openMsg("testSuiteStarted"); writeProperty("name", name); if(flowid.length() > 0) { writeProperty("flowId", flowid); } - + closeMsg(); } -void TeamcityMessages::suiteFinished(string name, string flowid) { +void TeamcityMessages::suiteFinished(std::string name, std::string flowid) { openMsg("testSuiteFinished"); writeProperty("name", name); if(flowid.length() > 0) { writeProperty("flowId", flowid); } - + closeMsg(); } -void TeamcityMessages::testStarted(string name, string flowid) { +void TeamcityMessages::testStarted(std::string name, std::string flowid, bool captureStandardOutput) { openMsg("testStarted"); writeProperty("name", name); if(flowid.length() > 0) { writeProperty("flowId", flowid); } - + + if(captureStandardOutput) { + writeProperty("captureStandardOutput", "true"); // false by default + } + closeMsg(); } -void TeamcityMessages::testFinished(string name, int durationMs, string flowid) { +void TeamcityMessages::testFinished(std::string name, int durationMs, std::string flowid) { openMsg("testFinished"); writeProperty("name", name); @@ -117,15 +144,15 @@ void TeamcityMessages::testFinished(string name, int durationMs, string flowid) } if(durationMs >= 0) { - stringstream out; + std::stringstream out(std::ios_base::out); out << durationMs; writeProperty("duration", out.str()); } - + closeMsg(); } -void TeamcityMessages::testFailed(string name, string message, string details, string flowid) { +void TeamcityMessages::testFailed(std::string name, std::string message, std::string details, std::string flowid) { openMsg("testFailed"); writeProperty("name", name); writeProperty("message", message); @@ -133,19 +160,31 @@ void TeamcityMessages::testFailed(string name, string message, string details, s if(flowid.length() > 0) { writeProperty("flowId", flowid); } - + closeMsg(); } -void TeamcityMessages::testIgnored(std::string name, std::string message, string flowid) { +void TeamcityMessages::testIgnored(std::string name, std::string message, std::string flowid) { openMsg("testIgnored"); writeProperty("name", name); writeProperty("message", message); if(flowid.length() > 0) { writeProperty("flowId", flowid); } - + closeMsg(); } +void TeamcityMessages::testOutput(std::string name, std::string output, std::string flowid, bool isStdError) { + openMsg(isStdError ? "testStdErr" : "testStdOut"); + writeProperty("name", name); + writeProperty("out", output); + if(flowid.length() > 0) { + writeProperty("flowId", flowid); + } + + closeMsg(); +} + +} } diff --git a/c++/src/corelib/teamcity_messages.h b/c++/src/corelib/teamcity_messages.h index 88dd5c0c..e4326e3e 100644 --- a/c++/src/corelib/teamcity_messages.h +++ b/c++/src/corelib/teamcity_messages.h @@ -12,23 +12,24 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * $Id: teamcity_messages.h 422318 2013-12-19 17:48:09Z satskyse $ + * $Id: teamcity_messages.h 500448 2016-05-04 18:16:16Z ucko $ */ #ifndef H_TEAMCITY_MESSAGES #define H_TEAMCITY_MESSAGES -#include #include +#include -namespace JetBrains { +namespace jetbrains { +namespace teamcity { std::string getFlowIdFromEnvironment(); bool underTeamcity(); class TeamcityMessages { std::ostream *m_out; - + protected: std::string escape(std::string s); @@ -37,19 +38,24 @@ protected: void closeMsg(); public: + static const bool StdErr = true; + static const bool StdOut = false; + TeamcityMessages(); - + void setOutput(std::ostream &); - - void suiteStarted(std::string name, std::string flowid = ""); - void suiteFinished(std::string name, std::string flowid = ""); - - void testStarted(std::string name, std::string flowid = ""); - void testFailed(std::string name, std::string message, std::string details, std::string flowid = ""); - void testIgnored(std::string name, std::string message, std::string flowid = ""); - void testFinished(std::string name, int durationMs = -1, std::string flowid = ""); + + void suiteStarted(std::string name, std::string flowid = std::string()); + void suiteFinished(std::string name, std::string flowid = std::string()); + + void testStarted(std::string name, std::string flowid = std::string(), bool captureStandardOutput = false); + void testFailed(std::string name, std::string message, std::string details, std::string flowid = std::string()); + void testIgnored(std::string name, std::string message, std::string flowid = std::string()); + void testOutput(std::string name, std::string output, std::string flowid, bool isStdErr = StdOut); + void testFinished(std::string name, int durationMs = -1, std::string flowid = std::string()); }; +} } #endif /* H_TEAMCITY_MESSAGES */ diff --git a/c++/src/corelib/test_boost.cpp b/c++/src/corelib/test_boost.cpp index 174758c2..6e8914b2 100644 --- a/c++/src/corelib/test_boost.cpp +++ b/c++/src/corelib/test_boost.cpp @@ -1,4 +1,4 @@ -/* $Id: test_boost.cpp 497436 2016-04-06 17:56:51Z ivanov $ +/* $Id: test_boost.cpp 520770 2016-12-01 15:44:45Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -301,7 +301,7 @@ public: virtual ~CNcbiTestsObserver(void) {} /// Method called before execution of all tests - virtual void test_start(but::counter_t /* test_cases_amount */); + // virtual void test_start(but::counter_t /* test_cases_amount */); /// Method called after execution of all tests virtual void test_finish(void); @@ -630,9 +630,9 @@ CNcbiBoostReporter::CNcbiBoostReporter() {} inline void -CNcbiBoostReporter::SetOutputFormat(but::output_format format) +CNcbiBoostReporter::SetOutputFormat(but::output_format fmt) { - if (format == but::OF_XML) { + if (fmt == but::OF_XML) { m_IsXML = true; m_Upper = new but::output::xml_report_formatter(); } @@ -897,7 +897,9 @@ CNcbiTestsTreeBuilder::EnsureDep(but::test_unit* tu, but::test_unit* tu_from) inline void CNcbiTestsTreeBuilder::FixUnitsOrder(void) { - m_RootElem->FixUnitsOrder(); + if (m_RootElem) { + m_RootElem->FixUnitsOrder(); + } } @@ -1079,6 +1081,13 @@ CNcbiTestApplication::x_EnsureAllDeps(void) inline void CNcbiTestApplication::x_ActualizeDeps(void) { +#if BOOST_VERSION >= 105900 + // Expedite run status initialization so s_IsEnabled will work. + auto master_id = but::framework::master_test_suite().p_id; + auto& state = but::framework::impl::s_frk_state(); + state.finalize_default_run_status(master_id, but::test_unit::RS_INVALID); + state.deduce_run_status(master_id); +#endif ITERATE(TUnitToManyMap, it, m_TestDeps) { but::test_unit* test = it->first; if (!m_DisabledTests.count(test) && !s_IsEnabled(*test)) { @@ -1565,10 +1574,13 @@ CNcbiTestApplication::AdjustTestTimeout(but::test_unit* tu) CNcbiEnvironment env; printf("Maximum execution time of %s seconds is exceeded", m_TimeoutStr.c_str()); -#if BOOST_VERSION >= 105900 +#if BOOST_VERSION < 105900 + throw but::test_being_aborted(); +#elif defined(SIGALRM) raise(SIGALRM); #else - throw but::test_being_aborted(); + throw runtime_error("Maximum execution time of " + m_TimeoutStr + + " seconds is exceeded"); #endif } new_timeout = (unsigned int)(m_Timeout - elapsed); @@ -1850,13 +1862,6 @@ CNcbiTestsCollector::test_suite_start(but::test_suite const& suite) return true; } - -void -CNcbiTestsObserver::test_start(but::counter_t /* test_cases_amount */) -{ - s_GetTestApp().InitTestsBeforeRun(); -} - void CNcbiTestsObserver::test_finish(void) { @@ -1994,6 +1999,10 @@ CNcbiBoostReporter::do_confirmation_report(but::test_unit const& tu, ostr << "*** Skipped some tests\n"; } } + // Boost.Test 3.x (from Boost 1.59+) treats skipped tests as errors. + // Override that treatment both here (to avoid a claim that errors + // occurred) and in main (to yield a sane exit code regardless of + // report level). const_cast(tr.p_skipped.get()) = false; const_cast(tr.p_test_cases_skipped.get()) = 0; } @@ -2229,6 +2238,8 @@ main(int argc, char* argv[]) framework::init( &init_unit_test_suite, argc, argv ); #endif + ncbi::s_GetTestApp().InitTestsBeforeRun(); + #if BOOST_VERSION >= 105900 if( RTCFG(bool, WAIT_FOR_DEBUGGER, wait_for_debugger) ) { results_reporter::get_stream() << "Press any key to continue..." << std::endl; @@ -2288,6 +2299,18 @@ main(int argc, char* argv[]) !runtime_config::no_result_code() #endif ) { +#if BOOST_VERSION >= 105900 + // Boost.Test 3.x (from Boost 1.59+) treats skipped tests + // as errors. Override that treatment both here (to yield + // a sane exit code regardless of report level) and in + // CNcbiBoostReporter::do_confirmation_report (to avoid a + // claim that errors occurred). + but::test_results const& tr + = but::results_collector.results( + framework::master_test_suite().p_id); + const_cast(tr.p_skipped.get()) = false; + const_cast(tr.p_test_cases_skipped.get()) = 0; +#endif result_code = results_collector.results( framework::master_test_suite().p_id ).result_code(); if (!NCBI_NS_NCBI::s_GetTestApp().HasTestErrors() && NCBI_NS_NCBI::s_GetTestApp().HasTestTimeouts()) diff --git a/c++/src/corelib/version.cpp b/c++/src/corelib/version.cpp index ec7250e0..2cdc97ef 100644 --- a/c++/src/corelib/version.cpp +++ b/c++/src/corelib/version.cpp @@ -1,4 +1,4 @@ -/* $Id: version.cpp 492326 2016-02-16 19:38:11Z ivanov $ +/* $Id: version.cpp 508166 2016-07-26 15:59:33Z elisovdn $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -33,6 +33,7 @@ #include #include #include +#include BEGIN_NCBI_SCOPE @@ -595,6 +596,13 @@ string CVersion::Print(const string& appname, TPrintFlags flags) const } } +#ifdef NCBI_TEAMCITY_BUILD_NUMBER + if (flags & fTCBuildNumber) { + os << " TeamCity-Build-Number: " << NCBI_TEAMCITY_BUILD_NUMBER + << endl; + } +#endif /* NCBI_TEAMCITY_BUILD_NUMBER */ + return CNcbiOstrstreamToString(os); } diff --git a/c++/src/dbapi/blobstream.cpp b/c++/src/dbapi/blobstream.cpp index 8b599df3..442510ff 100644 --- a/c++/src/dbapi/blobstream.cpp +++ b/c++/src/dbapi/blobstream.cpp @@ -1,4 +1,4 @@ -/* $Id: blobstream.cpp 498367 2016-04-15 17:18:04Z ivanov $ +/* $Id: blobstream.cpp 497635 2016-04-08 13:52:30Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -23,7 +23,7 @@ * * =========================================================================== * -* File Name: $Id: blobstream.cpp 498367 2016-04-15 17:18:04Z ivanov $ +* File Name: $Id: blobstream.cpp 497635 2016-04-08 13:52:30Z ucko $ * * Author: Michael Kholodov * diff --git a/c++/src/dbapi/blobstream.hpp b/c++/src/dbapi/blobstream.hpp index 44943b99..54dc8c10 100644 --- a/c++/src/dbapi/blobstream.hpp +++ b/c++/src/dbapi/blobstream.hpp @@ -1,7 +1,7 @@ #ifndef _BLOBSTREAM_HPP_ #define _BLOBSTREAM_HPP_ -/* $Id: blobstream.hpp 498367 2016-04-15 17:18:04Z ivanov $ +/* $Id: blobstream.hpp 497635 2016-04-08 13:52:30Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -26,7 +26,7 @@ * * =========================================================================== * -* File Name: $Id: blobstream.hpp 498367 2016-04-15 17:18:04Z ivanov $ +* File Name: $Id: blobstream.hpp 497635 2016-04-08 13:52:30Z ucko $ * * Author: Michael Kholodov * diff --git a/c++/src/dbapi/conn_impl.cpp b/c++/src/dbapi/conn_impl.cpp index 4342dc78..a4502307 100644 --- a/c++/src/dbapi/conn_impl.cpp +++ b/c++/src/dbapi/conn_impl.cpp @@ -1,4 +1,4 @@ -/* $Id: conn_impl.cpp 451412 2014-11-06 16:54:28Z ucko $ +/* $Id: conn_impl.cpp 507084 2016-07-14 16:04:41Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -23,7 +23,7 @@ * * =========================================================================== * -* File Name: $Id: conn_impl.cpp 451412 2014-11-06 16:54:28Z ucko $ +* File Name: $Id: conn_impl.cpp 507084 2016-07-14 16:04:41Z ucko $ * * Author: Michael Kholodov * @@ -64,7 +64,7 @@ CConnection::CConnection(CDataSource* ds, EOwnership ownership) CConnection::CConnection(CDB_Connection *conn, CDataSource* ds) : m_ds(ds), m_connection(conn), m_connCounter(-1), m_connUsed(false), m_modeMask(0), m_forceSingle(false), m_multiExH(0), - m_msgToEx(false) + m_msgToEx(false), m_ownership(eNoOwnership) { _TRACE("Auxiliary connection " << (void *)this << " created..."); SetIdent("CConnection"); diff --git a/c++/src/dbapi/dbapi.cpp b/c++/src/dbapi/dbapi.cpp index a9facd34..84fb2a7a 100644 --- a/c++/src/dbapi/dbapi.cpp +++ b/c++/src/dbapi/dbapi.cpp @@ -1,4 +1,4 @@ -/* $Id: dbapi.cpp 498367 2016-04-15 17:18:04Z ivanov $ +/* $Id: dbapi.cpp 497635 2016-04-08 13:52:30Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -23,7 +23,7 @@ * * =========================================================================== * -* File Name: $Id: dbapi.cpp 498367 2016-04-15 17:18:04Z ivanov $ +* File Name: $Id: dbapi.cpp 497635 2016-04-08 13:52:30Z ucko $ * * Author: Michael Kholodov * diff --git a/c++/src/dbapi/driver/dbapi_conn_factory.cpp b/c++/src/dbapi/driver/dbapi_conn_factory.cpp index b02e4551..5cda0b53 100644 --- a/c++/src/dbapi/driver/dbapi_conn_factory.cpp +++ b/c++/src/dbapi/driver/dbapi_conn_factory.cpp @@ -1,4 +1,4 @@ -/* $Id: dbapi_conn_factory.cpp 470851 2015-06-19 16:29:01Z ucko $ +/* $Id: dbapi_conn_factory.cpp 507218 2016-07-15 19:45:42Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -65,6 +65,7 @@ m_TryServerToo(false) CDBConnectionFactory::~CDBConnectionFactory(void) { + CDB_UserHandler::ClearExceptions(m_Errors); } void @@ -315,7 +316,7 @@ CDBConnectionFactory::MakeDBConnection( CDB_UserHandler::ClearExceptions(m_Errors); - CDB_Connection* t_con = NULL; + unique_ptr t_con; CRuntimeData& rt_data = GetRuntimeData(params.GetConnValidator()); TSvrRef dsp_srv = rt_data.GetDispatchedServer(params.GetServerName()); @@ -350,7 +351,7 @@ CDBConnectionFactory::MakeDBConnection( // because a named connection pool has been used before. // Dispatch server name ... - t_con = DispatchServerName(opening_ctx, params); + t_con.reset(DispatchServerName(opening_ctx, params)); } else { // Server name is already dispatched ... string single_server(params.GetParam("single_server")); @@ -361,8 +362,9 @@ CDBConnectionFactory::MakeDBConnection( // We definitely need to re-dispatch it ... // Clean previous info ... + rt_data.CleanExcluded(params.GetServerName()); rt_data.SetDispatchedServer(params.GetServerName(), TSvrRef()); - t_con = DispatchServerName(opening_ctx, params); + t_con.reset(DispatchServerName(opening_ctx, params)); } else { // We do not need to re-dispatch it ... @@ -379,9 +381,9 @@ CDBConnectionFactory::MakeDBConnection( // MakeValidConnection may return NULL here because a newly // created connection may not pass validation. - t_con = MakeValidConnection(opening_ctx, - // cur_conn_attr, - cur_params); + t_con.reset(MakeValidConnection(opening_ctx, + // cur_conn_attr, + cur_params)); } catch (CDB_Exception& ex) { // m_Errors.push_back(ex.Clone()); @@ -392,7 +394,7 @@ CDBConnectionFactory::MakeDBConnection( } } - if (!t_con) { + if (t_con.get() == NULL) { // We couldn't connect ... if (single_server != "true") { // Server might be temporarily unavailable ... @@ -404,7 +406,7 @@ CDBConnectionFactory::MakeDBConnection( } // Re-dispatch ... - t_con = DispatchServerName(opening_ctx, params); + t_con.reset(DispatchServerName(opening_ctx, params)); } } else { // Dispatched server is already set, but calling of this method @@ -418,14 +420,14 @@ CDBConnectionFactory::MakeDBConnection( ctx.SetTimeout(query_timeout); // Restore original query timeout ... - if (t_con) { + if (t_con.get() != NULL) { t_con->SetTimeout(query_timeout); } - x_LogConnection(opening_ctx, t_con, params); - handler->Flush((t_con == NULL) ? eDiagSevMax : eDiag_Warning); + x_LogConnection(opening_ctx, t_con.get(), params); + handler->Flush((t_con.get() == NULL) ? eDiagSevMax : eDiag_Warning); - return t_con; + return t_con.release(); } CDB_Connection* @@ -611,6 +613,10 @@ CDBConnectionFactory::MakeValidConnection( if (conn.get()) { + if (conn->Host() == 0) { + GetRuntimeData(params.GetConnValidator()).GetDBServiceMapper() + .RecordServer(conn->GetExtraFeatures()); + } CTrivialConnValidator use_db_validator( params.GetDatabaseName(), CTrivialConnValidator::eKeepModifiedConnection @@ -759,8 +765,11 @@ void CDBConnectionFactory::x_LogConnection(const SOpeningContext& ctx, }} extra.Print(prefix + "resource", service); + if ( !dsp_srv->GetName().empty() ) { extra.Print(prefix + "server_name", dsp_srv->GetName()); + } else if (connection != NULL && !connection->ServerName().empty()) { + extra.Print(prefix + "server_name", connection->ServerName()); } if (dsp_srv->GetHost() != 0) { @@ -768,12 +777,17 @@ void CDBConnectionFactory::x_LogConnection(const SOpeningContext& ctx, impl::ConvertN2A(dsp_srv->GetHost())); } else if (params.GetHost() != 0) { extra.Print(prefix + "server_ip", impl::ConvertN2A(params.GetHost())); + } else if (connection != NULL && connection->Host() != 0) { + extra.Print(prefix + "server_ip", + impl::ConvertN2A(connection->Host())); } if (dsp_srv->GetPort() != 0) { extra.Print(prefix + "server_port", dsp_srv->GetPort()); } else if (params.GetPort() != 0) { extra.Print(prefix + "server_port", params.GetPort()); + } else if (connection != NULL && connection->Port() != 0) { + extra.Print(prefix + "server_port", connection->Port()); } if ( !params.GetUserName().empty() ) { diff --git a/c++/src/dbapi/driver/dbapi_driver_conn_mgr.cpp b/c++/src/dbapi/driver/dbapi_driver_conn_mgr.cpp index 9a420dbb..4d57b0ac 100644 --- a/c++/src/dbapi/driver/dbapi_driver_conn_mgr.cpp +++ b/c++/src/dbapi/driver/dbapi_driver_conn_mgr.cpp @@ -1,4 +1,4 @@ -/* $Id: dbapi_driver_conn_mgr.cpp 494592 2016-03-08 17:55:58Z ivanov $ +/* $Id: dbapi_driver_conn_mgr.cpp 494417 2016-03-07 15:06:35Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/dbapi/driver/dbapi_driver_conn_params.cpp b/c++/src/dbapi/driver/dbapi_driver_conn_params.cpp index 2b76a0a4..f0ab89e5 100644 --- a/c++/src/dbapi/driver/dbapi_driver_conn_params.cpp +++ b/c++/src/dbapi/driver/dbapi_driver_conn_params.cpp @@ -1,4 +1,4 @@ -/* $Id: dbapi_driver_conn_params.cpp 488796 2016-01-05 20:20:40Z ucko $ +/* $Id: dbapi_driver_conn_params.cpp 515776 2016-10-05 17:33:35Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -729,6 +729,7 @@ CCPPToolkitConnParams::GetServerType(const CTempString& server_name) if (NStr::CompareNocase(server_name, 0, 8, "DBAPI_MS") == 0 || NStr::CompareNocase(server_name, 0, 5, "MSSQL") == 0 || NStr::CompareNocase(server_name, 0, 5, "MSDEV") == 0 + || NStr::CompareNocase(server_name, 0, 9, "MS2008DEV") == 0 || NStr::CompareNocase(server_name, 0, 7, "OAMSDEV") == 0 || NStr::CompareNocase(server_name, 0, 6, "QMSSQL") == 0 || NStr::CompareNocase(server_name, 0, 6, "BLASTQ") == 0 diff --git a/c++/src/dbapi/driver/dbapi_driver_utils.cpp b/c++/src/dbapi/driver/dbapi_driver_utils.cpp index 20ae4dda..be70dd64 100644 --- a/c++/src/dbapi/driver/dbapi_driver_utils.cpp +++ b/c++/src/dbapi/driver/dbapi_driver_utils.cpp @@ -1,4 +1,4 @@ -/* $Id: dbapi_driver_utils.cpp 487444 2015-12-17 18:38:53Z ucko $ +/* $Id: dbapi_driver_utils.cpp 503691 2016-06-07 15:44:43Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -99,6 +99,37 @@ SIZE_TYPE GetValidUTF8Len(const CTempString& ts) return len; } +size_t binary_to_hex_string(char* buffer, size_t buffer_size, + const void* value, size_t value_size, + TBinaryToHexFlags flags) +{ + static const char s_HexDigits[] = "0123456789ABCDEF"; + + const unsigned char* c = (const unsigned char*) value; + size_t i = 0, margin = 0; + if ((flags & fB2H_NoFinalNul) == 0) { + margin += 1; + } + if ((flags & fB2H_NoPrefix) == 0) { + margin += 2; + } + if (value_size * 2 + margin > buffer_size) { + return 0; + } + if ((flags & fB2H_NoPrefix) == 0) { + buffer[i++] = '0'; + buffer[i++] = 'x'; + } + for (size_t j = 0; j < value_size; j++) { + buffer[i++] = s_HexDigits[c[j] >> 4]; + buffer[i++] = s_HexDigits[c[j] & 0x0F]; + } + if ((flags & fB2H_NoFinalNul) == 0) { + buffer[i + 1] = '\0'; + } + return i; +} + //////////////////////////////////////////////////////////////////////////////// CDBBindedParams::CDBBindedParams(CDB_Params& bindings, EOwnership ownership) : m_Bindings(&bindings, ownership) diff --git a/c++/src/dbapi/driver/dbapi_impl_cmd.cpp b/c++/src/dbapi/driver/dbapi_impl_cmd.cpp index 7c1eb810..e6d8e8ef 100644 --- a/c++/src/dbapi/driver/dbapi_impl_cmd.cpp +++ b/c++/src/dbapi/driver/dbapi_impl_cmd.cpp @@ -1,4 +1,4 @@ -/* $Id: dbapi_impl_cmd.cpp 498367 2016-04-15 17:18:04Z ivanov $ +/* $Id: dbapi_impl_cmd.cpp 497635 2016-04-08 13:52:30Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/dbapi/driver/dbapi_impl_connection.cpp b/c++/src/dbapi/driver/dbapi_impl_connection.cpp index b8f62982..254f5cb5 100644 --- a/c++/src/dbapi/driver/dbapi_impl_connection.cpp +++ b/c++/src/dbapi/driver/dbapi_impl_connection.cpp @@ -1,4 +1,4 @@ -/* $Id: dbapi_impl_connection.cpp 498367 2016-04-15 17:18:04Z ivanov $ +/* $Id: dbapi_impl_connection.cpp 512261 2016-08-29 17:14:32Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -98,6 +98,7 @@ CConnection::CConnection(CDriverContext& dc, , m_ExceptionContext(new TDbgInfo(params)) , m_ServerType(params.GetServerType()) , m_ServerTypeIsKnown(false) +, m_RequestedServer(params.GetServerName()) , m_Host(params.GetHost()) , m_Port(params.GetPort()) , m_Passwd(params.GetPassword()) @@ -397,6 +398,16 @@ string CConnection::GetDriverName(void) const return GetCDriverContext().GetDriverName(); } +void CConnection::x_RecordServer(const CDBServer& server) +{ + string new_name = ServerName().substr(0, ServerName().find(':')) + + '@' + server.GetName(); + _TRACE("Updating server metadata from " << ServerName() << '@' + << ConvertN2A(m_Host) << ':' << m_Port << " to " << new_name); + m_ExceptionContext->server_name = new_name; + m_Host = server.GetHost(); + m_Port = server.GetPort(); +} } // namespace impl diff --git a/c++/src/dbapi/driver/dbapi_impl_context.cpp b/c++/src/dbapi/driver/dbapi_impl_context.cpp index c0da2cb1..7fabedb2 100644 --- a/c++/src/dbapi/driver/dbapi_impl_context.cpp +++ b/c++/src/dbapi/driver/dbapi_impl_context.cpp @@ -1,4 +1,4 @@ -/* $Id: dbapi_impl_context.cpp 498367 2016-04-15 17:18:04Z ivanov $ +/* $Id: dbapi_impl_context.cpp 516380 2016-10-13 11:32:10Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -63,9 +63,7 @@ namespace impl // CDriverContext::CDriverContext(void) : -#ifdef NCBI_THREADS m_PoolSem(0, 1), -#endif m_LoginTimeout(0), m_Timeout(0), m_CancelTimeout(0), @@ -78,7 +76,9 @@ CDriverContext::CDriverContext(void) : CDriverContext::~CDriverContext(void) { - return; + try { + DeleteAllConn(); + } STD_CATCH_ALL("CDriverContext::DeleteAllConn"); } void @@ -270,7 +270,7 @@ void CDriverContext::ResetEnvSybase(void) void CDriverContext::x_Recycle(CConnection* conn, bool conn_reusable) { - CMutexGuard mg(x_GetCtxMtx()); + CMutexGuard mg(m_PoolMutex); TConnPool::iterator it = find(m_InUse.begin(), m_InUse.end(), conn); @@ -310,7 +310,7 @@ void CDriverContext::x_Recycle(CConnection* conn, bool conn_reusable) void CDriverContext::CloseUnusedConnections(const string& srv_name, const string& pool_name) { - CMutexGuard mg(x_GetCtxMtx()); + CMutexGuard mg(m_PoolMutex); TConnPool::value_type con; @@ -318,7 +318,9 @@ void CDriverContext::CloseUnusedConnections(const string& srv_name, NON_CONST_ITERATE(TConnPool, it, m_NotInUse) { con = *it; - if((!srv_name.empty()) && srv_name.compare(con->ServerName())) continue; + if ( !srv_name.empty() && srv_name != con->ServerName() + && srv_name != con->GetRequestedServer() ) + continue; if((!pool_name.empty()) && pool_name.compare(con->PoolName())) continue; it = m_NotInUse.erase(it); @@ -330,7 +332,7 @@ void CDriverContext::CloseUnusedConnections(const string& srv_name, unsigned int CDriverContext::NofConnections(const TSvrRef& svr_ref, const string& pool_name) const { - CMutexGuard mg(x_GetCtxMtx()); + CMutexGuard mg(m_PoolMutex); if ((!svr_ref || !svr_ref->IsValid()) && pool_name.empty()) { return static_cast(m_InUse.size() + m_NotInUse.size()); @@ -352,7 +354,8 @@ unsigned int CDriverContext::NofConnections(const TSvrRef& svr_ref, ITERATE(TConnPool, it, (*pools[i])) { TConnPool::value_type con = *it; if(!server.empty()) { - if (server.compare(con->ServerName())) + if (server != con->ServerName() + && server != con->GetRequestedServer()) continue; } else if (host != 0) { @@ -377,6 +380,7 @@ unsigned int CDriverContext::NofConnections(const string& srv_name, CDB_Connection* CDriverContext::MakeCDBConnection(CConnection* connection) { connection->m_CleanupTime.Clear(); + CMutexGuard mg(m_PoolMutex); m_InUse.push_back(connection); return new CDB_Connection(connection); @@ -403,7 +407,7 @@ CDB_Connection* CDriverContext::MakePooledConnection(const CDBConnParams& params) { if (params.GetParam("is_pooled") == "true") { - CMutexGuard mg(x_GetCtxMtx()); + CMutexGuard mg(m_PoolMutex); string pool_name(params.GetParam("pool_name")); if (!m_NotInUse.empty()) { @@ -434,8 +438,8 @@ CDriverContext::MakePooledConnection(const CDBConnParams& params) } } else { - - if ( params.GetServerName().empty() ) { + string server_name = params.GetServerName(); + if ( server_name.empty() ) { return NULL; } @@ -443,7 +447,8 @@ CDriverContext::MakePooledConnection(const CDBConnParams& params) ERASE_ITERATE(TConnPool, it, m_NotInUse) { CConnection* t_con(*it); - if (params.GetServerName() == t_con->ServerName()) { + if (server_name == t_con->ServerName() + || server_name == t_con->GetRequestedServer()) { it = m_NotInUse.erase(it); if (t_con->Refresh()) { /* Future development ... @@ -487,7 +492,7 @@ CDriverContext::MakePooledConnection(const CDBConnParams& params) m_PoolSemSubject = pool_name; mg.Release(); if (m_PoolSem.TryWait(timeout)) { - mg.Guard(x_GetCtxMtx()); + mg.Guard(m_PoolMutex); CConnection* t_con = NULL; NON_CONST_REVERSE_ITERATE(TConnPool, it, m_NotInUse) { if (*it == m_PoolSemConn) { @@ -546,6 +551,7 @@ CDriverContext::MakePooledConnection(const CDBConnParams& params) void CDriverContext::CloseAllConn(void) { + CMutexGuard mg(m_PoolMutex); // close all connections first ITERATE(TConnPool, it, m_NotInUse) { delete *it; @@ -560,6 +566,7 @@ CDriverContext::CloseAllConn(void) void CDriverContext::DeleteAllConn(void) { + CMutexGuard mg(m_PoolMutex); // close all connections first ITERATE(TConnPool, it, m_NotInUse) { delete *it; @@ -867,6 +874,12 @@ CDriverContext::ReadDBConfParams(const string& service_name, params->pool_allow_temp_overflow = reg.Get(section_name, "conn_pool_allow_temp_overflow"); } + if (reg.HasEntry(section_name, "continue_after_raiserror", + IRegistry::fCountCleared)) { + params->flags += SDBConfParams::fContRaiserrorSet; + params->continue_after_raiserror + = reg.Get(section_name, "continue_after_raiserror"); + } if (reg.HasEntry(section_name, "args", IRegistry::fCountCleared)) { params->flags += SDBConfParams::fArgsSet; params->args = reg.Get(section_name, "args"); @@ -876,7 +889,7 @@ CDriverContext::ReadDBConfParams(const string& service_name, bool CDriverContext::SatisfyPoolMinimum(const CDBConnParams& params) { - CMutexGuard mg(x_GetCtxMtx()); + CMutexGuard mg(m_PoolMutex); string pool_min_str = params.GetParam("pool_minsize"); if (pool_min_str.empty() || pool_min_str == "default") @@ -930,7 +943,7 @@ CDriverContext::MakeConnection(const CDBConnParams& params) int was_timeout = GetTimeout(); int was_login_timeout = GetLoginTimeout(); - CDB_Connection* t_con = NULL; + unique_ptr t_con; try { string server_name = (conf_params.IsServerSet()? conf_params.server: params.GetServerName()); @@ -1053,6 +1066,21 @@ CDriverContext::MakeConnection(const CDBConnParams& params) else if (params.GetParam("pool_allow_temp_overflow") == "default") { act_params.SetParam("pool_allow_temp_overflow", "false"); } + if (conf_params.IsContinueAfterRaiserrorSet()) { + if (conf_params.continue_after_raiserror.empty()) { + act_params.SetParam("continue_after_raiserror", "false"); + } + else { + act_params.SetParam + ("continue_after_raiserror", + NStr::BoolToString( + NStr::StringToBool( + conf_params.continue_after_raiserror))); + } + } + else if (params.GetParam("continue_after_raiserror") == "default") { + act_params.SetParam("continue_after_raiserror", "false"); + } s_TransformLoginData(server_name, user_name, db_name, password); act_params.SetServerName(server_name); @@ -1061,13 +1089,13 @@ CDriverContext::MakeConnection(const CDBConnParams& params) act_params.SetPassword(password); CRef factory = CDbapiConnMgr::Instance().GetConnectionFactory(); - t_con = factory->MakeDBConnection(*this, act_params); + t_con.reset(factory->MakeDBConnection(*this, act_params)); - if((!t_con && act_params.GetParam("do_not_connect") == "true")) { - return NULL; - } + if (t_con.get() == NULL) { + if (act_params.GetParam("do_not_connect") == "true") { + return NULL; + } - if (!t_con) { string err; err += "Cannot connect to the server '" + act_params.GetServerName(); err += "' as user '" + act_params.GetUserName() + "'"; @@ -1094,12 +1122,12 @@ CDriverContext::MakeConnection(const CDBConnParams& params) SetTimeout(was_timeout); SetLoginTimeout(was_login_timeout); - return t_con; + return t_con.release(); } void CDriverContext::CloseConnsForPool(const string& pool_name) { - CMutexGuard mg(x_GetCtxMtx()); + CMutexGuard mg(m_PoolMutex); ITERATE(TConnPool, it, m_InUse) { CConnection* t_con(*it); @@ -1120,6 +1148,7 @@ void CDriverContext::CloseConnsForPool(const string& pool_name) void CDriverContext::CloseOldIdleConns(unsigned int max_closings, const string& pool_name) { + CMutexGuard mg(m_PoolMutex); if (max_closings == 0) { return; } diff --git a/c++/src/dbapi/driver/dbapi_object_convert.cpp b/c++/src/dbapi/driver/dbapi_object_convert.cpp index ad50f70c..aaee44ba 100644 --- a/c++/src/dbapi/driver/dbapi_object_convert.cpp +++ b/c++/src/dbapi/driver/dbapi_object_convert.cpp @@ -1,4 +1,4 @@ -/* $Id: dbapi_object_convert.cpp 498375 2016-04-15 17:20:50Z ivanov $ +/* $Id: dbapi_object_convert.cpp 498292 2016-04-14 19:07:55Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/dbapi/driver/dbapi_svc_mapper.cpp b/c++/src/dbapi/driver/dbapi_svc_mapper.cpp index ecd741cc..7b2fa0ad 100644 --- a/c++/src/dbapi/driver/dbapi_svc_mapper.cpp +++ b/c++/src/dbapi/driver/dbapi_svc_mapper.cpp @@ -1,4 +1,4 @@ -/* $Id: dbapi_svc_mapper.cpp 485360 2015-11-20 17:03:34Z ucko $ +/* $Id: dbapi_svc_mapper.cpp 506715 2016-07-11 16:01:42Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -254,6 +254,19 @@ CDBServiceMapperCoR::GetServersList(const string& service, list* serv_li } +bool +CDBServiceMapperCoR::RecordServer(I_ConnectionExtra& extra) const +{ + CFastMutexGuard mg(m_Mtx); + REVERSE_ITERATE (TDelegates, dg_it, m_Delegates) { + if ((*dg_it)->RecordServer(extra)) { + return true; + } + } + return false; +} + + void CDBServiceMapperCoR::ConfigureFromRegistry(const IRegistry* registry) { @@ -721,7 +734,8 @@ CDBUDPriorityMapper::Exclude(const string& service, void CDBUDPriorityMapper::CleanExcluded(const string& service) { - CNcbiDiag::DiagTrouble(DIAG_COMPILE_INFO, "Not implemented"); + CFastMutexGuard mg(m_Mtx); + m_ServiceUsageMap[service] = m_OrigServiceUsageMap[service]; } void @@ -753,6 +767,7 @@ CDBUDPriorityMapper::Add(const string& service, { TSvrMap& server_list = m_ServerMap[service]; TServerUsageMap& usage_map = m_ServiceUsageMap[service]; + TServerUsageMap& usage_map2 = m_OrigServiceUsageMap[service]; if (preference < 0) { preference = 0; @@ -763,10 +778,9 @@ CDBUDPriorityMapper::Add(const string& service, server_list.insert( TSvrMap::value_type(server, preference) ); - usage_map.insert(TServerUsageMap::value_type( - 100 - preference, - server) - ); + TServerUsageMap::value_type usage(100 - preference, server); + usage_map.insert(usage); + usage_map2.insert(usage); } diff --git a/c++/src/dbapi/driver/interfaces.cpp b/c++/src/dbapi/driver/interfaces.cpp index 2f73e978..3c134c5f 100644 --- a/c++/src/dbapi/driver/interfaces.cpp +++ b/c++/src/dbapi/driver/interfaces.cpp @@ -1,4 +1,4 @@ -/* $Id: interfaces.cpp 498367 2016-04-15 17:18:04Z ivanov $ +/* $Id: interfaces.cpp 501779 2016-05-18 19:36:43Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -343,10 +343,6 @@ I_Connection::~I_Connection(void) } -I_ConnectionExtra::~I_ConnectionExtra(void) -{} - - END_NCBI_SCOPE diff --git a/c++/src/dbapi/driver/memory_store.cpp b/c++/src/dbapi/driver/memory_store.cpp index ecdf9e9d..4192f61f 100644 --- a/c++/src/dbapi/driver/memory_store.cpp +++ b/c++/src/dbapi/driver/memory_store.cpp @@ -1,4 +1,4 @@ -/* $Id: memory_store.cpp 498375 2016-04-15 17:20:50Z ivanov $ +/* $Id: memory_store.cpp 498292 2016-04-14 19:07:55Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/dbapi/driver/memory_store.hpp b/c++/src/dbapi/driver/memory_store.hpp index f5e89232..2e2c7c2d 100644 --- a/c++/src/dbapi/driver/memory_store.hpp +++ b/c++/src/dbapi/driver/memory_store.hpp @@ -1,7 +1,7 @@ #ifndef DBAPI_DRIVER___MEMORY_STORE__HPP #define DBAPI_DRIVER___MEMORY_STORE__HPP -/* $Id: memory_store.hpp 498375 2016-04-15 17:20:50Z ivanov $ +/* $Id: memory_store.hpp 498292 2016-04-14 19:07:55Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/dbapi/driver/odbc/bcp.cpp b/c++/src/dbapi/driver/odbc/bcp.cpp index bee0c8e9..a518c01b 100644 --- a/c++/src/dbapi/driver/odbc/bcp.cpp +++ b/c++/src/dbapi/driver/odbc/bcp.cpp @@ -1,4 +1,4 @@ -/* $Id: bcp.cpp 498375 2016-04-15 17:20:50Z ivanov $ +/* $Id: bcp.cpp 498292 2016-04-14 19:07:55Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/dbapi/driver/odbc/connection.cpp b/c++/src/dbapi/driver/odbc/connection.cpp index b141ca3b..62889843 100644 --- a/c++/src/dbapi/driver/odbc/connection.cpp +++ b/c++/src/dbapi/driver/odbc/connection.cpp @@ -1,4 +1,4 @@ -/* $Id: connection.cpp 498375 2016-04-15 17:20:50Z ivanov $ +/* $Id: connection.cpp 499728 2016-04-27 19:40:54Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -1504,6 +1504,27 @@ CStatementBase::x_GetData(const CDB_Object& param, } break; case eDB_VarCharMax: +#ifdef UNICODE + if( !param.IsNULL() ) { + CDB_Stream& par = static_cast + (const_cast(param)); + size_t n = par.Size(); + AutoArray raw_data(n); + par.MoveTo(0); + _VERIFY(par.Read(raw_data.get(), n) == n); + CStringUTF8 utf_data + = CUtf8::AsUTF8(CTempString(raw_data.get(), n), + GetClientEncoding()); + raw_data.reset(); + wstring wdata = CUtf8::AsBasicString(utf_data); + utf_data.clear(); + n = wdata.size() * sizeof(TSqlChar); + data = bind_guard.Alloc(n); + memcpy(data, wdata.data(), n); + } + break; +// else fall through +#endif case eDB_VarBinaryMax: if( !param.IsNULL() ) { CDB_Stream& par = static_cast diff --git a/c++/src/dbapi/driver/odbc/cursor.cpp b/c++/src/dbapi/driver/odbc/cursor.cpp index 209e793b..a27fb3a3 100644 --- a/c++/src/dbapi/driver/odbc/cursor.cpp +++ b/c++/src/dbapi/driver/odbc/cursor.cpp @@ -1,4 +1,4 @@ -/* $Id: cursor.cpp 498375 2016-04-15 17:20:50Z ivanov $ +/* $Id: cursor.cpp 498292 2016-04-14 19:07:55Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/dbapi/driver/odbc/result.cpp b/c++/src/dbapi/driver/odbc/result.cpp index 7de91be5..c31d424d 100644 --- a/c++/src/dbapi/driver/odbc/result.cpp +++ b/c++/src/dbapi/driver/odbc/result.cpp @@ -1,4 +1,4 @@ -/* $Id: result.cpp 498375 2016-04-15 17:20:50Z ivanov $ +/* $Id: result.cpp 498292 2016-04-14 19:07:55Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/dbapi/driver/public.cpp b/c++/src/dbapi/driver/public.cpp index 88cdd15d..258f9a2d 100644 --- a/c++/src/dbapi/driver/public.cpp +++ b/c++/src/dbapi/driver/public.cpp @@ -1,4 +1,4 @@ -/* $Id: public.cpp 498367 2016-04-15 17:18:04Z ivanov $ +/* $Id: public.cpp 497635 2016-04-08 13:52:30Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/dbapi/driver/types.cpp b/c++/src/dbapi/driver/types.cpp index 7bbbb67b..2a98f494 100644 --- a/c++/src/dbapi/driver/types.cpp +++ b/c++/src/dbapi/driver/types.cpp @@ -1,4 +1,4 @@ -/* $Id: types.cpp 498375 2016-04-15 17:20:50Z ivanov $ +/* $Id: types.cpp 498292 2016-04-14 19:07:55Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/dbapi/driver_mgr.cpp b/c++/src/dbapi/driver_mgr.cpp index 5399a643..a284b42b 100644 --- a/c++/src/dbapi/driver_mgr.cpp +++ b/c++/src/dbapi/driver_mgr.cpp @@ -1,4 +1,4 @@ -/* $Id: driver_mgr.cpp 497437 2016-04-06 17:56:55Z ivanov $ +/* $Id: driver_mgr.cpp 497217 2016-04-05 11:37:33Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -23,7 +23,7 @@ * * =========================================================================== * -* File Name: $Id: driver_mgr.cpp 497437 2016-04-06 17:56:55Z ivanov $ +* File Name: $Id: driver_mgr.cpp 497217 2016-04-05 11:37:33Z ivanov $ * * Author: Michael Kholodov, Denis Vakatov * diff --git a/c++/src/dbapi/rs_impl.cpp b/c++/src/dbapi/rs_impl.cpp index 5dbee975..59770e08 100644 --- a/c++/src/dbapi/rs_impl.cpp +++ b/c++/src/dbapi/rs_impl.cpp @@ -1,4 +1,4 @@ -/* $Id: rs_impl.cpp 498375 2016-04-15 17:20:50Z ivanov $ +/* $Id: rs_impl.cpp 498292 2016-04-14 19:07:55Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -23,7 +23,7 @@ * * =========================================================================== * -* File Name: $Id: rs_impl.cpp 498375 2016-04-15 17:20:50Z ivanov $ +* File Name: $Id: rs_impl.cpp 498292 2016-04-14 19:07:55Z ucko $ * * Author: Michael Kholodov * diff --git a/c++/src/dbapi/rw_impl.cpp b/c++/src/dbapi/rw_impl.cpp index dcb00d41..8d0e7e26 100644 --- a/c++/src/dbapi/rw_impl.cpp +++ b/c++/src/dbapi/rw_impl.cpp @@ -1,4 +1,4 @@ -/* $Id: rw_impl.cpp 498367 2016-04-15 17:18:04Z ivanov $ +/* $Id: rw_impl.cpp 497635 2016-04-08 13:52:30Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/dbapi/rw_impl.hpp b/c++/src/dbapi/rw_impl.hpp index 020ba6f5..2ccbe88d 100644 --- a/c++/src/dbapi/rw_impl.hpp +++ b/c++/src/dbapi/rw_impl.hpp @@ -1,7 +1,7 @@ #ifndef _RW_IMPL_HPP_ #define _RW_IMPL_HPP_ -/* $Id: rw_impl.hpp 498367 2016-04-15 17:18:04Z ivanov $ +/* $Id: rw_impl.hpp 497635 2016-04-08 13:52:30Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE diff --git a/c++/src/dbapi/stmt_impl.cpp b/c++/src/dbapi/stmt_impl.cpp index 64d2062a..4f468ca7 100644 --- a/c++/src/dbapi/stmt_impl.cpp +++ b/c++/src/dbapi/stmt_impl.cpp @@ -1,4 +1,4 @@ -/* $Id: stmt_impl.cpp 498367 2016-04-15 17:18:04Z ivanov $ +/* $Id: stmt_impl.cpp 497635 2016-04-08 13:52:30Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -23,7 +23,7 @@ * * =========================================================================== * -* File Name: $Id: stmt_impl.cpp 498367 2016-04-15 17:18:04Z ivanov $ +* File Name: $Id: stmt_impl.cpp 497635 2016-04-08 13:52:30Z ucko $ * * Author: Michael Kholodov * diff --git a/c++/src/dbapi/stmt_impl.hpp b/c++/src/dbapi/stmt_impl.hpp index fde06c5f..282be163 100644 --- a/c++/src/dbapi/stmt_impl.hpp +++ b/c++/src/dbapi/stmt_impl.hpp @@ -1,7 +1,7 @@ #ifndef _STMT_IMPL_HPP_ #define _STMT_IMPL_HPP_ -/* $Id: stmt_impl.hpp 498367 2016-04-15 17:18:04Z ivanov $ +/* $Id: stmt_impl.hpp 497635 2016-04-08 13:52:30Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -26,7 +26,7 @@ * * =========================================================================== * -* File Name: $Id: stmt_impl.hpp 498367 2016-04-15 17:18:04Z ivanov $ +* File Name: $Id: stmt_impl.hpp 497635 2016-04-08 13:52:30Z ucko $ * * Author: Michael Kholodov * diff --git a/c++/src/dbapi/variant.cpp b/c++/src/dbapi/variant.cpp index 3d4025f8..f3558f4a 100644 --- a/c++/src/dbapi/variant.cpp +++ b/c++/src/dbapi/variant.cpp @@ -1,4 +1,4 @@ -/* $Id: variant.cpp 498375 2016-04-15 17:20:50Z ivanov $ +/* $Id: variant.cpp 498292 2016-04-14 19:07:55Z ucko $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -23,7 +23,7 @@ * * =========================================================================== * -* File Name: $Id: variant.cpp 498375 2016-04-15 17:20:50Z ivanov $ +* File Name: $Id: variant.cpp 498292 2016-04-14 19:07:55Z ucko $ * * Author: Michael Kholodov * diff --git a/c++/src/html/indentstream.cpp b/c++/src/html/indentstream.cpp index a6f9cb13..e2d4d8b5 100644 --- a/c++/src/html/indentstream.cpp +++ b/c++/src/html/indentstream.cpp @@ -1,4 +1,4 @@ -/* $Id: indentstream.cpp 103491 2007-05-04 17:18:18Z kazimird $ +/* $Id: indentstream.cpp 501456 2016-05-16 15:12:46Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -190,7 +190,7 @@ CT_INT_TYPE CIndentingStreambuf::uflow(void) CT_INT_TYPE CIndentingStreambuf::pbackfail(CT_INT_TYPE c) { - return (CT_EQ_INT_TYPE(c, CT_EOF) ? CT_EOF : m_Buf->sputbackc(c)); + return (CT_EQ_INT_TYPE(c, CT_EOF) ? CT_EOF : m_Buf->sputbackc((char)c)); } diff --git a/c++/src/html/selection.cpp b/c++/src/html/selection.cpp index ce999dd0..030c6a0e 100644 --- a/c++/src/html/selection.cpp +++ b/c++/src/html/selection.cpp @@ -1,4 +1,4 @@ -/* $Id: selection.cpp 367926 2012-06-29 14:04:54Z ivanov $ +/* $Id: selection.cpp 501456 2016-05-16 15:12:46Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -55,7 +55,7 @@ CSelection::CSelection(const CCgiRequest& request, found = values.find(checkboxName); if ( found != values.end() ) { for ( TCgiEntriesCI i = values.lower_bound(checkboxName), - end = values.upper_bound(checkboxName); i != end; ++i ) { + iend = values.upper_bound(checkboxName); i != iend; ++i ) { AddID(NStr::StringToInt(string(i->second))); } } diff --git a/c++/src/misc/CMakeLists.txt b/c++/src/misc/CMakeLists.txt new file mode 100644 index 00000000..087ff6aa --- /dev/null +++ b/c++/src/misc/CMakeLists.txt @@ -0,0 +1,22 @@ +############################################################################## +# CMakeLists.txt autogenerated from /export/home/dicuccio/cpp-cmake/cpp-cmake/src/misc/Makefile.in +# + +# Include projects from this directory + +# Recurse subdirectories +add_subdirectory_optional(third_party) +add_subdirectory_optional(third_party_static) +add_subdirectory_optional(clog) +add_subdirectory_optional(grid_cgi) +add_subdirectory_optional(xmlwrapp) +add_subdirectory_optional(eutils_client) +add_subdirectory_optional(hydra_client) +add_subdirectory_optional(discrepancy_report) +add_subdirectory_optional(discrepancy) +add_subdirectory_optional(xmlreaders) +add_subdirectory_optional(hgvs) +add_subdirectory_optional(netstorage) +add_subdirectory_optional(jsonwrapp) +add_subdirectory_optional(biosample_util) +add_subdirectory_optional(data_loaders_util) diff --git a/c++/src/misc/Makefile.in b/c++/src/misc/Makefile.in new file mode 100644 index 00000000..933d731b --- /dev/null +++ b/c++/src/misc/Makefile.in @@ -0,0 +1,10 @@ +# $Id: Makefile.in 506528 2016-07-08 11:48:54Z dicuccio $ + +SUB_PROJ = third_party third_party_static clog grid_cgi xmlwrapp \ + eutils_client hydra_client discrepancy_report discrepancy xmlreaders \ + hgvs netstorage jsonwrapp biosample_util \ + data_loaders_util lapackwrapp +EXPENDABLE_SUB_PROJ = cgi_redirect + +srcdir = @srcdir@ +include @builddir@/Makefile.meta diff --git a/c++/src/misc/third_party/CMakeLists.txt b/c++/src/misc/third_party/CMakeLists.txt new file mode 100644 index 00000000..de7e2243 --- /dev/null +++ b/c++/src/misc/third_party/CMakeLists.txt @@ -0,0 +1,6 @@ +############################################################################## +# CMakeLists.txt autogenerated from /export/home/dicuccio/cpp-cmake/cpp-cmake.2015-01-24/src/misc/third_party/Makefile.in +# + +# Include projects from this directory + diff --git a/c++/src/misc/third_party/Makefile.in b/c++/src/misc/third_party/Makefile.in new file mode 100644 index 00000000..f4ab5fed --- /dev/null +++ b/c++/src/misc/third_party/Makefile.in @@ -0,0 +1,10 @@ +################################# +# $Id: Makefile.in 107069 2007-07-11 13:46:21Z gouriano $ +# Author: Viatcheslav Gorelenkov +################################# + +MSVC_PROJ = third_party_dll_install third_party_msvcdll_install +REQUIRES = DLL + +srcdir = @srcdir@ +include @builddir@/Makefile.meta diff --git a/c++/src/misc/third_party/Makefile.third_party_dll_install.msvcproj b/c++/src/misc/third_party/Makefile.third_party_dll_install.msvcproj new file mode 100644 index 00000000..c456640d --- /dev/null +++ b/c++/src/misc/third_party/Makefile.third_party_dll_install.msvcproj @@ -0,0 +1,11 @@ +# $Id: Makefile.third_party_dll_install.msvcproj 216394 2010-12-09 16:54:20Z gouriano $ + +MSVC_PROJ = third_party_dll_install + +APP_DEP = + +DLL_DEP = + +VCPROJ = $(msvc_prj)\dll\third_party_dll_install.vcproj +VCXPROJ = $(msvc_prj)\dll\third_party_dll_install.vcxproj + diff --git a/c++/src/misc/third_party/Makefile.third_party_dll_install.msvcproj.msvc b/c++/src/misc/third_party/Makefile.third_party_dll_install.msvcproj.msvc new file mode 100644 index 00000000..b14ca76c --- /dev/null +++ b/c++/src/misc/third_party/Makefile.third_party_dll_install.msvcproj.msvc @@ -0,0 +1,4 @@ +# $Id: Makefile.third_party_dll_install.msvcproj.msvc 107885 2007-07-30 15:34:21Z kazimird $ + +[Common] +ProjectGUID = {9E4B5381-9B6C-4867-BF8A-F1AAA1FD580F} \ No newline at end of file diff --git a/c++/src/misc/third_party/Makefile.third_party_msvcdll_install.msvcproj b/c++/src/misc/third_party/Makefile.third_party_msvcdll_install.msvcproj new file mode 100644 index 00000000..6caaba94 --- /dev/null +++ b/c++/src/misc/third_party/Makefile.third_party_msvcdll_install.msvcproj @@ -0,0 +1,11 @@ +# $Id: Makefile.third_party_msvcdll_install.msvcproj 216394 2010-12-09 16:54:20Z gouriano $ + +MSVC_PROJ = third_party_msvcdll_install + +APP_DEP = + +DLL_DEP = + +VCPROJ = $(msvc_prj)\dll\third_party_msvcdll_install.vcproj +VCXPROJ = $(msvc_prj)\dll\third_party_msvcdll_install.vcxproj + diff --git a/c++/src/misc/third_party_static/CMakeLists.txt b/c++/src/misc/third_party_static/CMakeLists.txt new file mode 100644 index 00000000..fbec35ce --- /dev/null +++ b/c++/src/misc/third_party_static/CMakeLists.txt @@ -0,0 +1,6 @@ +############################################################################## +# CMakeLists.txt autogenerated from /export/home/dicuccio/cpp-cmake/cpp-cmake.2015-01-24/src/misc/third_party_static/Makefile.in +# + +# Include projects from this directory + diff --git a/c++/src/misc/third_party_static/Makefile.in b/c++/src/misc/third_party_static/Makefile.in new file mode 100644 index 00000000..4440e887 --- /dev/null +++ b/c++/src/misc/third_party_static/Makefile.in @@ -0,0 +1,10 @@ +################################# +# $Id: Makefile.in 107069 2007-07-11 13:46:21Z gouriano $ +# Author: Viatcheslav Gorelenkov +################################# + +MSVC_PROJ = third_party_static_install third_party_msvcstatic_install +REQUIRES = -DLL + +srcdir = @srcdir@ +include @builddir@/Makefile.meta diff --git a/c++/src/misc/third_party_static/Makefile.third_party_msvcstatic_install.msvcproj b/c++/src/misc/third_party_static/Makefile.third_party_msvcstatic_install.msvcproj new file mode 100644 index 00000000..9c6ebf3f --- /dev/null +++ b/c++/src/misc/third_party_static/Makefile.third_party_msvcstatic_install.msvcproj @@ -0,0 +1,11 @@ +# $Id: Makefile.third_party_msvcstatic_install.msvcproj 196847 2010-07-09 13:40:18Z gouriano $ + +MSVC_PROJ = third_party_msvcstatic_install + +APP_DEP = + +DLL_DEP = + +VCPROJ = $(msvc_prj)\static\third_party_msvcstatic_install.vcproj +VCXPROJ = $(msvc_prj)\static\third_party_msvcstatic_install.vcxproj + diff --git a/c++/src/misc/third_party_static/Makefile.third_party_static_install.msvcproj b/c++/src/misc/third_party_static/Makefile.third_party_static_install.msvcproj new file mode 100644 index 00000000..c68b712b --- /dev/null +++ b/c++/src/misc/third_party_static/Makefile.third_party_static_install.msvcproj @@ -0,0 +1,11 @@ +# $Id: Makefile.third_party_static_install.msvcproj 196847 2010-07-09 13:40:18Z gouriano $ + +MSVC_PROJ = third_party_static_install + +APP_DEP = + +DLL_DEP = + +VCPROJ = $(msvc_prj)\static\third_party_static_install.vcproj +VCXPROJ = $(msvc_prj)\static\third_party_static_install.vcxproj + diff --git a/c++/src/misc/third_party_static/Makefile.third_party_static_install.msvcproj.msvc b/c++/src/misc/third_party_static/Makefile.third_party_static_install.msvcproj.msvc new file mode 100644 index 00000000..5a457293 --- /dev/null +++ b/c++/src/misc/third_party_static/Makefile.third_party_static_install.msvcproj.msvc @@ -0,0 +1,4 @@ +# $Id: Makefile.third_party_static_install.msvcproj.msvc 107885 2007-07-30 15:34:21Z kazimird $ + +[Common] +ProjectGUID = {9E4B5381-9B6C-4867-BF8A-F1AAA1FD580E} \ No newline at end of file diff --git a/c++/src/objects/Makefile.in b/c++/src/objects/Makefile.in index 78a9c4d0..128cbc03 100644 --- a/c++/src/objects/Makefile.in +++ b/c++/src/objects/Makefile.in @@ -1,4 +1,4 @@ -# $Id: Makefile.in 437784 2014-06-10 14:26:24Z fongah2 $ +# $Id: Makefile.in 497130 2016-04-04 18:01:02Z foleyjp $ # Meta-makefile("objects" project) ################################# @@ -11,7 +11,7 @@ SUB_PROJ = general biblio medline pub seqcode seq seqset submit \ pcsubstance pcassay gbseq insdseq tinyseq biotree entrezgene \ omssa remap seqtest taxon1 taxon3 gbproj trackmgr valerr valid \ access docsum featdef genomecoll homologene mim objprt \ - variation macro genesbyloc coords + variation macro genesbyloc coords varrep REQUIRES = objects diff --git a/c++/src/objects/biblio/Auth_list.cpp b/c++/src/objects/biblio/Auth_list.cpp index aead49d1..9dd9fa37 100644 --- a/c++/src/objects/biblio/Auth_list.cpp +++ b/c++/src/objects/biblio/Auth_list.cpp @@ -1,4 +1,4 @@ -/* $Id: Auth_list.cpp 452468 2014-11-20 13:44:46Z bollin $ +/* $Id: Auth_list.cpp 498903 2016-04-20 15:50:10Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -223,7 +223,7 @@ void CAuth_list::ConvertMlToStandard(void) if (!NStr::IsBlank(*it)) { CRef new_auth(new CAuthor()); vector tokens; - NStr::Tokenize(*it, " ", tokens); + NStr::Split(*it, " ", tokens, NStr::fSplit_NoMergeDelims); string suffix = ""; string init = s_GetInitials(tokens); if (NStr::IsBlank(init) && tokens.size() > 1) { @@ -239,7 +239,7 @@ void CAuth_list::ConvertMlToStandard(void) if (!NStr::IsBlank(init)) { new_auth->SetName().SetName().SetFirst(init.substr(0, 1)); vector letters; - NStr::Tokenize(init, "", letters); + NStr::Split(init, "", letters, NStr::fSplit_NoMergeDelims); string initials = NStr::Join(letters, "."); new_auth->SetName().SetName().SetInitials(initials); } diff --git a/c++/src/objects/biblio/Cit_gen.cpp b/c++/src/objects/biblio/Cit_gen.cpp index 92352e83..7279509d 100644 --- a/c++/src/objects/biblio/Cit_gen.cpp +++ b/c++/src/objects/biblio/Cit_gen.cpp @@ -1,4 +1,4 @@ -/* $Id: Cit_gen.cpp 272691 2011-04-10 03:51:54Z ucko $ +/* $Id: Cit_gen.cpp 498027 2016-04-12 18:56:44Z grichenk $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -61,7 +61,7 @@ bool CCit_gen::GetLabelV1(string* label, TLabelFlags flags) const *label += "[" + NStr::IntToString(GetSerial_number()) + "]"; } if (IsSetMuid()) { - *label += "NLM" + NStr::IntToString(GetMuid()); + *label += "NLM" + NStr::NumericToString(GetMuid()); } string date; diff --git a/c++/src/objects/biblio/biblio.def b/c++/src/objects/biblio/biblio.def index 411bd027..1d647232 100644 --- a/c++/src/objects/biblio/biblio.def +++ b/c++/src/objects/biblio/biblio.def @@ -3,3 +3,16 @@ _export = NCBI_BIBLIO_EXPORT [Auth-list] names._delay = 1 + +[PubMedId] +_type = ncbi::TEntrezId + +[MedlineUID] +_type = ncbi::TEntrezId + +[PmcID] +_type = ncbi::TEntrezId + +[Cit-gen] +muid._type = ncbi::TEntrezId +muid._storage_type = ncbi::TIntId diff --git a/c++/src/objects/biotree/DistanceMatrix.cpp b/c++/src/objects/biotree/DistanceMatrix.cpp index 604674fe..7c83ac12 100644 --- a/c++/src/objects/biotree/DistanceMatrix.cpp +++ b/c++/src/objects/biotree/DistanceMatrix.cpp @@ -1,4 +1,4 @@ -/* $Id: DistanceMatrix.cpp 103491 2007-05-04 17:18:18Z kazimird $ +/* $Id: DistanceMatrix.cpp 498903 2016-04-20 15:50:10Z ivanov $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -159,7 +159,7 @@ void CDistanceMatrix::Read(istream &istr, EFormat format) { line = line.substr(10); } list fields; - NStr::Split(line, " \t\n\r", fields); + NStr::Split(line, " \t\n\r", fields, NStr::fSplit_Tokenize); ITERATE (list, field, fields) { line_values.push_back(NStr::StringToDouble(*field)); } diff --git a/c++/src/objects/blast/doc/blast.htm b/c++/src/objects/blast/doc/blast.htm index 06e87c9c..58f1b598 100644 --- a/c++/src/objects/blast/doc/blast.htm +++ b/c++/src/objects/blast/doc/blast.htm @@ -17,7 +17,7 @@ Center for Biotechnology Information provides free BLAST services to the public using this interface (over HTTP) and others. NCBI's BLAST source code is in the public domain, so other organizations may choose to run their own BLAST servers.

The functionality provided by this interface is similar to that provided by -the URL API. +the URL API. Either interface will work for many applications, but application programmers may find this interface to be more convenient.

For more information on using NCBI's public BLAST servers using this @@ -493,31 +493,31 @@ from each other, by spaces. Default values are shown in parentheses.

References

C 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