diff --git a/CHANGES.md b/CHANGES.md index e30b7837..9f02e9e3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,36 @@ # NCBI External Developer Release: +## SRA Toolkit 2.8.2 +**March 6, 2017** + + **blast**: Updated blast library to be able to process runs having empty rows + **blast, build**: removed library dependencies that were preventing users from launching these tools + **blast, sra-tools**: Prepared completely static build of blast tools for windows with HTTPS support + **build**: **bam-load**: changed memcpy to memmove when regions overlap - seems to corrupt data on centos7 + **build**: Added ability to specify ncbi-vdb/configure --with-magic-prefix. Look for libraries in (lib lib64) when running "configure --with-...-prefix" + **build**: configure detects location of ngs libraries + **build**: configure was fixed to skip options unrecognized by gcc 4.4.7 + **build**: created sra-toolkit Debian package + **build**: fixed a bug in 'configure' when in could not find source files in repository saved with non-standard name + **build, ncbi-vdb, sra-tools**: installation will back up old configuration files if they differ from the ones being installed + **cg-load**: added loading of CG File format v2.4 + **kns**: SRA tools respect standard set of environment variables for proxy specification + **kns**: updated mbedtls library to version 2.4.1 + **ncbi-vdb, ngs, ngs-tools, sra-tools**: eliminated memcpy from sources due to potential for overlap + **ngs, sra-search**: now supports search on reference + **ngs-tools**: updated the NCBI download page to incorporate ngs versions into 3rd party package names + **prefetch**: Fixed error message "path excessive while opening directory" when prefetch is trying to get vdbcache + **prefetch**: Fixed regression in prefetch-2.8.1 when downloading dbGaP files via HTTP + **prefetch**: Fixed regression in prefetch-2.8.1 when downloading vdbcache files from dbGaP via HTTP + **sam-dump**: consistency of sam-dump in fastq-mod improved + **sam-dump**: consistency of sam-dump in fastq-mode improved + **sra-stat**: sra-stat does XML-escaping when printing spot-groups + **test-sra**: extended test-sra to debug user problems with https connections to NCBI + **test-sra**: test-sra print amount of available disk space in user repositories + **vdb-config**: vdb-config correctly works when there is non-canonical path in configuration + + ## SRA Toolkit 2.8.1-2 **January 19, 2017** diff --git a/build/Makefile.env b/build/Makefile.env index 46cc5f53..9b5f2064 100644 --- a/build/Makefile.env +++ b/build/Makefile.env @@ -200,7 +200,7 @@ endif .PHONY: stdclean removelinks makedirs vers-includes rebuild-dirlinks .PHONY: stdjclean makejdirs -# configuration targets +# configuration targets out: @ echo $(OUTDIR) > $(TOP)/build/OUTDIR.$(BUILD_OS) @ $(MAKE) TOP=$(TOP) -f $(TOP)/build/Makefile.env rebuild-dirlinks @@ -362,11 +362,11 @@ LDFLAGS = $(DBG) $(PROF) $(CARCH) $(MIN_DEPLOY_OS_OPT) $(LDPATHS) #------------------------------------------------------------------------------- # runtests -# +# # MallocScribble=1 is for catching allocation problems on Mac # ifeq ($(RUNTESTS_OVERRIDE),) -runtests: std $(TEST_TOOLS) +runtests: all $(TEST_TOOLS) @ export VDB_CONFIG=$(VDB_CONFIG);export LD_LIBRARY_PATH=$(LIBDIR):$$LD_LIBRARY_PATH;export MallocScribble=1;\ for i in $(TEST_TOOLS);\ do\ @@ -380,11 +380,11 @@ endif #------------------------------------------------------------------------------- # slowtests -# +# # $(SLOWTESTSDATADIR) should be used to create temporary test files SLOWTESTSDATADIR ?= /panfs/pan1.be-md.ncbi.nlm.nih.gov/sra-test/slowtests/$(shell whoami) -slowtests: std $(SLOW_TEST_TOOLS) +slowtests: all $(SLOW_TEST_TOOLS) @ export LD_LIBRARY_PATH=$(LIBDIR):$$LD_LIBRARY_PATH;\ for i in $(SLOW_TEST_TOOLS);\ do\ diff --git a/test/Makefile b/test/Makefile index 9f6464b2..ae67bbea 100644 --- a/test/Makefile +++ b/test/Makefile @@ -35,6 +35,7 @@ include $(TOP)/build/Makefile.config # default # SUBDIRS = \ + vdb-config \ fastq-loader \ vcf-loader \ kget \ diff --git a/test/vdb-config/Makefile b/test/vdb-config/Makefile new file mode 100644 index 00000000..7813982a --- /dev/null +++ b/test/vdb-config/Makefile @@ -0,0 +1,35 @@ +# =========================================================================== +# +# 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. +# +# =========================================================================== + +default: runtests + +TOP ?= $(abspath ../..) +include $(TOP)/build/Makefile.env # BINDIR + +runtests: test-vdb-config + +test-vdb-config: + @ printf "Testing exit code vdb-config of vdb-config... " + @ PATH=$(BINDIR):$(PATH) ; ./test-vdb-config.pl + @ echo OK diff --git a/test/vdb-config/test-vdb-config.pl b/test/vdb-config/test-vdb-config.pl new file mode 100755 index 00000000..542a5b02 --- /dev/null +++ b/test/vdb-config/test-vdb-config.pl @@ -0,0 +1,12 @@ +#!/usr/bin/perl -w + +use strict; + +use File::Temp "tempdir"; + +my $tmp = tempdir ( "phgvXXXX", CLEANUP => 1 ); +$ENV{VDB_CONFIG}=$tmp; +$ENV{NCBI_SETTINGS}="$tmp/u.mkfg"; + +`vdb-config -s foo=bar`; +die "vdb-config exited with " . ( $? >> 8 ) if ( $? ); diff --git a/test/vdb-dump/Makefile b/test/vdb-dump/Makefile index 5449f2c5..9bcca8b5 100644 --- a/test/vdb-dump/Makefile +++ b/test/vdb-dump/Makefile @@ -53,6 +53,14 @@ $(ALL_TOOLS): makedirs .PHONY: all std $(ALL_TOOLS) #------------------------------------------------------------------------------- +# all +# +$(TARGDIR)/all: \ + $(addprefix $(BINDIR)/,$(ALL_TOOLS)) + +.PHONY: $(TARGDIR)/all + +#------------------------------------------------------------------------------- # std # $(TARGDIR)/std: \ diff --git a/tools/bam-loader/loader-imp.c b/tools/bam-loader/loader-imp.c index f81ea7ce..dc5cdba1 100644 --- a/tools/bam-loader/loader-imp.c +++ b/tools/bam-loader/loader-imp.c @@ -1548,6 +1548,7 @@ static rc_t ProcessBAM(char const bamFile[], context_t *ctx, VDatabase *db, KDataBuffer fragBuf; KDataBuffer cigBuf; rc_t rc; + const BAMRefSeq *refSeq = NULL; int32_t lastRefSeqId = -1; bool wasRenamed = false; size_t rsize; @@ -1650,7 +1651,6 @@ static rc_t ProcessBAM(char const bamFile[], context_t *ctx, VDatabase *db, uint16_t flags; int64_t rpos=0; char *seqDNA; - const BAMRefSeq *refSeq; ctx_value_t *value; bool wasInserted; int32_t refSeqId=-1; diff --git a/tools/sra-dump/fastq.c b/tools/sra-dump/fastq.c index 868443f9..0ee34956 100644 --- a/tools/sra-dump/fastq.c +++ b/tools/sra-dump/fastq.c @@ -3694,7 +3694,7 @@ rc_t SRADumper_Init( SRADumperFmt* fmt ) /* DO NOT ADD IN THE MIDDLE ORDER IS IMPORTANT IN USAGE FUNCTION ABOVE!!! */ {NULL, "split-spot", NULL, {"Split spots into individual reads", NULL}}, /* H_splip_sot = 0 */ - {"W", "clip", NULL, {"Clip adapter sequences", NULL}}, /* H_clip = 1 */ + {"W", "clip", NULL, {"Remove adapter sequences from reads", NULL}}, /* H_clip = 1 */ {"M", "minReadLen", "len", {"Filter by sequence length >= ", NULL}}, /* H_minReadLen = 2 */ {"E", "qual-filter", NULL, {"Filter used in early 1000 Genomes data:", /* H_qual_filter = 3 */ diff --git a/tools/util/test-sra.c b/tools/util/test-sra.c index c61ea626..09f2bd57 100644 --- a/tools/util/test-sra.c +++ b/tools/util/test-sra.c @@ -3438,11 +3438,11 @@ static rc_t MainFreeSpace ( const Main * self, const KDirectory * dir ) { if ( self -> xml ) OUTMSG ( ( - " \n", + " \n", free_bytes_available, total_number_of_bytes ) ); else OUTMSG ( ( - " Space free=\"%d\" total=\"%d\" units=\"KBytes\"\n", + " Space free=\"%lu\" total=\"%lu\" units=\"KBytes\"\n", free_bytes_available, total_number_of_bytes ) ); return rc; diff --git a/tools/vdb-config/interactive.cpp b/tools/vdb-config/interactive.cpp index 66af49f4..6bb0903e 100644 --- a/tools/vdb-config/interactive.cpp +++ b/tools/vdb-config/interactive.cpp @@ -883,7 +883,7 @@ bool vdbconf_controller::on_set_location_error( Dlg &dlg, ESetRootState s ) case eSetRootState_NewDirNotEmpty : vdbconf_msg( dlg, r, "the given location is not empty" ); break; case eSetRootState_NewNotDir : vdbconf_msg( dlg, r, "new location is not a directory" ); break; case eSetRootState_Error : vdbconf_msg( dlg, r, "error changing location" ); break; - default : vdbconf_msg( dlg, r, "unknow enum" ); break; + default : vdbconf_msg( dlg, r, "unknown enum" ); break; } return result; } diff --git a/tools/vdb-config/sra-config/images/aws_icon.png b/tools/vdb-config/sra-config/images/aws_icon.png new file mode 100644 index 00000000..46417fb2 Binary files /dev/null and b/tools/vdb-config/sra-config/images/aws_icon.png differ diff --git a/tools/vdb-config/sra-config/images/general_icon.png b/tools/vdb-config/sra-config/images/general_icon.png new file mode 100644 index 00000000..ebc0dbc3 Binary files /dev/null and b/tools/vdb-config/sra-config/images/general_icon.png differ diff --git a/tools/vdb-config/sra-config/images/images.ncbi.png b/tools/vdb-config/sra-config/images/images.ncbi.png new file mode 100644 index 00000000..a40a148f Binary files /dev/null and b/tools/vdb-config/sra-config/images/images.ncbi.png differ diff --git a/tools/vdb-config/sra-config/images/network_icon.png b/tools/vdb-config/sra-config/images/network_icon.png new file mode 100644 index 00000000..49ea5b4b Binary files /dev/null and b/tools/vdb-config/sra-config/images/network_icon.png differ diff --git a/tools/vdb-config/sra-config/images/troubleshooting.png b/tools/vdb-config/sra-config/images/troubleshooting.png new file mode 100644 index 00000000..96162131 Binary files /dev/null and b/tools/vdb-config/sra-config/images/troubleshooting.png differ diff --git a/tools/vdb-config/sra-config/main.cpp b/tools/vdb-config/sra-config/main.cpp new file mode 100644 index 00000000..894c97d7 --- /dev/null +++ b/tools/vdb-config/sra-config/main.cpp @@ -0,0 +1,64 @@ +/*=========================================================================== +* +* 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. +* +* =========================================================================== +* +*/ + +#include "sraconfig.h" + +#include "../configure.h" +#include "../interactive.h" +#include "../vdb-config-model.hpp" + +#include + +#include +#include +#include +#include + +#include + +static QApplication * app; +extern "C" +{ + rc_t run_interactive ( vdbconf_model &m ) + { + const QRect avail_geometry = QApplication :: desktop () -> availableGeometry ( QPoint ( 0, 0 ) ); + SRAConfig config_window ( m, avail_geometry ); + config_window . show (); + int status = app -> exec (); + if ( status != 0 ) + exit ( status ); + return 0; + } + } + +int main(int argc, char *argv[]) +{ + QApplication a ( argc, argv ); + app = & a; + + rc_t rc = configure ( eCfgModeVisual ); + return ( rc == 0 ) ? 0 : 3; +} diff --git a/tools/vdb-config/sra-config/resources.qrc b/tools/vdb-config/sra-config/resources.qrc new file mode 100644 index 00000000..a29f46d3 --- /dev/null +++ b/tools/vdb-config/sra-config/resources.qrc @@ -0,0 +1,9 @@ + + + images/general_icon.png + images/aws_icon.png + images/images.ncbi.png + images/network_icon.png + images/troubleshooting.png + + diff --git a/tools/vdb-config/sra-config/sra-config.pro b/tools/vdb-config/sra-config/sra-config.pro new file mode 100644 index 00000000..220c82f3 --- /dev/null +++ b/tools/vdb-config/sra-config/sra-config.pro @@ -0,0 +1,49 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2017-03-22T11:17:53 +# +#------------------------------------------------- + +QT += core gui + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = sra-config +TEMPLATE = app + +# The following define makes your compiler emit warnings if you use +# any feature of Qt which as been marked as deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if you use deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 +LIBS += -L/Users/rodarme1/ncbi-outdir/ncbi-vdb/mac/clang/x86_64/dbg/lib -lncbi-vdb + +INCLUDEPATH += ../../../../ncbi-vdb/interfaces \ + ../../../../ncbi-vdb/interfaces/os/mac \ + ../../../../ncbi-vdb/interfaces/os/unix \ + ../../../../ncbi-vdb/interfaces/cc/gcc \ + ../../../../ncbi-vdb/interfaces/cc/gcc/x86_64 + +SOURCES += main.cpp\ + sraconfig.cpp \ + ../configure.cpp \ + ../vdb-config-model.cpp \ + ../util.cpp \ + ../sra-tools-gui/libs/ktoolbaritem.cpp \ + srapreferences.cpp \ + sraconfigmodel.cpp + + +HEADERS += sraconfig.h \ + ../sra-tools-gui/interfaces/ktoolbaritem.h \ + srapreferences.h \ + sraconfigmodel.h + +RESOURCES += \ + resources.qrc + diff --git a/tools/vdb-config/sra-config/sra-config.pro.user b/tools/vdb-config/sra-config/sra-config.pro.user new file mode 100644 index 00000000..ee96d3fe --- /dev/null +++ b/tools/vdb-config/sra-config/sra-config.pro.user @@ -0,0 +1,339 @@ + + + + + + EnvironmentId + {8a39ecd7-5faa-47c8-8a45-2fb59818cecd} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + false + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + true + false + 1 + true + true + 1 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + + ProjectExplorer.Project.Target.0 + + Desktop Qt 5.8.0 clang 64bit + Desktop Qt 5.8.0 clang 64bit + qt.58.clang_64_kit + 0 + 0 + 0 + + /net/snowman/vol/export4/rodarme1/devel/sra-tools/tools/vdb-config/build-sra-config-Desktop_Qt_5_8_0_clang_64bit-Debug + + + true + qmake + + QtProjectManager.QMakeBuildStep + true + + false + false + false + + + true + Make + + Qt4ProjectManager.MakeStep + + -w + -r + + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + -w + -r + + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Debug + + Qt4ProjectManager.Qt4BuildConfiguration + 2 + true + + + /net/snowman/vol/export4/rodarme1/devel/sra-tools/tools/vdb-config/build-sra-config-Desktop_Qt_5_8_0_clang_64bit-Release + + + true + qmake + + QtProjectManager.QMakeBuildStep + false + + false + false + false + + + true + Make + + Qt4ProjectManager.MakeStep + + -w + -r + + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + -w + -r + + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release + + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + + /net/snowman/vol/export4/rodarme1/devel/sra-tools/tools/vdb-config/build-sra-config-Desktop_Qt_5_8_0_clang_64bit-Profile + + + true + qmake + + QtProjectManager.QMakeBuildStep + true + + false + true + false + + + true + Make + + Qt4ProjectManager.MakeStep + + -w + -r + + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + -w + -r + + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Profile + + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + 3 + + + 0 + Deploy + + ProjectExplorer.BuildSteps.Deploy + + 1 + Deploy locally + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + false + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + 1 + + VDB_CONFIG=/net/traces01.be-md.ncbi.nlm.nih.gov/trace_software/vdb/config:/net/traces01.be-md.ncbi.nlm.nih.gov/trace_software/vdb/mac/config + + sra-config + + Qt4ProjectManager.Qt4RunConfiguration:/net/snowman/vol/export4/rodarme1/devel/sra-tools/tools/vdb-config/sra-config/sra-config.pro + true + + sra-config.pro + false + false + + /net/snowman/vol/export4/rodarme1/devel/sra-tools/tools/vdb-config/build-sra-config-Desktop_Qt_5_8_0_clang_64bit-Debug/sra-config.app/Contents/MacOS + 3768 + false + true + false + false + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 18 + + + Version + 18 + + diff --git a/tools/vdb-config/sra-config/sraconfig.cpp b/tools/vdb-config/sra-config/sraconfig.cpp new file mode 100644 index 00000000..9ab8f4ae --- /dev/null +++ b/tools/vdb-config/sra-config/sraconfig.cpp @@ -0,0 +1,1021 @@ +/*=========================================================================== +* +* 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. +* +* =========================================================================== +* +*/ + +#include "sraconfig.h" +#include "sraconfigmodel.h" +#include "../sra-tools-gui/interfaces/ktoolbaritem.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +const QString rsrc_path = ":/images"; + +struct WorkspaceItem +{ + WorkspaceItem ( QString name, QString path, uint32_t id ) + : name_label ( new QLabel ( name ) ) + , path_label ( new QLabel ( path ) ) + , edit_button ( new QPushButton ( "Edit" ) ) + , ngc_id ( id ) + { + name_label -> setFixedWidth ( 150 ); + name_label -> setAlignment ( Qt::AlignRight ); + + path_label -> setFrameShape ( QFrame::Panel ); + path_label -> setFrameShadow ( QFrame::Sunken ); + + edit_button -> setFixedSize ( 30, 20 ); + } + + WorkspaceItem () + : name_label ( nullptr ) + , path_label ( nullptr ) + , edit_button ( nullptr ) + , ngc_id ( -1 ) + {} + + QLabel *name_label; + QLabel *path_label; + QPushButton *edit_button; + + int ngc_id; +}; + + +/* static functions */ +static +bool location_error ( RootState state, QWidget *w ) +{ + QString msg; + + switch ( state ) + { + case RootState_NotChanged : return true; + case RootState_NotUnique : msg = QString ( "location not unique, select a different one" ); break; + case RootState_MkdirFail : msg = QString ( "could not created directory, maybe permisson problem" ); break; + case RootState_NewPathEmpty : msg = QString ( "you gave me an empty path" ); break; + case RootState_NewDirNotEmpty : msg = QString ( "the given location is not empty" ); break; + case RootState_NewNotDir : msg = QString ( "new location is not a directory" ); break; + case RootState_Error : msg = QString ( "error changing location" ); break; + default : msg = QString ( "unknown enum" ); break; + } + + QMessageBox::critical ( w + , "Error" + , msg + , QMessageBox::Ok ); + return false; +} + +static +std :: string public_location_start_dir ( SRAConfigModel *model ) +{ + std :: string s = model -> get_public_path (); + + if ( ! model -> path_exists ( s ) ) + s = model -> get_user_default_path (); + + if ( ! model -> path_exists ( s ) ) + s = model -> get_home_path () + "/ncbi"; + + if ( ! model -> path_exists ( s ) ) + s = model -> get_home_path (); + + if ( ! model -> path_exists ( s ) ) + s = model -> get_current_path (); + + return s; +} + +static +bool select_public_location ( SRAConfigModel *model, QWidget *w ) +{ + std ::string path = public_location_start_dir ( model ) . c_str (); + + if ( model -> path_exists ( path ) ) + { + QString p = QFileDialog :: getOpenFileName ( w + , "Import Workspace" + , path . c_str () ); + path = p . toStdString (); + } + else + { + QString p = QInputDialog::getText ( w + , "" + , "Location of public cache" + , QLineEdit::Normal ); + path = p . toStdString (); + } + + if ( path . length () > 0 ) + { + QString p = path . c_str (); + QMessageBox::StandardButton reply; + reply = QMessageBox::question ( w + , "" + , "Change the location to '" + p + "'?" + , QMessageBox::Yes | QMessageBox::No ); + if ( reply == QMessageBox::Yes ) + { + bool flush_old = false; + bool reuse_new = false; + + RootState state = model -> set_public_path ( path, flush_old, reuse_new ); + + switch ( state ) + { + case RootState_OK: + return true; + case RootState_OldNotEmpty: + { + QMessageBox::StandardButton reply; + reply = QMessageBox::question ( w + , "Directory not empty" + , "Previous location is not empty, flush it?" + , QMessageBox::Yes | QMessageBox::No ); + if ( reply == QMessageBox::Yes ) + { + flush_old = true; + state = model -> set_public_path ( path, flush_old, reuse_new ); + if ( state == RootState_OK ) + return true; + else + return location_error ( state, w ); + } + } + default: + return location_error ( state, w ); + } + } + } + + return false; +} + +static +std :: string protected_location_start_dir ( SRAConfigModel *model, uint32_t id ) +{ + std :: string s = model -> get_workspace_path ( id ); + + if ( ! model -> path_exists ( s ) ) + s = model -> get_user_default_path (); + + if ( ! model -> path_exists ( s ) ) + s = model -> get_home_path () + "/ncbi"; + + if ( ! model -> path_exists ( s ) ) + s = model -> get_home_path (); + + if ( ! model -> path_exists ( s ) ) + s = model -> get_current_path (); + + return s; +} + +static +bool select_protected_location ( SRAConfigModel *model, int id, QWidget *w ) +{ + std :: string path = protected_location_start_dir ( model, id ); + qDebug () << "Protect location path: " << QString ( path . c_str () ) << " [" << id << "]"; + + if ( model -> path_exists ( path ) ) + { + QString p = QFileDialog :: getOpenFileName ( w + , "Import Workspace" + , path . c_str () ); + path = p . toStdString (); + } + else + { + QString p = QInputDialog::getText ( w + , "" + , "Location of dbGaP project" + , QLineEdit::Normal ); + path = p . toStdString (); + } + + if ( path . length () > 0 ) + { + QString repo_name = model -> get_workspace_name ( id ) . c_str (); + QMessageBox::StandardButton reply; + reply = QMessageBox::question ( w + , "" + , "Change the location of '" + repo_name + "' to '" + QString ( path . c_str () ) + "'?" + , QMessageBox::Yes | QMessageBox::No ); + if ( reply == QMessageBox::Yes ) + { + bool flush_old = false; + bool reuse_new = false; + + RootState state = model -> set_workspace_path ( path, id, flush_old, reuse_new ); + + switch ( state ) + { + case RootState_OK: + return true; + case RootState_OldNotEmpty: + { + QMessageBox::StandardButton reply; + reply = QMessageBox::question ( w + , "Directory not empty" + , "Previous location is not empty, flush it?" + , QMessageBox::Yes | QMessageBox::No ); + if ( reply == QMessageBox::Yes ) + { + flush_old = true; + state = model -> set_workspace_path ( path, id, flush_old, reuse_new ); + if ( state == RootState_OK ) + return true; + else + return location_error ( state, w ); + } + } + default: + return location_error ( state, w ); + } + } + } + + return false; +} + +static +bool make_ngc_obj ( const KNgcObj ** ngc, std::string &path ) +{ + KDirectory * dir; + rc_t rc = KDirectoryNativeDir( &dir ); + if ( rc == 0 ) + { + const KFile * src; + rc = KDirectoryOpenFileRead ( dir, &src, "%s", path.c_str() ); + if ( rc == 0 ) + { + rc = KNgcObjMakeFromFile ( ngc, src ); + KFileRelease( src ); + } + KDirectoryRelease( dir ); + } + + return ( rc == 0 ); +} + +static +bool prepare_ngc ( SRAConfigModel *model, const KNgcObj *ngc, QString *loc, QWidget *w ) +{ + std :: string base_path = model -> get_user_default_path (); + std :: string path = model -> get_ngc_root ( base_path, ngc ); + + RootState state = model -> configure_workspace ( path ); + + switch ( state ) + { + case RootState_OK: + { + *loc = path . c_str (); + return true; + } + case RootState_OldNotEmpty: + { + QMessageBox::StandardButton reply; + reply = QMessageBox::question ( w + , "Directory not empty" + , "Workspace location is not empty. Use it anyway?" + , QMessageBox::Yes | QMessageBox::No ); + if ( reply == QMessageBox::Yes ) + { + state = model -> configure_workspace ( path, true ); + if ( state == RootState_OK ) + { + *loc = path . c_str (); + return true; + } + else + return location_error ( state, w ); + } + } + default: + return location_error ( state, w ); + } + + return false; +} + +static +bool import_ngc ( SRAConfigModel *model, std :: string file, uint32_t &ngc_id, QWidget *w ) +{ + const KNgcObj *ngc; + if ( ! make_ngc_obj ( &ngc, file ) ) + { + QMessageBox::information ( w + , "Import Error" + , "Unable to import NGC file" ); + } + else + { + QString path; + if ( ! prepare_ngc ( model, ngc, &path, w ) ) + qDebug () << "failed to prepare ngc object"; + else + { + qDebug () << "prepared ngc object"; + + uint32_t result_flags = 0; + + if ( model -> import_ngc ( path . toStdString (), ngc, INP_CREATE_REPOSITORY, &result_flags ) ) + { + /* we have it imported or it exists and no changes made */ + bool modified = false; + if ( result_flags & INP_CREATE_REPOSITORY ) + { + /* success is the most common outcome, the repository was created */ + QMessageBox::information ( w + , "Import Successful" + , "project successfully imported" ); + + modified = true; + } + else + { + /* repository did exist and is completely identical to the given ngc-obj */ + QMessageBox::information ( w + , "" + , "this project exists already, no changes made" ); + + modified = false; + } + + if ( model -> get_ngc_obj_id ( ngc, &ngc_id ) ) + { + qDebug () << "NGC ID: " << ngc_id; + + QMessageBox::StandardButton reply; + reply = QMessageBox::question ( w + , "" + , "Do you want to change the location?" + , QMessageBox::Yes | QMessageBox::No ); + if ( reply == QMessageBox::Yes ) + { + modified |= select_protected_location ( model, ngc_id, w ); + } + } + else + { + QMessageBox::information ( w + , "" + , "Cannot find the imported Workspace" ); + } + + if ( modified ) + { + model -> commit (); // TBD - on import of NGC files, do we automaically commit, or allow for revert and require apply button? + model -> create_directory ( ngc ); + return true; + } + } + else if ( result_flags == 0 ) + { + QMessageBox::critical ( w + , "Error" + , "Internal Error: Failed to impport the ngc-object" + , QMessageBox::Ok ); + } + else + { + QMessageBox::information ( w, "", "the repository does already exist!" ); + + if ( result_flags & INP_UPDATE_ENC_KEY ) + { + QMessageBox::StandardButton reply; + reply = QMessageBox::question ( w + , "" + , "Encryption key would change, continue?" + , QMessageBox::Yes | QMessageBox::No ); + if ( reply == QMessageBox::Yes && ( result_flags & INP_UPDATE_DNLD_TICKET ) ) + { + QMessageBox::StandardButton reply; + reply = QMessageBox::question ( w + , "" + , "Download ticket would change, continue?" + , QMessageBox::Yes | QMessageBox::No ); + if ( reply == QMessageBox::Yes && ( result_flags & INP_UPDATE_DESC ) ) + { + QMessageBox::StandardButton reply; + reply = QMessageBox::question ( w + , "" + , "Description would change, continue?" + , QMessageBox::Yes | QMessageBox::No ); + if ( reply == QMessageBox::Yes ) + { + uint32_t result_flags2 = 0; + if ( model -> import_ngc ( path . toStdString () , ngc, result_flags, &result_flags2 ) ) + { + QMessageBox::StandardButton reply; + reply = QMessageBox::question ( w + , "" + , "Project successfully updated!\nDo you want to change the location? " + , QMessageBox::Yes | QMessageBox::No ); + + if ( reply == QMessageBox::Yes ) + { + /* we have to find out the id of the imported/existing repository */ + if ( model -> get_ngc_obj_id ( ngc, &ngc_id ) ) + { + qDebug () << "NGC ID: " << ngc_id; + select_protected_location ( model, ngc_id, w ); + } + else + QMessageBox::information ( w, "", "the repository does already exist!" ); + } + + model -> commit (); + + return true; + } + else + { + QMessageBox::critical ( w + , "Error" + , "Internal Error: Failed to impport the ngc-object" + , QMessageBox::Ok ); + } + } + else + QMessageBox::information ( w, "", "The import was canceled" ); + } + } + } + } + } + + KNgcObjRelease ( ngc ); + } + + return false; +} + + + +/* Class methods */ + +SRAConfig :: SRAConfig ( vdbconf_model &config_model, const QRect &avail_geometry, QWidget *parent ) + : QMainWindow ( parent ) + , model ( new SRAConfigModel ( config_model ) ) + , screen_geometry ( avail_geometry ) + , main_layout ( new QVBoxLayout () ) +{ + + setWindowTitle ( "SRA Configuration Tool" ); + setup_menubar (); + //setup_toolbar (); + + main_layout -> setSpacing ( 20 ); + main_layout -> setAlignment ( Qt::AlignTop ); + main_layout -> addSpacing ( 10 ); + main_layout -> addWidget ( setup_option_group () ); + main_layout -> addWidget ( setup_workspace_group () ); + main_layout -> addLayout ( setup_button_layout () ); + + populate (); + + connect ( this, SIGNAL ( dirty_config () ), this, SLOT ( modified_config () ) ); + + QWidget *main_widget = new QWidget (); + main_widget -> setLayout ( main_layout ); + + setCentralWidget ( main_widget ); + + resize ( ( screen_geometry . width () ) / 3, this -> height () ); + + move ( ( screen_geometry . width () - this -> width () ) / 2, + ( screen_geometry . height () - this -> height () ) / 2 ); +} + +SRAConfig :: ~SRAConfig () +{ + +} + +void SRAConfig :: setup_menubar () +{ + QMenu *file = menuBar () -> addMenu ( tr ( "&File" ) ); + + apply_action = file -> addAction ( tr ( "&Apply" ), this, SLOT ( commit_config () ) ); + apply_action -> setDisabled ( true ); + + file -> addSeparator (); + file -> addAction ( tr ( "&Import" ), this, SLOT ( import_workspace () ) ); + + QMenu *edit = menuBar () -> addMenu ( tr ( "\u200CEdit" ) ); // \u200C was added because OSX auto-adds some unwanted menu items + + discard_action = edit -> addAction ( tr ( "&Discard Changes" ), this, SLOT ( reload_config () ) ); + discard_action -> setDisabled ( true ); + + edit -> addSeparator (); + edit -> addAction ( tr ( "&Advanced" ), this, SLOT ( advanced_settings () ) ); + edit -> addSeparator (); + edit -> addAction ( tr ( "&Soft Factory Reset" ), this, SLOT ( default_config () ) ); +} + +void SRAConfig :: setup_toolbar () +{ +#ifdef Q_OS_OSX + setUnifiedTitleAndToolBarOnMac ( true ); +#endif + + QToolBar *bar = new QToolBar ( this ); + + KToolbarItem *item = new KToolbarItem ( "General", rsrc_path + "/general_icon" ); + bar -> addWidget ( item ); + + item = new KToolbarItem ( "AWS", rsrc_path + "/aws_icon" ); + bar -> addWidget ( item ); + + item = new KToolbarItem ( "Network", rsrc_path + "/network_icon" ); + bar -> addWidget ( item ); + + item = new KToolbarItem ( "Diagnostics", rsrc_path + "/troubleshooting" ); + bar -> addWidget ( item ); + + addToolBar ( bar ); + +} + +void SRAConfig :: populate () +{ + remote_enabled_cb -> setChecked ( model -> remote_enabled () ); + + local_caching_cb -> setChecked ( model -> global_cache_enabled () ); + + if ( model -> site_workspace_exists () ) + site_cb -> setChecked ( model -> site_enabled () ); + else + site_cb -> setDisabled ( true ); + + proxy_cb -> setChecked ( model -> proxy_enabled () ); + proxy_label -> setText ( model -> get_proxy_path () . c_str () ); + + http_priority_cb -> setChecked ( model -> proxy_priority () ); +} + +QGroupBox * SRAConfig::setup_option_group () +{ + QGroupBox *group = new QGroupBox ( "Options" ); + group -> setFixedHeight ( 170 ); + + QGridLayout *layout = new QGridLayout (); + layout -> setAlignment ( Qt :: AlignTop ); + layout -> setSpacing ( 15 ); + + //1 + remote_enabled_cb = new QCheckBox ( "Enable Remote Access" ); + remote_enabled_cb -> setAutoExclusive ( false ); + layout -> addWidget ( remote_enabled_cb, 0, 0 ); + connect ( remote_enabled_cb, SIGNAL ( clicked ( bool ) ), this, SLOT ( toggle_remote_enabled ( bool ) ) ); + + //2 + local_caching_cb = new QCheckBox ( "Enable Local File Caching" ); + local_caching_cb -> setAutoExclusive ( false ); + layout -> addWidget ( local_caching_cb, 1, 0 ); + connect ( local_caching_cb, SIGNAL ( clicked ( bool ) ), this, SLOT ( toggle_local_caching ( bool ) ) ); + + //3 + site_cb = new QCheckBox ( "Use Site Installation" ); + site_cb -> setAutoExclusive ( false ); + layout -> addWidget ( site_cb, 2, 0 ); + connect ( site_cb, SIGNAL ( clicked ( bool ) ), this, SLOT ( toggle_use_site ( bool ) ) ); + + //4 + proxy_cb = new QCheckBox ( "Use Proxy" ); + proxy_cb -> setAutoExclusive ( false ); + layout -> addWidget ( proxy_cb, 3, 0 ); + connect ( proxy_cb, SIGNAL ( clicked ( bool ) ), this, SLOT ( toggle_use_proxy ( bool ) ) ); + + proxy_label = new QLabel (); + proxy_label -> setMargin ( 0 ); + proxy_label -> setFrameShape ( QFrame::Panel ); + proxy_label -> setFrameShadow ( QFrame::Sunken ); + proxy_label -> setFixedHeight ( 20 ); + layout -> addWidget ( proxy_label, 3, 1 ); + + QPushButton *edit = new QPushButton ( "Edit" ); + edit -> setFixedSize ( 30, 20 ); + layout -> addWidget ( edit, 3, 2 ); + connect ( edit, SIGNAL ( clicked () ), this, SLOT ( edit_proxy_path () ) ); + + //5 + http_priority_cb = new QCheckBox ( "Prioritize Environment Variable 'http-proxy'" ); + http_priority_cb -> setAutoExclusive ( false ); + layout -> addWidget ( http_priority_cb, 4, 0 ); + connect ( http_priority_cb, SIGNAL ( clicked ( bool ) ), this, SLOT ( toggle_prioritize_http ( bool ) ) ); + + group -> setLayout ( layout ); + + return group; +} + +void SRAConfig :: add_workspace (QString name, QString val, int ngc_id, bool insert ) +{ + QHBoxLayout *layout = new QHBoxLayout (); + + WorkspaceItem *ws = new WorkspaceItem ( name . append ( ':' ), val, ngc_id ); + + if ( ngc_id == -1 ) + { + public_workspace = ws; + connect ( ws -> edit_button, SIGNAL ( clicked () ), this, SLOT ( edit_public_path () ) ); + } + else + { + protected_workspaces . append ( ws ); + connect ( ws -> edit_button, SIGNAL ( clicked () ), this, SLOT ( edit_workspace_path () ) ); + } + + layout -> addWidget ( ws -> name_label ); + layout -> addWidget ( ws -> path_label ); + layout -> addWidget ( ws -> edit_button ); + + if ( insert ) + { + workspace_layout -> insertLayout ( workspace_layout -> count () - 1, layout ); + } + else + workspace_layout -> addLayout ( layout ); +} + + +void SRAConfig :: import_workspace () +{ + // open a file dialog to browse for the repository + std :: string path = model -> get_home_path (); + if ( ! model -> path_exists ( path ) ) + path = model -> get_current_path (); + + QString filter = tr ("NGS (*.ngc)" ); + QString file = QFileDialog :: getOpenFileName ( this + , "Import Workspace" + , path . c_str () + , tr ("NGC files (*.ngc)" ) ); + + if ( ! file . isEmpty () ) + { + std :: string s = file . toStdString (); + uint32_t ngc_id; + if ( import_ngc ( model, s, ngc_id, this ) ) + { + QString name = model -> get_workspace_name ( ngc_id ) . c_str (); + + name = QInputDialog::getText ( this + , tr ( "Name Workspace" ) + , tr ( "Choose a name for your workspace" ) + , QLineEdit::Normal + , name ); + + if ( name . isEmpty () ) + name = model -> get_workspace_name ( ngc_id ) . c_str (); + + add_workspace ( name, file, ngc_id, true ); + } + } +} + + +QGroupBox * SRAConfig :: setup_workspace_group () +{ + QGroupBox *group = new QGroupBox ( "Workspaces" ); + + workspace_layout = new QVBoxLayout (); + workspace_layout -> setAlignment ( Qt :: AlignTop ); + workspace_layout -> setSpacing ( 15 ); + + add_workspace ( "Public", model -> get_public_path () . c_str(), -1 ); + + int ws_count = model -> workspace_count (); + qDebug () << "Setup workspace group: repo-count: " << ws_count; + for ( int i = 0; i < ws_count; ++ i ) + { + std :: string name = model -> get_workspace_name ( i ); + add_workspace ( name . c_str () , + model -> get_workspace_path ( i ) . c_str (), + model -> get_workspace_id ( name ) ); + } + + //3 + QHBoxLayout *i_layout = new QHBoxLayout (); + + i_layout -> addSpacing ( 125 ); + + QPushButton *import = new QPushButton ( "+" ); + import -> setFixedSize ( 30, 25 ); + connect ( import, SIGNAL ( clicked () ), this, SLOT ( import_workspace () ) ); + i_layout -> addWidget ( import ); + + i_layout -> addSpacing ( 5 ); + + QLabel *label = new QLabel (); + label -> setFrameShape ( QFrame::Panel ); + label -> setFrameShadow ( QFrame::Sunken ); + + i_layout -> addWidget ( label ); + + workspace_layout -> addLayout ( i_layout ); + + group -> setLayout ( workspace_layout ); + + return group; +} + +QVBoxLayout * SRAConfig::setup_button_layout () +{ + QVBoxLayout *v_layout = new QVBoxLayout (); + + // 1 + QHBoxLayout *layout = new QHBoxLayout (); + layout -> setAlignment ( Qt::AlignTop | Qt::AlignRight ); + + QPushButton *advanced = new QPushButton ( "Advanced" ); + advanced -> setFixedWidth ( 150 ); + connect ( advanced, SIGNAL ( clicked () ), this, SLOT ( advanced_settings () ) ); + + layout -> addWidget ( advanced ); + v_layout -> addLayout ( layout ); + v_layout -> addStretch ( 1 ); + + // 2 + layout = new QHBoxLayout (); + layout -> setAlignment ( Qt::AlignBottom | Qt::AlignRight ); + layout -> setSpacing ( 5 ); + + apply_btn = new QPushButton ( "Apply" ); + apply_btn -> setDisabled ( true ); + connect ( apply_btn, SIGNAL ( clicked () ), this, SLOT ( commit_config () ) ); + + discard_btn = new QPushButton ( "Revert" ); + discard_btn -> setDisabled ( true ); + connect ( discard_btn, SIGNAL ( clicked () ), this, SLOT ( reload_config () ) ); + + layout -> addWidget ( discard_btn ); + layout -> addWidget ( apply_btn ); + + v_layout -> addLayout ( layout ); + + return v_layout; +} + +void SRAConfig :: closeEvent ( QCloseEvent *ev ) +{ + if ( model -> config_changed () ) + { + QMessageBox::StandardButton reply; + reply = QMessageBox::question ( this + , "" + , "Save changes? " + , QMessageBox::No | QMessageBox::Yes ); + + if ( reply == QMessageBox::Yes ) + commit_config (); + } + + ev -> accept (); +} + +void SRAConfig :: advanced_settings () +{ + adv_setting_window = new QFrame (); + adv_setting_window -> resize ( this -> width () * .7, this -> height () / 2 ); + adv_setting_window -> setWindowTitle ( "Advanced Settings" ); + + QVBoxLayout *v_layout = new QVBoxLayout (); + + // 1 + QHBoxLayout *layout = new QHBoxLayout (); + + QLabel *label = new QLabel ( "Default import path:" ); + label -> setFixedWidth ( 150 ); + label -> setAlignment ( Qt::AlignRight ); + layout -> addWidget ( label); + + import_path_label = new QLabel ( model -> get_user_default_path () . c_str () ); + import_path_label -> setFrameShape ( QFrame::Panel ); + import_path_label -> setFrameShadow ( QFrame::Sunken ); + layout -> addWidget ( import_path_label ); + + QPushButton *edit = new QPushButton ( "Edit" ); + connect ( edit, SIGNAL ( clicked () ), this, SLOT ( edit_import_path () ) ); + edit -> setFixedSize ( 30, 20 ); + layout -> addWidget ( edit ); + + v_layout -> addLayout ( layout ); + v_layout -> addStretch ( 1 ); + + // last + layout = new QHBoxLayout (); + layout -> setAlignment ( Qt::AlignBottom | Qt::AlignRight ); + + QPushButton *done = new QPushButton ( "Done" ); + connect ( done, SIGNAL ( clicked () ), adv_setting_window, SLOT ( close () ) ); + + layout -> addWidget ( done ); + v_layout -> addLayout ( layout ); + + adv_setting_window -> setLayout ( v_layout ); + + adv_setting_window -> show (); +} + +void SRAConfig :: commit_config () +{ + if ( ! model -> commit () ) + QMessageBox::information ( this, "", "Error saving changes" ); + + apply_btn -> setDisabled ( true ); + discard_btn -> setDisabled ( true ); +} + +void SRAConfig :: reload_config () +{ + model -> reload (); + populate (); + + if ( ! model -> config_changed () ) + { + apply_btn -> setDisabled ( true ); + apply_action -> setDisabled ( true ); + discard_btn -> setDisabled ( true ); + discard_action -> setDisabled ( true ); + } +} + +void SRAConfig :: modified_config () +{ + if ( model -> config_changed () ) // this wont trigger on workspace addition yet + { + apply_btn -> setDisabled ( false ); + apply_action -> setDisabled ( false ); + discard_btn -> setDisabled ( false ); + discard_action -> setDisabled ( false ); + } +} + +// TBD - still needs a menu item to be triggered. -- this is not a hard reset - it still keeps some user settings +void SRAConfig :: default_config () +{ + model -> set_remote_enabled ( true ); + model -> set_global_cache_enabled ( true ); + model -> set_site_enabled ( true ); + + populate (); + + emit dirty_config (); +} + +void SRAConfig :: toggle_remote_enabled ( bool toggled ) +{ + model -> set_remote_enabled ( toggled ); + emit dirty_config (); +} + +void SRAConfig :: toggle_local_caching ( bool toggled ) +{ + model -> set_global_cache_enabled ( toggled ); + emit dirty_config (); +} + +void SRAConfig :: toggle_use_site ( bool toggled ) +{ + model -> set_site_enabled ( toggled ); + emit dirty_config (); +} + +void SRAConfig :: toggle_use_proxy ( bool toggled ) +{ + model -> set_proxy_enabled ( toggled ); + emit dirty_config (); +} + +void SRAConfig :: toggle_prioritize_http ( bool toggled ) +{ + model -> set_proxy_priority ( toggled ); + emit dirty_config (); +} + +void SRAConfig :: edit_import_path () +{ + std :: string path = model -> get_user_default_path () . c_str (); + + if ( ! model -> path_exists ( path ) ) + path = model -> get_home_path (); + + if ( ! model -> path_exists ( path ) ) + path = model -> get_current_path (); + + QString e_path = QFileDialog :: getOpenFileName ( adv_setting_window + , "" + , path . c_str () ); + + + if ( e_path . isEmpty () ) + return; + + import_path_label -> setText ( e_path ); + model -> set_user_default_path ( e_path . toStdString () . c_str () ); + + emit dirty_config (); +} + +void SRAConfig :: edit_proxy_path () +{ + QString input = QInputDialog::getText ( this + , tr ( "Proxy Path" ) + , tr ( "Enter a proxy path" ) + , QLineEdit::Normal + , proxy_label -> text () ); + + if ( input . isEmpty () ) + return; + + proxy_label -> setText ( input ); + model -> set_proxy_path ( input . toStdString () ); + + emit dirty_config (); +} + +void SRAConfig :: edit_public_path () +{ + qDebug () << public_workspace -> ngc_id; + if ( select_public_location ( model, this ) ) + { + public_workspace -> path_label -> setText ( model -> get_public_path () . c_str () ); + + emit dirty_config (); + } +} + +void SRAConfig :: edit_workspace_path () +{ + foreach ( WorkspaceItem *item, protected_workspaces ) + { + if ( sender () == item -> edit_button ) + { + qDebug () << item -> ngc_id; + + if ( select_protected_location ( model, item -> ngc_id, this ) ) + { + QString path = model -> get_workspace_path ( item -> ngc_id ) . c_str (); + item -> path_label -> setText ( path ); + import_path_label -> setText ( path ); + + emit dirty_config (); + } + + return; + } + } +} + + diff --git a/tools/vdb-config/sra-config/sraconfig.h b/tools/vdb-config/sra-config/sraconfig.h new file mode 100644 index 00000000..326eb109 --- /dev/null +++ b/tools/vdb-config/sra-config/sraconfig.h @@ -0,0 +1,127 @@ +/*=========================================================================== +* +* 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. +* +* =========================================================================== +* +*/ + +#ifndef SRACONFIG_H +#define SRACONFIG_H + +#include + +QT_BEGIN_NAMESPACE +class QHBoxLayout; +class QVBoxLayout; +class QCheckBox; +class QFrame; +class QGroupBox; +class QLabel; +class QPushButton; +QT_END_NAMESPACE + +class SRAConfigModel; +class vdbconf_model; +struct KNgcObj; +struct WorkspaceItem; + +class SRAConfig : public QMainWindow +{ + Q_OBJECT + +public: + + SRAConfig ( vdbconf_model &config_model, const QRect &avail_geometry, QWidget *parent = 0 ); + ~SRAConfig (); + +signals: + + void dirty_config (); + +private slots: + + void advanced_settings (); + void commit_config (); + void reload_config (); + void default_config (); + void modified_config (); + + void import_workspace (); + + void edit_import_path (); + void edit_proxy_path (); + void edit_public_path (); + void edit_workspace_path (); + + void toggle_remote_enabled ( bool toggled ); + void toggle_local_caching ( bool toggled ); + void toggle_use_site ( bool toggled ); + void toggle_use_proxy ( bool toggled ); + void toggle_prioritize_http ( bool toggled ); + + + +private: + + + void closeEvent ( QCloseEvent *event ); + void populate (); + + void add_workspace ( QString name, QString val, int ngc_id, bool insert = false ); + + void setup_menubar (); + void setup_toolbar (); + + SRAConfigModel *model; + + QAction *discard_action; + QAction *apply_action; + + QRect screen_geometry; + + QVBoxLayout *main_layout; + QVBoxLayout *workspace_layout; + + QCheckBox *remote_enabled_cb; + QCheckBox *local_caching_cb; + QCheckBox *site_cb; + QCheckBox *proxy_cb; + QCheckBox *http_priority_cb; + + QLabel *proxy_label; + QLabel *import_path_label; + + QFrame *adv_setting_window; + + QPushButton *apply_btn; + QPushButton *discard_btn; + + QGroupBox* setup_option_group (); + QGroupBox* setup_workspace_group (); + QVBoxLayout *setup_button_layout(); + + WorkspaceItem *public_workspace; + QVector protected_workspaces; + +}; + +#endif // SRACONFIG_H diff --git a/tools/vdb-config/sra-config/sraconfigmodel.cpp b/tools/vdb-config/sra-config/sraconfigmodel.cpp new file mode 100644 index 00000000..f095a016 --- /dev/null +++ b/tools/vdb-config/sra-config/sraconfigmodel.cpp @@ -0,0 +1,223 @@ +#include "sraconfigmodel.h" +#include "../vdb-config-model.hpp" + +#include + +#include +#include + +static +RootState translate_state ( ESetRootState state ) +{ + switch ( state ) + { + case eSetRootState_OK: + return RootState_OK; // successfully changed repository root + case eSetRootState_NotChanged: + return RootState_NotChanged; // the new path is the same as the old one + case eSetRootState_NotUnique: + return RootState_NotUnique; // there is another repository with the same root + case eSetRootState_MkdirFail: + return RootState_MkdirFail; // failed to make new repository directory + case eSetRootState_NewPathEmpty: + return RootState_NewPathEmpty; // new repository directory path is not empty + case eSetRootState_NewDirNotEmpty: + return RootState_NewDirNotEmpty; // new repository directory is not empty + case eSetRootState_NewNotDir: + return RootState_NewNotDir; // new repository exists and is not a directory + case eSetRootState_OldNotEmpty: + return RootState_OldNotEmpty; // old repository is not empty + case eSetRootState_Error: + return RootState_Error; // some unusual error happened + } +} + +bool SRAConfigModel::commit() +{ + return model . commit (); +} + +bool SRAConfigModel :: config_changed () +{ + return model . get_config_changed (); +} + + +bool SRAConfigModel :: path_exists ( const std :: string &path ) +{ + return model . does_path_exist ( path ); +} + +void SRAConfigModel :: create_directory ( const KNgcObj *ngc ) +{ + model . mkdir ( ngc ); +} + +void SRAConfigModel :: reload () +{ + model . reload (); +} + +// cache +bool SRAConfigModel :: global_cache_enabled () +{ + return model . is_global_cache_enabled (); +} + +bool SRAConfigModel :: user_cache_enabled () +{ + return model . is_user_cache_enabled (); +} + +void SRAConfigModel :: set_global_cache_enabled ( bool enabled ) +{ + model . set_global_cache_enabled ( enabled ); +} + +void SRAConfigModel :: set_user_cache_enabled ( bool enabled ) +{ + model . set_user_cache_enabled ( enabled ); +} + +// network +bool SRAConfigModel :: remote_enabled () +{ + return model . is_remote_enabled (); +} + +void SRAConfigModel :: set_remote_enabled ( bool enabled ) +{ + model . set_remote_enabled ( enabled ); +} + +bool SRAConfigModel :: site_enabled () +{ + return model . is_site_enabled (); +} + +void SRAConfigModel :: set_site_enabled ( bool enabled ) +{ + model . set_site_enabled ( enabled ); +} + +// ngc +bool SRAConfigModel :: import_ngc ( const std :: string path, const KNgcObj *ngc, uint32_t permissions, uint32_t *rslt_flags ) +{ + return model . import_ngc ( path, ngc, permissions, rslt_flags ); +} + +bool SRAConfigModel :: get_ngc_obj_id ( const KNgcObj *ngc, uint32_t *id ) +{ + return model . get_id_of_ngc_obj ( ngc, id ); +} + +std :: string SRAConfigModel :: get_ngc_root ( std :: string &dir, const KNgcObj *ngc ) +{ + return model . get_ngc_root ( dir, ngc ); +} + +// proxy +bool SRAConfigModel :: proxy_enabled () +{ + return model . is_http_proxy_enabled (); +} + +void SRAConfigModel :: set_proxy_enabled ( bool enabled ) +{ + model . set_http_proxy_enabled ( enabled ); +} + +std :: string SRAConfigModel :: get_proxy_path () +{ + return model . get_http_proxy_path (); +} + +void SRAConfigModel :: set_proxy_path ( const std :: string &path ) +{ + model . set_http_proxy_path ( path ); +} + +bool SRAConfigModel :: proxy_priority () +{ + return model . has_http_proxy_env_higher_priority (); +} + +void SRAConfigModel :: set_proxy_priority ( bool priority ) +{ + model . set_http_proxy_env_higher_priority ( priority ); +} + +// settings +std :: string SRAConfigModel :: get_current_path () +{ + return model . get_current_dir (); +} + +std :: string SRAConfigModel :: get_home_path () +{ + return model . get_home_dir (); +} + +std :: string SRAConfigModel :: get_public_path () +{ + return model . get_public_location (); +} + +RootState SRAConfigModel :: set_public_path ( const std :: string &path, bool flushOld, bool reuseNew ) +{ + return translate_state ( model . set_public_location ( flushOld, path, reuseNew ) ); +} + +std :: string SRAConfigModel :: get_user_default_path () +{ + return model . get_user_default_dir (); +} + +void SRAConfigModel :: set_user_default_path ( const char *path ) +{ + model . set_user_default_dir ( path ); +} + +// workspace + +bool SRAConfigModel :: site_workspace_exists () +{ + return model . does_site_repo_exist (); +} + +RootState SRAConfigModel :: configure_workspace ( const std :: string &path, bool reuseNew ) +{ + return translate_state ( model . prepare_repo_directory ( path, reuseNew ) ); +} + +uint32_t SRAConfigModel :: workspace_count () +{ + return model . get_repo_count (); +} + +int32_t SRAConfigModel :: get_workspace_id ( const std :: string &name ) +{ + return model . get_repo_id ( name ); +} + +std :: string SRAConfigModel :: get_workspace_name ( uint32_t id ) +{ + return model . get_repo_name ( id ); +} + +std :: string SRAConfigModel :: get_workspace_path ( uint32_t id ) +{ + return model . get_repo_location ( id ); +} + +RootState SRAConfigModel :: set_workspace_path ( const std :: string & path, uint32_t id, bool flushOld, bool reuseNew ) +{ + return translate_state ( model . set_repo_location ( id, flushOld, path, reuseNew ) ); +} + +SRAConfigModel :: SRAConfigModel ( vdbconf_model &config_model, QObject *parent ) + : QObject ( parent ) + , model ( config_model ) +{ +} + diff --git a/tools/vdb-config/sra-config/sraconfigmodel.h b/tools/vdb-config/sra-config/sraconfigmodel.h new file mode 100644 index 00000000..9b0f887b --- /dev/null +++ b/tools/vdb-config/sra-config/sraconfigmodel.h @@ -0,0 +1,102 @@ +#ifndef SRACONFIGCONTROLLER_H +#define SRACONFIGCONTROLLER_H + +#include + +class vdbconf_model; +struct KNgcObj; + + +enum RootState +{ + RootState_OK, // successfully changed repository root + RootState_NotChanged, // the new path is the same as the old one + RootState_NotUnique, // there is another repository with the same root + RootState_MkdirFail, // failed to make new repository directory + RootState_NewPathEmpty, // new repository directory path is not empty + RootState_NewDirNotEmpty,// new repository directory is not empty + RootState_NewNotDir, // new repository exists and is not a directory + RootState_OldNotEmpty, // old repository is not empty + RootState_Error, // some unusual error happened +}; + +class SRAConfigModel : public QObject +{ + Q_OBJECT + +public: + + bool commit (); + bool config_changed (); + bool path_exists ( const std :: string &path ); + + void create_directory ( const KNgcObj *ngc ); + void reload (); + + + // cache + bool global_cache_enabled (); + void set_global_cache_enabled ( bool enabled ); + + bool user_cache_enabled (); + void set_user_cache_enabled ( bool enabled ); + + // network + bool remote_enabled (); + void set_remote_enabled ( bool enabled ); + + bool site_enabled (); + void set_site_enabled ( bool enabled ); + + // ngc + bool import_ngc ( const std :: string path, const KNgcObj *ngc, uint32_t permissions, uint32_t *rslt_flags ); + bool get_ngc_obj_id ( const KNgcObj *ngc, uint32_t *id ); + std :: string get_ngc_root ( std :: string &dir, const KNgcObj *ngc ); + + // proxy + bool proxy_enabled (); + void set_proxy_enabled ( bool enabled ); + + std :: string get_proxy_path (); + void set_proxy_path ( const std :: string &path ); + + bool proxy_priority (); + void set_proxy_priority ( bool priority ); + + // settings + std :: string get_current_path (); + std :: string get_home_path (); + + std :: string get_public_path (); + RootState set_public_path ( const std :: string &path, bool flushOld, bool reuseNew ); + + std :: string get_user_default_path (); + void set_user_default_path ( const char *path ); + + // workspace + bool site_workspace_exists (); + + RootState configure_workspace ( const std :: string &path, bool reuseNew = false ); + + uint32_t workspace_count (); + int32_t get_workspace_id ( const std :: string &name ); + + std :: string get_workspace_name ( uint32_t id ); + std :: string get_workspace_path ( uint32_t id ); + + RootState set_workspace_path ( const std :: string &path, uint32_t id, bool flushOld, bool reuseNew ); + + // constructor + SRAConfigModel ( vdbconf_model &config_model, QObject *parent = 0 ); + +signals: + + void dirty_config (); + +private: + + vdbconf_model &model; + +}; + +#endif // SRACONFIGCONTROLLER_H diff --git a/tools/vdb-config/sra-config/srapreferences.cpp b/tools/vdb-config/sra-config/srapreferences.cpp new file mode 100644 index 00000000..b3e301d0 --- /dev/null +++ b/tools/vdb-config/sra-config/srapreferences.cpp @@ -0,0 +1,6 @@ +#include "srapreferences.h" + +SRAPreferences :: SRAPreferences ( QWidget *parent ) +{ + +} diff --git a/tools/vdb-config/sra-config/srapreferences.h b/tools/vdb-config/sra-config/srapreferences.h new file mode 100644 index 00000000..881a28f6 --- /dev/null +++ b/tools/vdb-config/sra-config/srapreferences.h @@ -0,0 +1,12 @@ +#ifndef SRAPREFERENCES_H +#define SRAPREFERENCES_H + +#include + +class SRAPreferences +{ +public: + SRAPreferences ( QWidget *parent = 0 ); +}; + +#endif // SRAPREFERENCES_H diff --git a/tools/vdb-config/sra-tools-gui/interfaces/ktoolbaritem.h b/tools/vdb-config/sra-tools-gui/interfaces/ktoolbaritem.h new file mode 100644 index 00000000..72d2a661 --- /dev/null +++ b/tools/vdb-config/sra-tools-gui/interfaces/ktoolbaritem.h @@ -0,0 +1,41 @@ +/*=========================================================================== +* +* 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. +* +* =========================================================================== +* +*/ + +#ifndef KTOOLBARITEM_H +#define KTOOLBARITEM_H + +#include + +class KToolbarItem : public QWidget +{ + +public: + KToolbarItem ( const QString &name, const QString &icon, QWidget *parent = 0 ); + ~KToolbarItem (); + +}; + +#endif // KTOOLBARITEM_H diff --git a/tools/vdb-config/sra-tools-gui/libs/ktoolbaritem.cpp b/tools/vdb-config/sra-tools-gui/libs/ktoolbaritem.cpp new file mode 100644 index 00000000..ee406dc7 --- /dev/null +++ b/tools/vdb-config/sra-tools-gui/libs/ktoolbaritem.cpp @@ -0,0 +1,60 @@ +/*=========================================================================== +* +* 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. +* +* =========================================================================== +* +*/ + +#include "../../sra-tools-gui/interfaces/ktoolbaritem.h" + +#include +#include +#include +#include + +KToolbarItem :: KToolbarItem ( const QString &name, const QString &icon_name, QWidget *parent ) + : QWidget ( parent ) +{ + QVBoxLayout *layout = new QVBoxLayout (); + layout -> setMargin ( 10 ); + layout -> setSpacing ( 10 ); + + QPixmap pxmp = QPixmap :: fromImage ( QImage ( icon_name ) ); + + QLabel *label = new QLabel ( name ); + label -> setPixmap ( pxmp . scaled ( QSize ( 50, 50 ), Qt::IgnoreAspectRatio, Qt::SmoothTransformation ) ); + label -> setScaledContents ( true ); + label -> resize ( 50, 50 ); + + layout -> addWidget ( label ); + + QLabel *txt = new QLabel ( name ); + txt -> setAlignment ( Qt::AlignHCenter ); + layout -> addWidget ( txt ); + + setLayout ( layout ); + +} + +KToolbarItem :: ~KToolbarItem () +{ +} diff --git a/tools/vdb-config/util.cpp b/tools/vdb-config/util.cpp index fdbbb334..f5e41728 100644 --- a/tools/vdb-config/util.cpp +++ b/tools/vdb-config/util.cpp @@ -480,7 +480,7 @@ void CKConfig::Reload(bool verbose) { m_Self = NULL; if (rc == 0) { - rc = KConfigMake(&m_Self, NULL); + rc = KConfigMakeLocal (&m_Self, NULL); } if (rc == 0) { diff --git a/tools/vdb-config/vdb-config-model.cpp b/tools/vdb-config/vdb-config-model.cpp index 184ff2b5..0e7e28e7 100644 --- a/tools/vdb-config/vdb-config-model.cpp +++ b/tools/vdb-config/vdb-config-model.cpp @@ -384,7 +384,7 @@ ESetRootState vdbconf_model::set_repo_location(uint32_t id, } ESetRootState vdbconf_model::set_public_location( - bool flushOld, string &path, bool reuseNew) + bool flushOld, const string &path, bool reuseNew) { ESetRootState res = x_ChangeRepoLocation( path, reuseNew, kPublicRepoId, flushOld ); _config_changed = true; @@ -403,10 +403,11 @@ ESetRootState vdbconf_model::prepare_repo_directory (const string &newPath, bool reuseNew) { ESetRootState res = x_ChangeRepoLocation( newPath, reuseNew, kInvalidRepoId ); - _config_changed = true; + /*_config_changed = true;*/ return res; } + #if TDB bool check_locations_unique(KRepositoryVector *nonUniqueRepos, const string &newRootPath) diff --git a/tools/vdb-config/vdb-config-model.hpp b/tools/vdb-config/vdb-config-model.hpp index f294a429..a7bf6577 100644 --- a/tools/vdb-config/vdb-config-model.hpp +++ b/tools/vdb-config/vdb-config-model.hpp @@ -28,6 +28,7 @@ #define _h_vdb_config_model_ #include +#include #include #include #include @@ -226,6 +227,7 @@ class vdbconf_model } void set_user_enabled( bool enabled ) { + ( void ) enabled; #ifdef ALLOW_USER_REPOSITORY_DISABLING if ( _config_valid ) KConfig_Set_User_Access_Enabled( _config, enabled ); #endif @@ -268,6 +270,7 @@ class vdbconf_model bool is_protected_repo_enabled( uint32_t id ) const { + ( void ) id; bool res = true; #ifdef ALLOW_USER_REPOSITORY_DISABLING if ( _config_valid ) KConfigGetProtectedRepositoryEnabledById( _config, id, &res ); @@ -276,6 +279,8 @@ class vdbconf_model } void set_protected_repo_enabled( uint32_t id, bool enabled ) { + ( void ) id; + ( void ) enabled; #ifdef ALLOW_USER_REPOSITORY_DISABLING if ( _config_valid ) KConfigSetProtectedRepositoryEnabledById( _config, id, enabled ); #endif @@ -324,7 +329,7 @@ class vdbconf_model std::string get_public_location( void ) const; - ESetRootState set_public_location( bool flushOld, std::string &path, bool reuseNew ); + ESetRootState set_public_location(bool flushOld, const std::string &path, bool reuseNew ); bool is_user_public_enabled( void ) const { @@ -428,7 +433,7 @@ class vdbconf_model kcmCreate | kcmParents, root.c_str()) == 0; } - bool does_path_exist( std::string &path ) + bool does_path_exist( const std::string &path ) { bool res = false; if ( _dir != NULL ) @@ -447,7 +452,7 @@ class vdbconf_model _mgr = NULL; KConfigRelease ( _config ); - _config_valid = ( KConfigMake ( &_config, NULL ) == 0 ); + _config_valid = ( KConfigMakeLocal ( &_config, NULL ) == 0 ); if ( _config_valid ) KConfigMakeRepositoryMgrRead( _config, &_mgr ); diff --git a/tools/vdb-config/vdb-config.c b/tools/vdb-config/vdb-config.c index f4b9e562..cec49c0e 100644 --- a/tools/vdb-config/vdb-config.c +++ b/tools/vdb-config/vdb-config.c @@ -1672,6 +1672,8 @@ rc_t CC KMain(int argc, char* argv[]) { } } } + else + rc = 0; } RELEASE ( KDirectory, d ); diff --git a/tools/vdb-dump/vdb-dump-coldefs.c b/tools/vdb-dump/vdb-dump-coldefs.c index af221650..1e13a2a5 100644 --- a/tools/vdb-dump/vdb-dump-coldefs.c +++ b/tools/vdb-dump/vdb-dump-coldefs.c @@ -844,3 +844,105 @@ rc_t vdcd_collect_spread( const struct num_gen * row_set, col_defs * cols, const } return rc; } + +static uint32_t same_values( const VCursor * curs, uint32_t col_idx, int64_t first, uint32_t test_rows ) +{ + uint32_t res = 0; + const void * base; + uint32_t elem_bits, boff, row_len; + rc_t rc = VCursorCellDataDirect( curs, first, col_idx, &elem_bits, &base, &boff, &row_len ); + while ( rc == 0 && res < test_rows && rc == 0 ) + { + const void * base_1; + uint32_t elem_bits_1, boff_1, row_len_1; + rc = VCursorCellDataDirect( curs, first + res + 1, col_idx, &elem_bits_1, &base_1, &boff_1, &row_len_1 ); + if ( rc == 0 ) + { + if ( elem_bits != elem_bits_1 ) return res; + if ( boff != boff_1 ) return res; + if ( row_len != row_len_1 ) return res; + if ( base != base_1 ) return res; + } + res += 1; + } + return res; +} + +static bool vdcd_is_static_column1( const VTable *my_table, col_def * col, uint32_t test_rows ) +{ + bool res = false; + const VCursor * curs; + rc_t rc = VTableCreateCursorRead( my_table, &curs ); + if ( rc == 0 ) + { + uint32_t idx; + rc = VCursorAddColumn( curs, &idx, "%s", col->name ); + if ( rc == 0 ) + { + rc = VCursorOpen( curs ); + if ( rc == 0 ) + { + int64_t first; + uint64_t count; + rc = VCursorIdRange( curs, idx, &first, &count ); + if ( rc == 0 && count == 0 ) + { + res = ( same_values( curs, idx, first, test_rows ) == test_rows ); + } + } + } + VCursorRelease( curs ); + } + return res; +} + +static bool vdcd_is_static_column2( const VTable *my_table, col_def * col ) +{ + bool res = false; + const VCursor * curs; + rc_t rc = VTableCreateCursorRead( my_table, &curs ); + if ( rc == 0 ) + { + uint32_t idx; + rc = VCursorAddColumn( curs, &idx, "%s", col->name ); + if ( rc == 0 ) + { + rc = VCursorOpen( curs ); + if ( rc == 0 ) + rc = VCursorIsStaticColumn( curs, idx, &res ); + } + VCursorRelease( curs ); + } + return res; +} + + +#define TEST_ROWS 20 + +uint32_t vdcd_extract_static_columns( col_defs* defs, const VTable *my_table, const size_t str_limit ) +{ + col_defs * temp_defs; + uint32_t res = 0; + if ( vdcd_init( &temp_defs, str_limit ) ) + { + uint32_t count = vdcd_extract_from_table( temp_defs, my_table ); + uint32_t idx; + for ( idx = 0; idx < count; ++idx ) + { + col_def * col = VectorGet( &(temp_defs->cols), idx ); + if ( col != NULL ) + { + if ( vdcd_is_static_column1( my_table, col, TEST_ROWS ) ) + { + p_col_def c = vdcd_append_col( defs, col->name ); + if ( c != NULL ) + { + res++; + } + } + } + } + vdcd_destroy( temp_defs ); + } + return res; +} \ No newline at end of file diff --git a/tools/vdb-dump/vdb-dump-coldefs.h b/tools/vdb-dump/vdb-dump-coldefs.h index fb81d044..c0c48416 100644 --- a/tools/vdb-dump/vdb-dump-coldefs.h +++ b/tools/vdb-dump/vdb-dump-coldefs.h @@ -101,6 +101,8 @@ void vdcd_ins_trans_fkt( col_defs* defs, const VSchema *my_schema ); void vdcd_exclude_these_columns( col_defs* defs, const char* column_names ); bool vdcd_get_first_none_static_column_idx( col_defs* defs, const VCursor * cur, uint32_t * idx ); +uint32_t vdcd_extract_static_columns( col_defs* defs, const VTable *my_table, const size_t str_limit ); + rc_t vdcd_collect_spread( const struct num_gen * row_set, col_defs * cols, const VCursor * cursor ); #ifdef __cplusplus diff --git a/tools/vdb-dump/vdb-dump-context.c b/tools/vdb-dump/vdb-dump-context.c index e3ac2d7b..17154920 100644 --- a/tools/vdb-dump/vdb-dump-context.c +++ b/tools/vdb-dump/vdb-dump-context.c @@ -138,6 +138,7 @@ static void vdco_init_values( p_dump_context ctx ) ctx->diff = false; ctx->show_spotgroups = false; ctx->show_spread = false; + ctx->len_spread = false; ctx->interactive = false; } @@ -597,6 +598,7 @@ static void vdco_evaluate_options( const Args *my_args, ctx->show_blobbing = vdco_get_bool_option( my_args, OPTION_SHOW_BLOBBING, false ); ctx->enum_phys = vdco_get_bool_option( my_args, OPTION_ENUM_PHYS, false ); ctx->enum_readable = vdco_get_bool_option( my_args, OPTION_ENUM_READABLE, false ); + ctx->enum_static = vdco_get_bool_option( my_args, OPTION_ENUM_STATIC, false ); ctx->idx_enum_requested = vdco_get_bool_option( my_args, OPTION_IDX_ENUM, false ); ctx->disable_multithreading = vdco_get_bool_option( my_args, OPTION_NO_MULTITHREAD, false ); ctx->print_info = vdco_get_bool_option( my_args, OPTION_INFO, false ); @@ -605,6 +607,7 @@ static void vdco_evaluate_options( const Args *my_args, /*ctx->force_sra_schema = vdco_get_bool_option( my_args, OPTION_SRASCHEMA, false );*/ ctx->merge_ranges = vdco_get_bool_option( my_args, OPTION_MERGE_RANGES, false ); ctx->show_spread = vdco_get_bool_option( my_args, OPTION_SPREAD, false ); + ctx->len_spread = vdco_get_bool_option( my_args, OPTION_LEN_SPREAD, false ); ctx->interactive = vdco_get_bool_option( my_args, OPTION_INTERACTIVE, false ); ctx->slice_depth = vdco_get_uint16_option( my_args, OPTION_SLICE, 0 ); diff --git a/tools/vdb-dump/vdb-dump-context.h b/tools/vdb-dump/vdb-dump-context.h index 2bd5d545..9d873c53 100644 --- a/tools/vdb-dump/vdb-dump-context.h +++ b/tools/vdb-dump/vdb-dump-context.h @@ -68,6 +68,7 @@ extern "C" { #define OPTION_SHOW_BLOBBING "blobbing" #define OPTION_ENUM_PHYS "phys" #define OPTION_ENUM_READABLE "readable" +#define OPTION_ENUM_STATIC "static" #define OPTION_IDX_ENUM "idx-report" #define OPTION_IDX_RANGE "idx-range" #define OPTION_CUR_CACHE "cur-cache" @@ -86,6 +87,7 @@ extern "C" { #define OPTION_SPREAD "spread" #define OPTION_SLICE "slice" #define OPTION_INTERACTIVE "interactive" +#define OPTION_LEN_SPREAD "len-spread" #define ALIAS_ROW_ID_ON "I" #define ALIAS_LINE_FEED "l" @@ -186,6 +188,7 @@ typedef struct dump_context bool show_blobbing; bool enum_phys; bool enum_readable; + bool enum_static; bool idx_enum_requested; bool idx_range_requested; bool disable_multithreading; @@ -196,6 +199,7 @@ typedef struct dump_context bool merge_ranges; bool show_spread; bool interactive; + bool len_spread; } dump_context; typedef dump_context* p_dump_context; diff --git a/tools/vdb-dump/vdb-dump-fastq.c b/tools/vdb-dump/vdb-dump-fastq.c index d02fef3b..a0a3733b 100644 --- a/tools/vdb-dump/vdb-dump-fastq.c +++ b/tools/vdb-dump/vdb-dump-fastq.c @@ -26,6 +26,7 @@ #include "vdb-dump-fastq.h" #include "vdb-dump-helper.h" +#include "vdb-dump-tools.h" #include @@ -464,15 +465,18 @@ static rc_t print_qual( const char * qual, uint32_t count, uint32_t max_line_len rc = KOutMsg( "%s", buffer ); on_line = num_writ; } - if ( ( on_line + num_writ + 1 ) < max_line_len ) - { - rc = KOutMsg( " %s", buffer ); - on_line += ( num_writ + 1 ); - } else { - rc = KOutMsg( "\n%s", buffer ); - on_line = num_writ; + if ( ( on_line + num_writ + 1 ) < max_line_len ) + { + rc = KOutMsg( " %s", buffer ); + on_line += ( num_writ + 1 ); + } + else + { + rc = KOutMsg( "\n%s", buffer ); + on_line = num_writ; + } } i++; } @@ -988,7 +992,7 @@ static rc_t vdb_fastq_table( const p_dump_context ctx, const VDBManager *mgr, fastq_ctx * fctx ) { - VSchema * schema = NULL; + VSchema * schema = NULL; rc_t rc; vdh_parse_schema( mgr, &schema, &(ctx->schema_list), true /* ctx->force_sra_schema */ ); @@ -1022,25 +1026,42 @@ static rc_t vdb_fastq_database( const p_dump_context ctx, DISP_RC( rc, "VDBManagerOpenDBRead() failed" ); if ( rc == 0 ) { - bool table_defined = ( ctx->table != NULL ); - if ( !table_defined ) - table_defined = vdh_take_this_table_from_db( ctx, db, "SEQUENCE" ); - - if ( table_defined ) + KNamelist *tbl_names; + rc = VDatabaseListTbl( db, &tbl_names ); + if ( rc != 0 ) + ErrMsg( "VDatabaseListTbl( '%s' ) -> %R", ctx->path, rc ); + else { - rc = VDatabaseOpenTableRead( db, &fctx->tbl, "%s", ctx->table ); - DISP_RC( rc, "VDatabaseOpenTableRead() failed" ); + if ( ctx->table == NULL ) + { + /* the user DID NOT not specify a table: by default assume the SEQUENCE-table */ + bool table_found = vdh_take_this_table_from_list( ctx, tbl_names, "SEQUENCE" ); + /* if there is no SEQUENCE-table, just pick the first table available... */ + if ( !table_found ) + vdh_take_1st_table_from_db( ctx, tbl_names ); + } + else + { + /* the user DID specify a table: check if the database has a table with this name, + if not try with a sub-string */ + String value; + StringInitCString( &value, ctx->table ); + if ( !list_contains_value( tbl_names, &value ) ) + vdh_take_this_table_from_list( ctx, tbl_names, ctx->table ); + } + rc = KNamelistRelease( tbl_names ); + if ( rc != 0 ) + ErrMsg( "KNamelistRelease() -> %R", rc ); + } + if ( rc == 0 ) + { + rc = open_table_by_path( db, ctx->table, &fctx->tbl ); /* vdb-dump-tools.c */ if ( rc == 0 ) { rc = vdb_fastq_tbl( ctx, fctx ); VTableRelease( fctx->tbl ); } } - else - { - LOGMSG( klogInfo, "opened as vdb-database, but no table found/defined" ); - ctx->usage_requested = true; - } VDatabaseRelease( db ); } @@ -1103,10 +1124,6 @@ static rc_t vdb_fastq_by_probing( const p_dump_context ctx, PLOGERR( klogInt, ( klogInt, rc, "the path '$(p)' cannot be opened as vdb-database or vdb-table", "p=%s", ctx->path ) ); - if ( vdco_schema_count( ctx ) == 0 ) - { - LOGERR( klogInt, rc, "Maybe it is a legacy table. If so, specify a schema with the -S option" ); - } } return rc; } @@ -1130,3 +1147,302 @@ rc_t vdf_main( const p_dump_context ctx, const VDBManager * mgr, const char * ac return rc; } + +/* ---------------------------------------------------------------------------------------------------- */ + +#define NUM_COUNTERS 1024 + +static rc_t vdf_len_spread_loop( const p_dump_context ctx, + const VCursor * curs, + bool has_read_len, bool has_ref_len, + uint32_t read_len_idx, uint32_t ref_len_idx, + const char * path ) +{ + const struct num_gen_iter * row_iter; + rc_t rc = num_gen_iterator_make( ctx->rows, &row_iter ); + DISP_RC( rc, "num_gen_iterator_make() failed" ); + if ( rc == 0 ) + { + int64_t row_id; + uint64_t read_len_counters[ NUM_COUNTERS ]; + uint64_t ref_len_counters[ NUM_COUNTERS ]; + uint32_t idx; + + + for ( idx = 0; idx < NUM_COUNTERS; ++idx ) + { + read_len_counters[ idx ] = 0; + ref_len_counters[ idx ] = 0; + } + + while ( rc == 0 && num_gen_iterator_next( row_iter, &row_id, &rc ) ) + { + if ( rc == 0 ) + rc = Quitting(); + if ( rc == 0 ) + { + uint32_t elem_bits, boff, row_len; + uint32_t * ptr; + if ( has_read_len ) + { + rc = VCursorCellDataDirect( curs, row_id, read_len_idx, &elem_bits, (const void**)&ptr, &boff, &row_len ); + if ( rc == 0 && row_len > 0 ) + { + if ( *ptr < NUM_COUNTERS ) + read_len_counters[ *ptr ]++; + else + read_len_counters[ NUM_COUNTERS - 1 ]++; + } + } + if ( has_ref_len ) + { + rc = VCursorCellDataDirect( curs, row_id, ref_len_idx, &elem_bits, (const void**)&ptr, &boff, &row_len ); + if ( rc == 0 && row_len > 0 ) + { + if ( *ptr < NUM_COUNTERS ) + ref_len_counters[ *ptr ]++; + else + ref_len_counters[ NUM_COUNTERS - 1 ]++; + } + } + } + } + + num_gen_iterator_destroy( row_iter ); + + for ( idx = 0; idx < NUM_COUNTERS; ++idx ) + { + if ( read_len_counters[ idx ] > 0 ) + rc = KOutMsg( "READ_LEN[ %d ] = %,lu\n", idx, read_len_counters[ idx ] ); + } + for ( idx = 0; idx < NUM_COUNTERS; ++idx ) + { + if ( ref_len_counters[ idx ] > 0 ) + rc = KOutMsg( "REF_LEN[ %d ] = %,lu\n", idx, ref_len_counters[ idx ] ); + } + } + return rc; +} + +static rc_t vdf_len_spread_vdbtbl( const p_dump_context ctx, const VTable * tbl, const char * path ) +{ + KNamelist * col_names; + rc_t rc = VTableListCol( tbl, &col_names ); + DISP_RC( rc, "VTableListCol() failed" ); + if ( rc == 0 ) + { + const VCursor * curs; + rc = VTableCreateCachedCursorRead( tbl, &curs, 1024 * 1024 * 32 ); + DISP_RC( rc, "VTableCreateCursorRead( fasta/fastq ) failed" ); + if ( rc == 0 ) + { + bool has_read_len = is_name_in_list( col_names, "READ_LEN" ); + bool has_ref_len = is_name_in_list( col_names, "REF_LEN" ); + if ( has_read_len || has_ref_len ) + { + uint32_t read_len_idx, ref_len_idx; + if ( has_read_len ) + { + rc = VCursorAddColumn( curs, &read_len_idx, "READ_LEN" ); + if ( rc != 0 ) + { + PLOGERR( klogInt, ( klogInt, rc, "VCurosrAddColumn( '$(col)' ) failed", "col=%s", "READ_LEN" ) ); + } + } + if ( rc == 0 && has_ref_len ) + { + rc = VCursorAddColumn( curs, &ref_len_idx, "REF_LEN" ); + if ( rc != 0 ) + { + PLOGERR( klogInt, ( klogInt, rc, "VCurosrAddColumn( '$(col)' ) failed", "col=%s", "REF_LEN" ) ); + } + } + if ( rc == 0 ) + { + rc = VCursorOpen( curs ); + DISP_RC( rc, "VCursorOpen( len-spread ) failed" ); + } + if ( rc == 0 ) + { + int64_t first; + uint64_t count; + + if ( has_read_len ) + rc = VCursorIdRange( curs, read_len_idx, &first, &count ); + else + rc = VCursorIdRange( curs, ref_len_idx, &first, &count ); + DISP_RC( rc, "VCursorIdRange() failed" ); + if ( rc == 0 ) + { + if ( count == 0 ) + KOutMsg( "this table is empty\n" ); + else + { + /* if the user did not specify a row-range, take all rows */ + if ( ctx->rows == NULL ) + { + rc = num_gen_make_from_range( &ctx->rows, first, count ); + DISP_RC( rc, "num_gen_make_from_range() failed" ); + } + /* if the user did specify a row-range, check the boundaries */ + else + { + rc = num_gen_trim( ctx->rows, first, count ); + DISP_RC( rc, "num_gen_trim() failed" ); + } + } + } + } + if ( rc == 0 && !num_gen_empty( ctx->rows ) ) + rc = vdf_len_spread_loop( ctx, curs, has_read_len, has_ref_len, read_len_idx, ref_len_idx, path ); /* <=== the meat */ + } + else + { + rc = RC( rcVDB, rcNoTarg, rcConstructing, rcItem, rcNotFound ); + PLOGERR( klogInt, ( klogInt, rc, + "neither READ_LEN nor REF_LEN found in '$(p)'", "p=%s", path ) ); + } + VCursorRelease( curs ); + } + KNamelistRelease( col_names ); + } + return rc; + + return KOutMsg( "vdf_len_spread_vdbtbl\n" ); +} + + +static rc_t vdf_len_spread_db( const p_dump_context ctx, const VDBManager * mgr, const char * path ) +{ + const VDatabase * db; + VSchema *schema = NULL; + rc_t rc; + + vdh_parse_schema( mgr, &schema, &(ctx->schema_list), true /* ctx->force_sra_schema */ ); + + rc = VDBManagerOpenDBRead( mgr, &db, schema, "%s", path ); + DISP_RC( rc, "VDBManagerOpenDBRead() failed" ); + if ( rc == 0 ) + { + KNamelist *tbl_names; + rc = VDatabaseListTbl( db, &tbl_names ); + if ( rc != 0 ) + ErrMsg( "VDatabaseListTbl( '%s' ) -> %R", path, rc ); + else + { + if ( ctx->table == NULL ) + { + /* the user DID NOT not specify a table: by default assume the SEQUENCE-table */ + bool table_found = vdh_take_this_table_from_list( ctx, tbl_names, "SEQUENCE" ); + /* if there is no SEQUENCE-table, just pick the first table available... */ + if ( !table_found ) + vdh_take_1st_table_from_db( ctx, tbl_names ); + } + else + { + /* the user DID specify a table: check if the database has a table with this name, + if not try with a sub-string */ + String value; + StringInitCString( &value, ctx->table ); + if ( !list_contains_value( tbl_names, &value ) ) + vdh_take_this_table_from_list( ctx, tbl_names, ctx->table ); + } + rc = KNamelistRelease( tbl_names ); + if ( rc != 0 ) + ErrMsg( "KNamelistRelease() -> %R", rc ); + } + + if ( rc == 0 ) + { + const VTable * tbl; + rc = open_table_by_path( db, ctx->table, &tbl ); /* vdb-dump-tools.c */ + if ( rc == 0 ) + { + rc = vdf_len_spread_vdbtbl( ctx, tbl, path ); + VTableRelease( tbl ); + } + } + VDatabaseRelease( db ); + } + if ( schema != NULL ) + VSchemaRelease( schema ); + return rc; + +} + + +static rc_t vdf_len_spread_tbl( const p_dump_context ctx, const VDBManager * mgr, const char * path ) +{ + VSchema * schema = NULL; + const VTable * tbl; + rc_t rc; + + vdh_parse_schema( mgr, &schema, &(ctx->schema_list), true /* ctx->force_sra_schema */ ); + + rc = VDBManagerOpenTableRead( mgr, &tbl, schema, "%s", path ); + DISP_RC( rc, "VDBManagerOpenTableRead() failed" ); + if ( rc == 0 ) + { + rc = vdf_len_spread_vdbtbl( ctx, tbl, path ); + VTableRelease( tbl ); + } + if ( schema != NULL ) + VSchemaRelease( schema ); + return rc; + +} + + +static rc_t vdf_len_spread_by_pathtype( const p_dump_context ctx, const VDBManager * mgr, const char * path ) +{ + rc_t rc; + int path_type = ( VDBManagerPathType ( mgr, "%s", path ) & ~ kptAlias ); + /* types defined in */ + switch ( path_type ) + { + case kptDatabase : rc = vdf_len_spread_db( ctx, mgr, path ); break; + + case kptPrereleaseTbl: + case kptTable : rc = vdf_len_spread_tbl( ctx, mgr, path ); break; + + default : rc = RC( rcVDB, rcNoTarg, rcConstructing, rcItem, rcNotFound ); + PLOGERR( klogInt, ( klogInt, rc, + "the path '$(p)' cannot be opened as vdb-database or vdb-table", + "p=%s", ctx->path ) ); + break; + } + return rc; + +} + +static rc_t vdf_len_spread_by_probing( const p_dump_context ctx, const VDBManager * mgr, const char * path ) +{ + rc_t rc; + if ( vdh_is_path_database( mgr, path, &(ctx->schema_list) ) ) + { + rc = vdf_len_spread_db( ctx, mgr, path ); + } + else if ( vdh_is_path_table( mgr, path, &(ctx->schema_list) ) ) + { + rc = vdf_len_spread_tbl( ctx, mgr, path ); + } + else + { + rc = RC( rcVDB, rcNoTarg, rcConstructing, rcItem, rcNotFound ); + PLOGERR( klogInt, ( klogInt, rc, + "the path '$(p)' cannot be opened as vdb-database or vdb-table", + "p=%s", path ) ); + } + return rc; + +} + +rc_t vdf_len_spread( const p_dump_context ctx, const VDBManager * mgr, const char * path ) +{ + rc_t rc = 0; + if ( USE_PATHTYPE_TO_DETECT_DB_OR_TAB ) /* in vdb-dump-context.h */ + rc = vdf_len_spread_by_pathtype( ctx, mgr, path ); + else + rc = vdf_len_spread_by_probing( ctx, mgr, path ); + return rc; +} diff --git a/tools/vdb-dump/vdb-dump-fastq.h b/tools/vdb-dump/vdb-dump-fastq.h index 652718ca..e598e398 100644 --- a/tools/vdb-dump/vdb-dump-fastq.h +++ b/tools/vdb-dump/vdb-dump-fastq.h @@ -40,6 +40,8 @@ extern "C" { rc_t vdf_main( const p_dump_context ctx, const VDBManager * mgr, const char * acc_or_path ); +rc_t vdf_len_spread( const p_dump_context ctx, const VDBManager * mgr, const char * path ); + #ifdef __cplusplus } #endif diff --git a/tools/vdb-dump/vdb-dump-str.c b/tools/vdb-dump/vdb-dump-str.c index 8dac7e79..d96e6771 100644 --- a/tools/vdb-dump/vdb-dump-str.c +++ b/tools/vdb-dump/vdb-dump-str.c @@ -537,4 +537,4 @@ rc_t vds_diff( const char * f1, const char * f2 ) clear_recorded_errors(); return rc; -} \ No newline at end of file +} diff --git a/tools/vdb-dump/vdb-dump-tools.c b/tools/vdb-dump/vdb-dump-tools.c index bbcee5c9..f831578f 100644 --- a/tools/vdb-dump/vdb-dump-tools.c +++ b/tools/vdb-dump/vdb-dump-tools.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -526,3 +527,111 @@ rc_t vdt_dump_element( const p_dump_src src, const p_col_def def, bool bracket ) src->element_idx++; return rc; } + + +void vdm_clear_recorded_errors( void ) +{ + rc_t rc; + const char * filename; + const char * funcname; + uint32_t line_nr; + while ( GetUnreadRCInfo ( &rc, &filename, &funcname, &line_nr ) ) + { + } +} + + +static rc_t walk_sections( const VDatabase * base_db, const VDatabase ** sub_db, + const VNamelist * sections, uint32_t count ) +{ + rc_t rc = 0; + const VDatabase * parent_db = base_db; + if ( count == 0 ) + { + rc = VDatabaseAddRef ( parent_db ); + DISP_RC( rc, "VDatabaseAddRef() failed" ); + } + else + { + uint32_t idx; + for ( idx = 0; rc == 0 && idx < count; ++idx ) + { + const char * dbname; + rc = VNameListGet ( sections, idx, &dbname ); + DISP_RC( rc, "VNameListGet() failed" ); + if ( rc == 0 ) + { + const VDatabase * temp; + rc = VDatabaseOpenDBRead ( parent_db, &temp, "%s", dbname ); + DISP_RC( rc, "VDatabaseOpenDBRead() failed" ); + if ( rc == 0 && idx > 0 ) + { + rc = VDatabaseRelease ( parent_db ); + DISP_RC( rc, "VDatabaseRelease() failed" ); + } + if ( rc == 0 ) + parent_db = temp; + } + } + } + + if ( rc == 0 ) *sub_db = parent_db; + return rc; +} + + +rc_t check_table_empty( const VTable * tab ) +{ + bool empty; + rc_t rc = VTableIsEmpty( tab, &empty ); + DISP_RC( rc, "VTableIsEmpty() failed" ); + if ( rc == 0 && empty ) + { + vdm_clear_recorded_errors(); + KOutMsg( "the requested table is empty!\n" ); + rc = RC( rcVDB, rcNoTarg, rcConstructing, rcTable, rcEmpty ); + } + return rc; +} + + +rc_t open_table_by_path( const VDatabase * db, const char * inner_db_path, const VTable ** tab ) +{ + VNamelist * sections; + rc_t rc = vds_path_to_sections( inner_db_path, '.', §ions ); + DISP_RC( rc, "vds_path_to_sections() failed" ); + if ( rc == 0 ) + { + uint32_t count; + rc = VNameListCount ( sections, &count ); + DISP_RC( rc, "VNameListCount() failed" ); + if ( rc == 0 && count > 0 ) + { + const VDatabase * sub_db; + rc = walk_sections( db, &sub_db, sections, count - 1 ); + if ( rc == 0 ) + { + const char * tabname; + rc = VNameListGet ( sections, count - 1, &tabname ); + DISP_RC( rc, "VNameListGet() failed" ); + if ( rc == 0 ) + { + rc = VDatabaseOpenTableRead( sub_db, tab, "%s", tabname ); + DISP_RC( rc, "VDatabaseOpenTableRead() failed" ); + if ( rc == 0 ) + { + rc = check_table_empty( *tab ); + if ( rc != 0 ) + { + VTableRelease( *tab ); + tab = NULL; + } + } + } + VDatabaseRelease ( sub_db ); + } + } + VNamelistRelease ( sections ); + } + return rc; +} diff --git a/tools/vdb-dump/vdb-dump-tools.h b/tools/vdb-dump/vdb-dump-tools.h index d8b7ac71..64060c27 100644 --- a/tools/vdb-dump/vdb-dump-tools.h +++ b/tools/vdb-dump/vdb-dump-tools.h @@ -53,6 +53,12 @@ typedef dump_src* p_dump_src; rc_t vdt_dump_element( const p_dump_src src, const p_col_def def, bool bracket ); +void vdm_clear_recorded_errors( void ); + +rc_t check_table_empty( const VTable * tab ); + +rc_t open_table_by_path( const VDatabase * db, const char * inner_db_path, const VTable ** tab ); + #ifdef __cplusplus } #endif diff --git a/tools/vdb-dump/vdb-dump.c b/tools/vdb-dump/vdb-dump.c index fe5eff4e..3ad4f5d7 100644 --- a/tools/vdb-dump/vdb-dump.c +++ b/tools/vdb-dump/vdb-dump.c @@ -104,6 +104,7 @@ static const char * numelemsum_usage[] = { "sum element-count", static const char * show_blobbing_usage[] = { "show blobbing", NULL }; static const char * enum_phys_usage[] = { "enumerate physical columns", NULL }; static const char * enum_readable_usage[] = { "enumerate readable columns", NULL }; +static const char * enum_static_usage[] = { "enumerate static columns", NULL }; static const char * objtype_usage[] = { "report type of object", NULL }; static const char * idx_enum_usage[] = { "enumerate all available index", NULL }; static const char * idx_range_usage[] = { "enumerate values and row-ranges of one index", NULL }; @@ -118,6 +119,7 @@ static const char * info_usage[] = { "print info about run", static const char * spotgroup_usage[] = { "show spotgroups", NULL }; static const char * merge_ranges_usage[] = { "merge and sort row-ranges", NULL }; static const char * spread_usage[] = { "show spread of integer values", NULL }; +static const char * len_spread_usage[] = { "show spread of READ/REF_LEN values", NULL }; static const char * slice_usage[] = { "find a slice of given depth", NULL }; static const char * interactive_usage[] = { "interactive mode", NULL }; @@ -149,6 +151,7 @@ OptDef DumpOptions[] = { OPTION_SHOW_BLOBBING, NULL, NULL, show_blobbing_usage, 1, false, false }, { OPTION_ENUM_PHYS, NULL, NULL, enum_phys_usage, 1, false, false }, { OPTION_ENUM_READABLE, NULL, NULL, enum_readable_usage, 1, false, false }, + { OPTION_ENUM_STATIC, NULL, NULL, enum_static_usage, 1, false, false }, { OPTION_OBJVER, ALIAS_OBJVER, NULL, objver_usage, 1, false, false }, { OPTION_OBJTS, NULL, NULL, objts_usage, 1, false, false }, { OPTION_OBJTYPE, ALIAS_OBJTYPE, NULL, objtype_usage, 1, false, false }, @@ -167,6 +170,7 @@ OptDef DumpOptions[] = { OPTION_SPOTGROUPS, NULL, NULL, spotgroup_usage, 1, false, false }, { OPTION_MERGE_RANGES, NULL, NULL, merge_ranges_usage, 1, false, false }, { OPTION_SPREAD, NULL, NULL, spread_usage, 1, false, false }, + { OPTION_LEN_SPREAD, NULL, NULL, len_spread_usage, 1, false, false }, { OPTION_INTERACTIVE, NULL, NULL, interactive_usage, 1, false, false }, { OPTION_SLICE, NULL, NULL, slice_usage, 1, true, false } }; @@ -522,8 +526,29 @@ static uint32_t vdm_extract_or_parse_columns( const p_dump_context ctx, { bool cols_unknown = ( ( ctx->columns == NULL ) || ( string_cmp( ctx->columns, 1, "*", 1, 1 ) == 0 ) ); if ( cols_unknown ) - /* the user does not know the column-names or wants all of them */ - count = vdcd_extract_from_table( my_col_defs, my_table ); + { + if ( ctx->enum_static ) + { + /* the user wants to see only the static columns */ + count = vdcd_extract_static_columns( my_col_defs, my_table, ctx->max_line_len ); + if ( count > 0 ) + { + /* if we found some static columns, let's restrict the row-count + if the user did not give a specific row-set to just show row #1 */ + if ( ctx->rows == NULL ) + { + rc_t rc = num_gen_make_from_range( &ctx->rows, 1, 1 ); + DISP_RC( rc, "num_gen_make_from_range() failed" ); + } + + } + } + else + { + /* the user does not know the column-names or wants all of them */ + count = vdcd_extract_from_table( my_col_defs, my_table ); + } + } else /* the user knows the names of the wanted columns... */ count = vdcd_parse_string( my_col_defs, ctx->columns, my_table ); @@ -545,8 +570,10 @@ static bool vdm_extract_or_parse_phys_columns( const p_dump_context ctx, { bool cols_unknown = ( ( ctx->columns == NULL ) || ( string_cmp( ctx->columns, 1, "*", 1, 1 ) == 0 ) ); if ( cols_unknown ) + { /* the user does not know the column-names or wants all of them */ res = vdcd_extract_from_phys_table( my_col_defs, my_table ); + } else /* the user knows the names of the wanted columns... */ res = vdcd_parse_string( my_col_defs, ctx->columns, my_table ); @@ -558,6 +585,24 @@ static bool vdm_extract_or_parse_phys_columns( const p_dump_context ctx, return res; } + +static bool vdm_extract_or_parse_static_columns( const p_dump_context ctx, + const VTable *my_table, + p_col_defs my_col_defs ) +{ + bool res = false; + if ( ctx != NULL && my_col_defs != NULL ) + { + /* the user does not know the column-names or wants all of them */ + res = ( vdcd_extract_static_columns( my_col_defs, my_table, ctx->max_line_len ) > 0 ); + + if ( ctx->excluded_columns != NULL ) + vdcd_exclude_these_columns( my_col_defs, ctx->excluded_columns ); + } + return res; + +} + /************************************************************************************* dump_tab_table: * called by "dump_db_table()" and "dump_tab()" as a fkt-pointer @@ -683,117 +728,11 @@ static rc_t vdm_dump_opened_table( const p_dump_context ctx, const VTable *my_ta ctx [IN] ... contains path, tablename, columns, row-range etc. my_database [IN] ... open database needed for vdb-calls *************************************************************************************/ -static rc_t vdm_walk_sections( const VDatabase * base_db, const VDatabase ** sub_db, - const VNamelist * sections, uint32_t count ) -{ - rc_t rc = 0; - const VDatabase * parent_db = base_db; - if ( count == 0 ) - { - rc = VDatabaseAddRef ( parent_db ); - DISP_RC( rc, "VDatabaseAddRef() failed" ); - } - else - { - uint32_t idx; - for ( idx = 0; rc == 0 && idx < count; ++idx ) - { - const char * dbname; - rc = VNameListGet ( sections, idx, &dbname ); - DISP_RC( rc, "VNameListGet() failed" ); - if ( rc == 0 ) - { - const VDatabase * temp; - rc = VDatabaseOpenDBRead ( parent_db, &temp, "%s", dbname ); - DISP_RC( rc, "VDatabaseOpenDBRead() failed" ); - if ( rc == 0 && idx > 0 ) - { - rc = VDatabaseRelease ( parent_db ); - DISP_RC( rc, "VDatabaseRelease() failed" ); - } - if ( rc == 0 ) - parent_db = temp; - } - } - } - - if ( rc == 0 ) *sub_db = parent_db; - return rc; -} - - -static void vdm_clear_recorded_errors( void ) -{ - rc_t rc; - const char * filename; - const char * funcname; - uint32_t line_nr; - while ( GetUnreadRCInfo ( &rc, &filename, &funcname, &line_nr ) ) - { - } -} - - -static rc_t vdm_check_table_empty( const VTable * tab ) -{ - bool empty; - rc_t rc = VTableIsEmpty( tab, &empty ); - DISP_RC( rc, "VTableIsEmpty() failed" ); - if ( rc == 0 && empty ) - { - vdm_clear_recorded_errors(); - KOutMsg( "the requested table is empty!\n" ); - rc = RC( rcVDB, rcNoTarg, rcConstructing, rcTable, rcEmpty ); - } - return rc; -} - -static rc_t vdm_open_table_by_path( const VDatabase * db, const char * path, const VTable ** tab ) -{ - VNamelist * sections; - rc_t rc = vds_path_to_sections( path, '.', §ions ); - DISP_RC( rc, "vds_path_to_sections() failed" ); - if ( rc == 0 ) - { - uint32_t count; - rc = VNameListCount ( sections, &count ); - DISP_RC( rc, "VNameListCount() failed" ); - if ( rc == 0 && count > 0 ) - { - const VDatabase * sub_db; - rc = vdm_walk_sections( db, &sub_db, sections, count - 1 ); - if ( rc == 0 ) - { - const char * tabname; - rc = VNameListGet ( sections, count - 1, &tabname ); - DISP_RC( rc, "VNameListGet() failed" ); - if ( rc == 0 ) - { - rc = VDatabaseOpenTableRead( sub_db, tab, "%s", tabname ); - DISP_RC( rc, "VDatabaseOpenTableRead() failed" ); - if ( rc == 0 ) - { - rc = vdm_check_table_empty( *tab ); - if ( rc != 0 ) - { - VTableRelease( *tab ); - tab = NULL; - } - } - } - VDatabaseRelease ( sub_db ); - } - } - VNamelistRelease ( sections ); - } - return rc; -} - static rc_t vdm_dump_opened_database( const p_dump_context ctx, const VDatabase *my_database ) { const VTable *my_table; - rc_t rc = vdm_open_table_by_path( my_database, ctx->table, &my_table ); + rc_t rc = open_table_by_path( my_database, ctx->table, &my_table ); if ( rc == 0 ) { rc = vdm_dump_opened_table( ctx, my_table ); @@ -876,7 +815,7 @@ static rc_t vdm_show_db_spread( const p_dump_context ctx, const VDatabase *my_database ) { const VTable *my_table; - rc_t rc = vdm_open_table_by_path( my_database, ctx->table, &my_table ); + rc_t rc = open_table_by_path( my_database, ctx->table, &my_table ); if ( rc == 0 ) { rc = vdm_show_tab_spread( ctx, my_table ); @@ -956,7 +895,7 @@ static rc_t vdm_dump_db_schema( const p_dump_context ctx, { /* the user has given a database as object, but asks to inspect a given table */ const VTable *my_table; - rc = vdm_open_table_by_path( my_database, ctx->table, &my_table ); + rc = open_table_by_path( my_database, ctx->table, &my_table ); if ( rc == 0 ) { rc = vdm_dump_tab_schema( ctx, my_table ); @@ -1299,6 +1238,7 @@ static rc_t vdm_enum_readable_columns( const VTable *my_table ) return rc; } + /************************************************************************************* enum_tab_columns: * called by "enum_db_columns()" and "dump_table()" as fkt-pointer @@ -1344,6 +1284,13 @@ static rc_t vdm_enum_tab_columns( const p_dump_context ctx, const VTable *my_tab rc = VTableOpenKTableRead( my_table, &ci_ctx.my_ktable ); DISP_RC( rc, "VTableOpenKTableRead() failed" ); } + if ( ctx->enum_static ) + { + extracted = vdm_extract_or_parse_static_columns( ctx, my_table, my_col_defs ); + rc = VTableOpenKTableRead( my_table, &ci_ctx.my_ktable ); + DISP_RC( rc, "VTableOpenKTableRead() failed" ); + + } else { extracted = vdm_extract_or_parse_columns( ctx, my_table, my_col_defs ); @@ -1396,7 +1343,7 @@ my_database [IN] ... open database needed for vdb-calls static rc_t vdm_enum_db_columns( const p_dump_context ctx, const VDatabase *my_database ) { const VTable *my_table; - rc_t rc = vdm_open_table_by_path( my_database, ctx->table, &my_table ); + rc_t rc = open_table_by_path( my_database, ctx->table, &my_table ); if ( rc == 0 ) { rc = vdm_enum_tab_columns( ctx, my_table ); @@ -1469,7 +1416,7 @@ my_database [IN] ... open database needed for vdb-calls static rc_t vdm_print_db_id_range( const p_dump_context ctx, const VDatabase *my_database ) { const VTable *my_table; - rc_t rc = vdm_open_table_by_path( my_database, ctx->table, &my_table ); + rc_t rc = open_table_by_path( my_database, ctx->table, &my_table ); if ( rc == 0 ) { rc = vdm_print_tab_id_range( ctx, my_table ); @@ -1570,7 +1517,7 @@ static rc_t vdm_enum_tab_index( const p_dump_context ctx, const VTable *my_table static rc_t vdm_enum_db_index( const p_dump_context ctx, const VDatabase *my_database ) { const VTable *my_table; - rc_t rc = vdm_open_table_by_path( my_database, ctx->table, &my_table ); + rc_t rc = open_table_by_path( my_database, ctx->table, &my_table ); if ( rc == 0 ) { rc = vdm_enum_tab_index( ctx, my_table ); @@ -1619,7 +1566,7 @@ static rc_t vdm_range_tab_index( const p_dump_context ctx, const VTable *my_tabl static rc_t vdm_range_db_index( const p_dump_context ctx, const VDatabase *my_database ) { const VTable *my_table; - rc_t rc = vdm_open_table_by_path( my_database, ctx->table, &my_table ); + rc_t rc = open_table_by_path( my_database, ctx->table, &my_table ); if ( rc == 0 ) { rc = vdm_range_tab_index( ctx, my_table ); @@ -1715,7 +1662,7 @@ static rc_t vdm_show_tab_spotgroups( const p_dump_context ctx, const VTable *my_ static rc_t vdm_show_db_spotgroups( const p_dump_context ctx, const VDatabase *my_database ) { const VTable *my_table; - rc_t rc = vdm_open_table_by_path( my_database, ctx->table, &my_table ); + rc_t rc = open_table_by_path( my_database, ctx->table, &my_table ); if ( rc == 0 ) { rc = vdm_show_tab_spotgroups( ctx, my_table ); @@ -1757,7 +1704,7 @@ static rc_t vdm_dump_tab_fkt( const p_dump_context ctx, ErrMsg( "VDBManagerOpenTableRead( '%R' ) -> %R", ctx->path, rc ); else { - rc = vdm_check_table_empty( my_table ); + rc = check_table_empty( my_table ); if ( rc == 0 ) rc = tab_fkt( ctx, my_table ); /* fkt-pointer is called */ VTableRelease( my_table ); @@ -2213,6 +2160,8 @@ static rc_t vdm_main( const p_dump_context ctx, Args * args ) if ( ctx->print_info ) rc = vdb_info( &(ctx->schema_list), ctx->format, mgr, value, ctx->rows ); /* in vdb_info.c */ + else if ( ctx->len_spread ) + rc = vdf_len_spread( ctx, mgr, value ); /* in vdb-dump-fastq.c */ else switch( ctx->format ) { case df_fastq : ; @@ -2328,17 +2277,17 @@ rc_t CC KMain ( int argc, char *argv [] ) if ( rc == 0 ) { if ( ctx->phase > 0 ) - rc = vdi_bin_phase( ctx, args ); /* vdb-dump-bin.c */ + rc = vdi_bin_phase( ctx, args ); /* vdb-dump-bin.c */ else if ( ctx->diff ) - rc = diff_files( args ); /* above calls into vdb-dump-str.c */ + rc = diff_files( args ); /* code is above, calls into vdb-dump-str.c */ else if ( ctx->interactive ) - rc = vdi_main( ctx, args ); /* vdb-dump-interact.c */ + rc = vdi_main( ctx, args ); /* vdb-dump-interact.c */ else if ( ctx->slice_depth > 0 ) - rc = find_slice( ctx, args ); /* vdb-dump-str.c */ + rc = find_slice( ctx, args ); /* vdb-dump-str.c */ else rc = vdm_main( ctx, args ); - release_out_redir( &redir ); /* vdb-dump-redir.c */ + release_out_redir( &redir ); /* vdb-dump-redir.c */ } } vdco_destroy( ctx );