diff --git a/libs/seiscomp/io/recordstream/descriptions/global_recordstream.rst b/libs/seiscomp/io/recordstream/descriptions/global_recordstream.rst index d190c0722..4ee08aee8 100644 --- a/libs/seiscomp/io/recordstream/descriptions/global_recordstream.rst +++ b/libs/seiscomp/io/recordstream/descriptions/global_recordstream.rst @@ -198,6 +198,10 @@ This process is repeated for each requested channel individually. It always starts to search data from the first given SDS to the last one, for each data channel. +Optional URL encoded parameters are: + +- `format` - miniSEED format to read (2,3), default: any + Examples ^^^^^^^^ diff --git a/libs/seiscomp/io/recordstream/sdsarchive.cpp b/libs/seiscomp/io/recordstream/sdsarchive.cpp index 40ce8b24c..738c14a94 100644 --- a/libs/seiscomp/io/recordstream/sdsarchive.cpp +++ b/libs/seiscomp/io/recordstream/sdsarchive.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include "sdsarchive.h" @@ -188,7 +189,8 @@ bool SDSArchive::Index::operator==(const Index &other) const { // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -SDSArchive::SDSArchive() {} +SDSArchive::SDSArchive() { +} // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @@ -212,11 +214,23 @@ SDSArchive::~SDSArchive() {} // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> bool SDSArchive::setSource(const string &src) { - if ( src.empty() ) { + Util::Url url(src); + + if ( url.hasQueryItem("format") ) { + if ( !Core::fromString(_format, url.queryItemValue("format")) || + _format < 2 || _format > 3 ) { + SEISCOMP_ERROR("Invalid 'format' (must be '2' or '3')"); + return false; + } + } + + string arcroots = url.path(); + + if ( arcroots.empty() ) { _arcroots.push_back(Environment::Instance()->installDir() + "/var/lib/archive"); } else { - Core::split(_arcroots, src.c_str(), ","); + Core::split(_arcroots, arcroots.c_str(), ","); } for ( string &root : _arcroots ) { @@ -392,7 +406,17 @@ bool SDSArchive::resolveSta(string &pathStr, int doy, int year, bool first) { if ( !isWildcard(sta) ) { pathStr += sta + "/"; - return resolveCha(pathStr, net, sta, loc, cha, requestStartTime, doy, year, first); + bool res = true; + + if ( _format == 0 || _format == 2 ) { + res = resolveCha(pathStr, net, sta, loc, cha, "D", requestStartTime, doy, year, first); + } + + if ( res && (_format == 0 || _format == 3) ) { + res &= resolveCha(pathStr, net, sta, loc, cha, "3", requestStartTime, doy, year, first); + } + + return res; } try { @@ -407,7 +431,13 @@ bool SDSArchive::resolveSta(string &pathStr, string staPath = pathStr + leaf + "/"; // Got a station here - resolveCha(staPath, net, leaf, loc, cha, requestStartTime, doy, year, first); + if ( _format == 0 || _format == 2 ) { + resolveCha(staPath, net, leaf, loc, cha, "D", requestStartTime, doy, year, first); + } + + if ( _format == 0 || _format == 3 ) { + resolveCha(staPath, net, leaf, loc, cha, "3", requestStartTime, doy, year, first); + } } } catch ( ... ) { @@ -425,17 +455,18 @@ bool SDSArchive::resolveSta(string &pathStr, bool SDSArchive::resolveCha(string &pathStr, const string &net, const string &sta, const string &loc, const string &cha, + const string &ext, const Time &requestStartTime, int doy, int year, bool first) { if ( !isWildcard(cha) ) { - pathStr += cha + ".D/"; - return resolveLoc(pathStr, net, sta, loc, cha, requestStartTime, doy, year, first); + string chaPath = pathStr + cha + "." + ext + "/"; + return resolveLoc(chaPath, net, sta, loc, cha, ext, requestStartTime, doy, year, first); } try { SC_FS_DECLARE_PATH(path, pathStr) fs::directory_iterator it(path); - string chaSel = cha + ".D"; + string chaSel = cha + "." + ext; for ( ; it != fsDirEnd; ++it ) { if ( !fs::is_directory(*it) ) continue; @@ -443,10 +474,10 @@ bool SDSArchive::resolveCha(string &pathStr, if ( !wildcmp(chaSel, leaf) ) continue; string chaPath = pathStr + leaf + "/"; - leaf.erase(leaf.rfind(".D")); + leaf.erase(leaf.rfind("." + ext)); // Got a channel here - resolveLoc(chaPath, net, sta, loc, leaf, requestStartTime, doy, year, first); + resolveLoc(chaPath, net, sta, loc, leaf, ext, requestStartTime, doy, year, first); } } catch ( ... ) { @@ -464,12 +495,13 @@ bool SDSArchive::resolveCha(string &pathStr, bool SDSArchive::resolveLoc(string &pathStr, const string &net, const string &sta, const string &loc, const string &cha, + const string &ext, const Time &requestStartTime, int doy, int year, bool first) { char buf[10]; string filename; snprintf(buf, 9, "%d", year); - filename = net + "." + sta + "." + loc + "." + cha + ".D." + buf + "."; + filename = net + "." + sta + "." + loc + "." + cha + "." + ext + "." + buf + "."; snprintf(buf, 9, "%03d", doy); filename += buf; @@ -482,7 +514,7 @@ bool SDSArchive::resolveLoc(string &pathStr, if ( first && getStartTime(fpath) > requestStartTime ) { (Time::FromYearDay(year, doy) - TimeSpan(86400,0)).get2(&year, &doy); - resolveLoc(pathStr, net, sta, loc, cha, requestStartTime, doy+1, year, true); + resolveLoc(pathStr, net, sta, loc, cha, ext, requestStartTime, doy+1, year, true); first = false; } @@ -514,7 +546,7 @@ bool SDSArchive::resolveLoc(string &pathStr, if ( first && getStartTime(fpath) > requestStartTime ) { (Time::FromYearDay(year, doy) - TimeSpan(86400,0)).get2(&year, &doy); - resolveLoc(pathStr, net, sta, loc, cha, requestStartTime, doy+1, year, first); + resolveLoc(pathStr, net, sta, loc, cha, ext, requestStartTime, doy+1, year, first); } SEISCOMP_DEBUG("+ %s", fpath); diff --git a/libs/seiscomp/io/recordstream/sdsarchive.h b/libs/seiscomp/io/recordstream/sdsarchive.h index 6ba4b4ac6..acc588840 100644 --- a/libs/seiscomp/io/recordstream/sdsarchive.h +++ b/libs/seiscomp/io/recordstream/sdsarchive.h @@ -123,6 +123,9 @@ class SDSArchive : public Seiscomp::IO::RecordStream { bool _closeRequested; std::ifstream _file; + //! 2: mseed2, 3: mseed3, 0: any + int _format{0}; + int getDoy(const Seiscomp::Core::Time &time); void resolveRequest(); bool setStart(const std::string &fname, bool bsearch); @@ -140,11 +143,13 @@ class SDSArchive : public Seiscomp::IO::RecordStream { bool resolveLoc(std::string &path, const std::string &net, const std::string &sta, const std::string &loc, const std::string &cha, + const std::string &ext, const Seiscomp::Core::Time &requestStartTime, int doy, int year, bool first); bool resolveCha(std::string &path, const std::string &net, const std::string &sta, const std::string &loc, const std::string &cha, + const std::string &ext, const Seiscomp::Core::Time &requestStartTime, int doy, int year, bool first);