diff --git a/.gitignore b/.gitignore index 6bbc474648..2a9b873cb1 100644 --- a/.gitignore +++ b/.gitignore @@ -176,4 +176,4 @@ timing/*/*.dtps /bw-output/ ## IDE configuration -.vscode/** +.vscode/*.json diff --git a/.vscode/jhrg/settings.json b/.vscode/jhrg/settings.json index 9ec8ed642f..a00f09a687 100644 --- a/.vscode/jhrg/settings.json +++ b/.vscode/jhrg/settings.json @@ -1,7 +1,8 @@ { // For Hyrax, prefix and PATH need to be set. jhrg 3/11/26 - "prefix": "/Users/jimg/src/opendap/hyrax/build", + "prefix": "/Users/jimg/src/opendap/hyrax_git/build", "PATH": "${config:prefix}/bin:${config:prefix}/deps/bin:${env:PATH}", + // C/C++ extensionsettings. jhrg 3/11/26 "C_Cpp.default.configurationProvider": "ms-vscode.makefile-tools", "C_Cpp.default.compileCommands": "${workspaceFolder}/compile_commands.json", "C_Cpp.default.includePath": [ @@ -18,11 +19,24 @@ "${workspaceFolder}/server/**", "${workspaceFolder}/standalone/**", "${workspaceFolder}/xmlcommand/**", - "${workspaceFolder}/modules/**", + "${workspaceFolder}/modules/**" ], "C_Cpp.default.cppStandard": "c++14", "C_Cpp.default.intelliSenseMode": "macos-clang-arm64", "C_Cpp.vcFormat.indent.namespaceContents": false, + // Makefile settings. jhrg 3/11/26 + "files.associations": { + "*.am": "makefile" + }, + "[makefile]": { + "editor.insertSpaces": false + }, + // Exclude object files from the file explorer. jhrg 3/29/26 + "files.exclude": { + "**/*.o": true, + "**/*.lo": true + }, + // Terminal environment settings. jhrg 3/11/26 "terminal.integrated.env.osx": { "prefix": "${config:prefix}", "PATH": "${config:PATH}" diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000000..593b7acaa9 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,105 @@ +# AGENTS.md + +## Scope + +These instructions apply to the entire `bes` repository. + +## Project Context + +- `bes` is the Back-End Server for Hyrax and is a long-lived C++ codebase with downstream users who depend on stable behavior. +- Prefer compatibility, behavioral stability, and small reviewable diffs over broad cleanup or refactoring. +- Treat changes to protocol behavior, server startup/configuration, packaging, and installed layout as high risk. + +## Primary Build System + +- Use autotools for normal development work in this repository. +- A top-level `CMakeLists.txt` exists, but ignore that since it is a relic. + +## Autotools Workflow + +For a fresh git checkout: + +```sh +autoreconf --force --install --verbose +./configure --prefix="$prefix" --with-dependencies="$prefix/deps" --enable-developer +make -j +make check +``` + +For a source-distribution style build: + +```sh +./configure +make -j +make check +``` + +Notes: + +- Check that `prefix` is defined before using commands that rely on it. +- Use `--with-dependencies=` when BES dependencies are installed outside standard system paths. +- `--enable-developer` is the normal developer-mode configure option in this repo. +- Useful configure toggles defined at the top level include `--enable-asan`, `--enable-coverage`, `--without-cmr`, `--without-ngap`, and `--without-s3`. +- `make distcheck` is a supported validation path here; top-level build files already carry `AM_DISTCHECK_CONFIGURE_FLAGS` logic for dependency-aware distcheck runs. + +## Testing Expectations + +- For code changes, run focused validation first, then broaden test scope when the risk warrants it. +- Default autotools validation is `make check`. +- Parallel test runs are used in CI, but `INSTALL` notes that some tests may object to parallel execution; if `-j` causes issues, retry serially and mention that in your summary. +- If you change build, packaging, or install behavior, consider whether `make distcheck` or the Docker build path should also be exercised. + +## CI And Container Workflows + +- CI is defined in [`.travis.yml`](.travis.yml) and uses autotools, `make check`, `make distcheck`, coverage builds, and Docker image builds. +- Additional CI in [`.github/workflows`](.github/workflows) for OSX Intel and ARM64. +- Docker builds are driven by [`Dockerfile`](Dockerfile) and [`travis/build-rhel-docker.sh`](travis/build-rhel-docker.sh). +- CI commonly configures with `--disable-dependency-tracking`, `--with-dependencies=$prefix/deps`, and `--enable-developer`. +- Docker and CI assume external dependency artifacts such as hyrax-dependencies and libdap builds; do not hardcode local-only assumptions into those paths. + +## Generated Files And Build Artifacts + +- Prefer editing source inputs such as [`configure.ac`](configure.ac) and [`Makefile.am`](Makefile.am), not generated outputs like `configure`, `Makefile.in`, or `config.h.in`, unless the task explicitly requires regenerating them. +- This repository may contain checked-in generated files and local build artifacts. Do not delete or revert unrelated generated files just to make the tree look clean. +- If you regenerate autotools outputs, keep the resulting changes tightly scoped and mention that regeneration was performed. + +## Documentation + +- Top-level API docs are built with `make docs`. +- Doc inputs are generated from top-level templates such as `doxy.conf.in` and `main_page.doxygen.in`; keep template/generated relationships consistent with the chosen build workflow. + +## Configuration Awareness + +- BES is not just a library build; installation layout and runtime configuration matter. +- `INSTALL` and `README.md` both assume post-install configuration under `etc/bes`, including `bes.conf` and module configuration files. +- When changing defaults, installed paths, service scripts, or startup behavior, call out runtime configuration impact explicitly. + +## Legacy C++ Constraints + +- Match local style in touched files; avoid unrelated formatting sweeps. +- Avoid API or ABI-impacting changes unless explicitly requested. +- Be conservative with ownership, lifetime, and assertion behavior in older pointer-heavy code. +- Developer mode and release mode differ here (`--enable-developer` vs. `NDEBUG` builds), so consider both when changing assertions, debug-only behavior, or diagnostics. + +## Change Discipline + +- Do not revert unrelated local changes in a dirty worktree. +- Keep edits narrowly scoped to the request. +- If you encounter unexpected repository changes that conflict with the task, stop and ask how to proceed. +- Do not run destructive git commands unless explicitly requested. + +## Review Priorities + +When asked to review, prioritize: + +1. Behavioral regressions in server responses, protocol handling, and installed/runtime behavior +2. Memory/resource safety and ownership lifetime issues +3. Build-system or packaging regressions in autotools, distcheck, CI, or Docker flows +4. Configuration/install-layout regressions that would affect deployed BES instances +5. Missing or weak regression coverage + +## Communication + +- State assumptions and environment details explicitly, especially configure flags and dependency locations. +- If full validation was not run, say exactly what was run and what was not. +- If a change depends on external prerequisites such as `libdap`, hyrax-dependencies, AWS-fetched artifacts, or system packages, note that clearly. diff --git a/Dockerfile b/Dockerfile index 6d21af7627..aa1ec35b84 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,17 @@ # Dockerfile for bes_core images + +# This Dockerfile is intended to build a base image that will be used to build +# subsequent images for our production BES/Hyrax images. The build process is +# split into two stages, with the first stage building the BES and the second +# stage copying over the built BES and its dependencies to a slimmer base image. + ARG BUILDER_BASE_IMAGE ARG FINAL_BASE_IMAGE FROM ${BUILDER_BASE_IMAGE:-"rockylinux:8"} AS builder +# Sanity check that the required build argument is provided and non-empty, evn +# though a default value is provided above. We want to enforce that the value is +# always specified. ARG BUILDER_BASE_IMAGE RUN if [ -z "$BUILDER_BASE_IMAGE" ]; then \ echo "Error: Non-empty BUILDER_BASE_IMAGE must be specified. Exiting."; \ @@ -59,6 +68,10 @@ COPY . ./bes RUN sudo chown -R $BES_USER:$BES_USER bes WORKDIR bes +# *** Note that since this is going to be used in production, the +# --enable-developer configure option should not be used. This is the only +# change that I think we need to make to the build process for production +# images. jhrg 3/29/26 RUN autoreconf -fiv RUN echo "Sanity check: CPPFLAGS=$CPPFLAGS LDFLAGS=$LDFLAGS prefix=$PREFIX" \ && ./configure --disable-dependency-tracking \ @@ -134,7 +147,7 @@ COPY --from=builder /home/$BES_USER/bes/bes_VERSION bes_VERSION COPY --from=builder /home/$BES_USER/bes/libdap_VERSION libdap_VERSION COPY --from=builder $DEPS_PREFIX $DEPS_PREFIX -# Copy over everything installed in the builder image +# Copy over everything installed in the builder image. # This is a little ham-fisted, but seems to be at least sufficient # (if not particularly elegant!). COPY --from=builder /etc/bes /etc/bes @@ -172,7 +185,8 @@ USER root # Adapted from bes/spec.all_static.in in RPM creation. # The four *.pem substitutions may be unnecessary, as those *.pem files may be -# vestigial substitutions for a build process past. +# vestigial substitutions for a build process past. See HYRAX-2075. + RUN sed -i.dist \ -e 's:=.*/bes.log:=/var/log/bes/bes.log:' \ -e 's:=.*/lib/bes:=/usr/lib/bes:' \ diff --git a/access-log-processing.txt b/access-log-processing.txt new file mode 100644 index 0000000000..a92462da8a --- /dev/null +++ b/access-log-processing.txt @@ -0,0 +1,3 @@ + How I made accesses.06.26.24.txt + +cut -f 1 -d ' ' localhost_access_log.2024-06-26.txt | sort -n | uniq -c | sort -r -n > accesses.06.26.24.txt diff --git a/agents-needs-work.md b/agents-needs-work.md deleted file mode 100644 index 0ebc27f5eb..0000000000 --- a/agents-needs-work.md +++ /dev/null @@ -1,94 +0,0 @@ -# AGENTS.md - -## Scope - -These instructions apply to the entire `bes` repository. - -## Project Context - -- `bes` is a legacy C++ implementation of the Hyrax data server long-lived downstream consumers. -- Prioritize compatibility, behavioral stability, and small, reviewable diffs. -- Prefer minimal, targeted changes over broad refactors. - -## Primary Build Systems - -- Prefer autotools for day-to-day work. - - -## Autotools Workflow (preferred) - -For a fresh git checkout: - -```sh -autoreconf --force --install --verbose -./configure --prefix=$prefix --with-dependencies=$prefix/deps --enable-developer -make -j -make -j check -``` - -For release-tarball style builds: - -```sh -./configure -make -j -make -j check -``` - -Notes: - -- Check that the environment variable 'prefix' is defined before running any command that uses it. -- Use `--prefix=` when installation path matters. -- Use `TESTSUITEFLAGS=-j` with `make check` when parallelizing tests. -- If `make check` fails due to missing `config.guess`, link `conf/config.guess` into `tests/` per `tests/README`. - -## Testing Expectations - -- For code changes, run focused tests in affected areas first, then broader suites when risk is higher. -- Autotools default: `make -j check` -- If tests are flaky or expected-fail in legacy areas, call that out explicitly in your summary. - -## Documentation And Doxygen - -- Doxygen docs are built with: - -```sh -make docs -``` - -- Inputs are `doxy.conf` and `main_page.doxygen` (generated from `.in` templates by configure). -- When updating doc config/templates, keep generated and template files consistent with the chosen build workflow. - -## Legacy C++ Constraints - -- Match local style in touched files; do not perform unrelated formatting sweeps. -- Avoid API/ABI-impacting changes unless explicitly requested. -- Be conservative with ownership/lifetime changes in pointer-heavy code. -- Parser/scanner sources are generated (`*.tab.cc`, `*.tab.hh`, `lex.*.cc`); edit `*.yy`/`*.lex` sources, not generated outputs, unless the task explicitly requires generated-file updates. - -## Tooling And Quality - -- `clang-format` and pre-commit are configured (`README.pre-commit.md`, `.pre-commit-config.yaml`). -- Prefer running formatting/hooks only on changed files relevant to the task. -- Address sanitizer is supported (`--enable-asan` in autotools, `asan` preset in CMake) for memory-safety debugging. - -## Change Discipline - -- Do not revert unrelated local changes in a dirty worktree. -- Keep edits tightly scoped to the request. -- If you encounter unexpected repository changes during work, stop and ask how to proceed. -- Do not run destructive git commands unless explicitly requested. - -## Review Priorities - -When asked to review: - -1. Behavioral regressions in protocol/data-model behavior -2. Memory/resource safety and ownership lifetime issues -3. Parser/serialization correctness and edge cases -4. Build-system regressions (autotools and CMake) -5. Missing or weak regression coverage - -## Communication - -- State assumptions and environment details explicitly (build system, preset/configure flags, test scope). -- If full validation is not run, say exactly what was run and what was not. diff --git a/aws/unit-tests/SignedUrlCacheTest b/aws/unit-tests/SignedUrlCacheTest new file mode 100755 index 0000000000..2f2b242b0a --- /dev/null +++ b/aws/unit-tests/SignedUrlCacheTest @@ -0,0 +1,210 @@ +#! /bin/sh + +# SignedUrlCacheTest - temporary wrapper script for .libs/SignedUrlCacheTest +# Generated by libtool (GNU libtool) 2.5.4 +# +# The SignedUrlCacheTest program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s|\([`"$\\]\)|\\\1|g' + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command="" + +# This environment variable determines our operation mode. +if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then + # install mode needs the following variables: + generated_by_libtool_version='2.5.4' + notinst_deplibs=' ../../dispatch/libbes_dispatch.la /Users/jimg/src/opendap/hyrax/bes/dispatch/libbes_dispatch.la' +else + # When we are sourced in execute mode, $file and $ECHO are already set. + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + file="$0" + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + ECHO="printf %s\\n" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ that is used only on +# windows platforms, and (c) all begin with the string --lt- +# (application programs are unlikely to have options that match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's ../../libtool value, followed by no. +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=$0 + shift + for lt_opt + do + case "$lt_opt" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%/[^/]*$%%'` + test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=. + lt_dump_F=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%^.*/%%'` + cat "$lt_dump_D/$lt_dump_F" + exit 0 + ;; + --lt-*) + $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n "$lt_option_debug"; then + echo "SignedUrlCacheTest:SignedUrlCacheTest:$LINENO: libtool wrapper (GNU libtool) 2.5.4" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + $ECHO "SignedUrlCacheTest:SignedUrlCacheTest:$LINENO: newargv[$lt_dump_args_N]: $lt_arg" + lt_dump_args_N=`expr $lt_dump_args_N + 1` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ + + if test -n "$lt_option_debug"; then + $ECHO "SignedUrlCacheTest:SignedUrlCacheTest:$LINENO: newargv[0]: $progdir/$program" 1>&2 + func_lt_dump_args ${1+"$@"} 1>&2 + fi + exec "$progdir/$program" ${1+"$@"} + + $ECHO "$0: cannot exec $program $*" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from $@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case " $* " in + *\ --lt-*) + for lt_wr_arg + do + case $lt_wr_arg in + --lt-*) ;; + *) set x "$@" "$lt_wr_arg"; shift;; + esac + shift + done ;; + esac + func_exec_program_core ${1+"$@"} +} + + # Parse options + func_parse_lt_options "$0" ${1+"$@"} + + # Find the directory that this script lives in. + thisdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'` + test "x$thisdir" = "x$file" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=`ls -ld "$file" | /usr/bin/sed -n 's/.*-> //p'` + while test -n "$file"; do + destdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'` + + # If there was a directory component, then change thisdir. + if test "x$destdir" != "x$file"; then + case "$destdir" in + [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;; + *) thisdir="$thisdir/$destdir" ;; + esac + fi + + file=`$ECHO "$file" | /usr/bin/sed 's%^.*/%%'` + file=`ls -ld "$thisdir/$file" | /usr/bin/sed -n 's/.*-> //p'` + done + + # Usually 'no', except on cygwin/mingw/windows when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no + if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then + # special case for '.' + if test "$thisdir" = "."; then + thisdir=`pwd` + fi + # remove .libs from thisdir + case "$thisdir" in + *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /usr/bin/sed 's%[\\/][^\\/]*$%%'` ;; + .libs ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=`cd "$thisdir" && pwd` + test -n "$absdir" && thisdir="$absdir" + + program='SignedUrlCacheTest' + progdir="$thisdir/.libs" + + + if test -f "$progdir/$program"; then + # Add our own library path to DYLD_LIBRARY_PATH + DYLD_LIBRARY_PATH="/Users/jimg/src/opendap/hyrax/bes/dispatch/.libs:$DYLD_LIBRARY_PATH" + + # Some systems cannot cope with colon-terminated DYLD_LIBRARY_PATH + # The second colon is a workaround for a bug in BeOS R4 sed + DYLD_LIBRARY_PATH=`$ECHO "$DYLD_LIBRARY_PATH" | /usr/bin/sed 's/::*$//'` + + export DYLD_LIBRARY_PATH + + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + # Run the actual program with our arguments. + func_exec_program ${1+"$@"} + fi + else + # The program doesn't exist. + $ECHO "$0: error: '$progdir/$program' does not exist" 1>&2 + $ECHO "This script is just a wrapper for $program." 1>&2 + $ECHO "See the libtool documentation for more information." 1>&2 + exit 1 + fi +fi diff --git a/demo/bescmd.xml b/demo/bescmd.xml new file mode 100644 index 0000000000..5feba16678 --- /dev/null +++ b/demo/bescmd.xml @@ -0,0 +1,18 @@ + + + 300 + {"$schema":"https:\/\/harmony.earthdata.nasa.gov\/schemas\/history\/0.1.0\/history-0.1.0.json","date_time":"2024-06-16T22:50:52.661+0000","program":"hyrax","version":"metrics-0.2","parameters":[{"request_url":"http:\/\/localhost:8080\/opendap\/demo\/3B42.20190110.09.7.HDF.dmrpp.dap.nc4?dap4.ce=\/nlat%5B0:1:399%5D;\/nlon%5B0:1:1439%5D;\/Grid\/precipitation%5B0:1:1439%5D%5B0:1:399%5D"},{"decoded_constraint":"dap4.ce=\/nlat[0:1:399];\/nlon[0:1:1439];\/Grid\/precipitation[0:1:1439][0:1:399]"}]} + 2024-06-16 22:50:52 GMT hyrax-metrics-0.2 http://localhost:8080/opendap/demo/3B42.20190110.09.7.HDF.dmrpp.dap.nc4?dap4.ce=/nlat%5B0:1:399%5D;/nlon%5B0:1:1439%5D;/Grid/precipitation%5B0:1:1439%5D%5B0:1:399%5D + no + xml + 0 + 0 + not_logged_in + /demo/3B42.20190110.09.7.HDF.dmrpp + + + /nlat[0:1:399];/nlon[0:1:1439];/Grid/precipitation[0:1:1439][0:1:399] + + + + diff --git a/demo/bescmd_2.xml b/demo/bescmd_2.xml new file mode 100644 index 0000000000..fd74e63d02 --- /dev/null +++ b/demo/bescmd_2.xml @@ -0,0 +1,18 @@ + + + 300 + {"$schema":"https:\/\/harmony.earthdata.nasa.gov\/schemas\/history\/0.1.0\/history-0.1.0.json","date_time":"2024-06-16T22:50:52.661+0000","program":"hyrax","version":"metrics-0.2","parameters":[{"request_url":"http:\/\/localhost:8080\/opendap\/demo\/3B42.20190110.09.7.HDF.dmrpp.dap.nc4?dap4.ce=\/nlat%5B0:1:399%5D;\/nlon%5B0:1:1439%5D;\/Grid\/precipitation%5B0:1:1439%5D%5B0:1:399%5D"},{"decoded_constraint":"dap4.ce=\/nlat[0:1:399];\/nlon[0:1:1439];\/Grid\/precipitation[0:1:1439][0:1:399]"}]} + 2024-06-16 22:50:52 GMT hyrax-metrics-0.2 http://localhost:8080/opendap/demo/3B42.20190110.09.7.HDF.dmrpp.dap.nc4?dap4.ce=/nlat%5B0:1:399%5D;/nlon%5B0:1:1439%5D;/Grid/precipitation%5B0:1:1439%5D%5B0:1:399%5D + no + xml + 0 + 0 + not_logged_in + /demo/3B42.20190110.09.7.HDF.dmrpp + + + /nlat[0:1:399];/nlon[0:1:1439] + + + + diff --git a/demo/bescmd_3.xml b/demo/bescmd_3.xml new file mode 100644 index 0000000000..747612d597 --- /dev/null +++ b/demo/bescmd_3.xml @@ -0,0 +1,18 @@ + + + 300 + {"$schema":"https:\/\/harmony.earthdata.nasa.gov\/schemas\/history\/0.1.0\/history-0.1.0.json","date_time":"2024-06-16T22:50:52.661+0000","program":"hyrax","version":"metrics-0.2","parameters":[{"request_url":"http:\/\/localhost:8080\/opendap\/demo\/3B42.20190110.09.7.HDF.dmrpp.dap.nc4?dap4.ce=\/nlat%5B0:1:399%5D;\/nlon%5B0:1:1439%5D;\/Grid\/precipitation%5B0:1:1439%5D%5B0:1:399%5D"},{"decoded_constraint":"dap4.ce=\/nlat[0:1:399];\/nlon[0:1:1439];\/Grid\/precipitation[0:1:1439][0:1:399]"}]} + 2024-06-16 22:50:52 GMT hyrax-metrics-0.2 http://localhost:8080/opendap/demo/3B42.20190110.09.7.HDF.dmrpp.dap.nc4?dap4.ce=/nlat%5B0:1:399%5D;/nlon%5B0:1:1439%5D;/Grid/precipitation%5B0:1:1439%5D%5B0:1:399%5D + no + xml + 0 + 0 + not_logged_in + /demo/3B42.20190110.09.7.HDF.dmrpp + + + /grid/precipitation + + + + diff --git a/http/retired/awsv4.cc b/http/retired/awsv4.cc new file mode 100644 index 0000000000..c3d2cee975 --- /dev/null +++ b/http/retired/awsv4.cc @@ -0,0 +1,410 @@ + + +// -*- mode: c++; c-basic-offset:4 -*- + +// This file is part of the Hyrax data server. + +// This code is derived from https://github.com/bradclawsie/awsv4-cpp +// Copyright (c) 2013, brad clawsie +// All rights reserved. +// see the file AWSV4_LICENSE + +// Copyright (c) 2019 OPeNDAP, Inc. +// Modifications Author: James Gallagher +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. + +#include "config.h" + +#include "awsv4.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "url_impl.h" +#include "BESInternalError.h" +#include "BESDebug.h" +#include "HttpNames.h" + +#define prolog std::string("AWSV4::").append(__func__).append("() - ") + +namespace AWSV4 { + +// used in sha256_base16() and hmac_to_string(). jhrg 1/5/20 +const int SHA256_DIGEST_STRING_LENGTH = (SHA256_DIGEST_LENGTH << 1); + +/** + * @brief join strings using a delimiter + * @param ss Strings to join + * @param delim Dilimiter to separate the strings + * @return The string result + */ +std::string join(const std::vector &ss, const std::string &delim) { + if (ss.empty()) + return ""; + + std::stringstream sstream; + const size_t l = ss.size() - 1; + for (size_t i = 0; i < l; i++) { + sstream << ss[i] << delim; + } + sstream << ss.back(); + return sstream.str(); +} + +std::string sha256_base16(const std::string &str) { + + unsigned char hashOut[SHA256_DIGEST_LENGTH]; + SHA256_CTX sha256; + SHA256_Init(&sha256); + SHA256_Update(&sha256, (const unsigned char *) str.c_str(), str.size()); + SHA256_Final(hashOut, &sha256); + + char outputBuffer[SHA256_DIGEST_STRING_LENGTH + 1]; + for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) { + snprintf(outputBuffer + (i * 2), 3, "%02x", hashOut[i]); + } + outputBuffer[SHA256_DIGEST_STRING_LENGTH] = 0; + return std::string{outputBuffer}; +} + +// From https://stackoverflow.com/questions/1798112/removing-leading-and-trailing-spaces-from-a-string +static std::string trim(const std::string &str, const std::string &whitespace = " \t") { + const auto strBegin = str.find_first_not_of(whitespace); + if (strBegin == std::string::npos) + return ""; // no content + + const auto strEnd = str.find_last_not_of(whitespace); + const auto strRange = strEnd - strBegin + 1; + + return str.substr(strBegin, strRange); +} + +// ----------------------------------------------------------------------------------- +// TASK 1 - create a canonical request +// http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html + +// create a map of the "canonicalized" headers +// will return empty map on malformed input. +// +// headers A vector where each element is a header name and value, separated by a colon. No spaces. +std::map canonicalize_headers(const std::vector &headers) { + std::map header_key2val; + for (const auto &header: headers) { + auto i = header.find(':'); + if (i == std::string::npos) { + header_key2val.clear(); + return header_key2val; + } + + std::string key = trim(header.substr(0, i)); + const std::string val = trim(header.substr(i + 1)); + if (key.empty() || val.empty()) { + header_key2val.clear(); + return header_key2val; + } + + std::transform(key.begin(), key.end(), key.begin(), ::tolower); + header_key2val[key] = val; + } + return header_key2val; +} + +// get a string representation of header:value lines +std::string map_headers_string(const std::map &header_key2val) { + const std::string pair_delim{":"}; + std::string h; + for (const auto &kv: header_key2val) { + h.append(kv.first).append(pair_delim).append(kv.second).append(ENDL); + } + return h; +} + +// get a string representation of the header names +std::string map_signed_headers(const std::map &header_key2val) { + const std::string signed_headers_delim{";"}; + std::vector ks; + for ( const auto &kv: header_key2val) { + ks.push_back(kv.first); + } + return join(ks, signed_headers_delim); +} + +std::string canonicalize_request(const std::string &http_request_method, + const std::string &canonical_uri, + const std::string &canonical_query_string, + const std::string &canonical_headers, + const std::string &signed_headers, + const std::string &shar256_of_payload) { + return std::string(http_request_method).append(ENDL).append(canonical_uri).append(ENDL) + .append(canonical_query_string).append(ENDL).append(canonical_headers).append(ENDL) + .append(signed_headers).append(ENDL).append(shar256_of_payload); +} + +// ----------------------------------------------------------------------------------- +// TASK 2 - create a string-to-sign +// http://docs.aws.amazon.com/general/latest/gr/sigv4-create-string-to-sign.html + +std::string string_to_sign(const std::string &algorithm, + const std::time_t &request_date, + const std::string &credential_scope, + const std::string &hashed_canonical_request) { + return algorithm + ENDL + + ISO8601_date(request_date) + ENDL + + credential_scope + ENDL + + hashed_canonical_request; +} + +std::string credential_scope(const std::time_t &request_date, + const std::string ®ion, + const std::string &service) { + const std::string s{"/"}; + return utc_yyyymmdd(request_date).append(s).append(region).append(s).append(service).append(s).append(AWS4_REQUEST); +} + +// time_t -> 20131222T043039Z +std::string ISO8601_date(const std::time_t &t) { + char buf[sizeof "20111008T070709Z"]; + struct tm tm_buf{}; + std::strftime(buf, sizeof buf, "%Y%m%dT%H%M%SZ", gmtime_r(&t, &tm_buf)); + return buf; +} + +// time_t -> 20131222 +std::string utc_yyyymmdd(const std::time_t &t) { + char buf[sizeof "20111008"]; + struct tm tm_buf{}; + std::strftime(buf, sizeof buf, "%Y%m%d", gmtime_r(&t, &tm_buf)); + return buf; +} + +// HMAC --> string. jhrg 11/25/19 +std::string hmac_to_string(const unsigned char *hmac) { + // Added to print the kSigning value to check against AWS example. jhrg 11/24/19 + char buf[SHA256_DIGEST_STRING_LENGTH + 1]; + for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) { + // size is 3 for each call (2 chars plus null). jhrg 1/3/20 + snprintf(buf + (i * 2), 3, "%02x", hmac[i]); + } + buf[SHA256_DIGEST_STRING_LENGTH] = 0; + return buf; +} + +// ----------------------------------------------------------------------------------- +// TASK 3 +// http://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html + +/* + * unsigned char *HMAC(const EVP_MD *evp_md, + * const void *key, int key_len, + * const unsigned char *d, int n, + * unsigned char *md, unsigned int *md_len); + * where md must be EVP_MAX_MD_SIZE in size + */ + +std::string calculate_signature(const std::time_t &request_date, + const std::string &secret, + const std::string ®ion, + const std::string &service, + const std::string &string_to_sign) { + + // These are used/re-used for the various signatures. jhrg 1/3/20 + unsigned char md[EVP_MAX_MD_SIZE + 1]; + unsigned int md_len; + + const std::string k1 = AWS4 + secret; + const std::string yyyymmdd = utc_yyyymmdd(request_date); + // NB: The third argument for HMAC is an unsigned int. jhrg 10/31/22 + const unsigned char *kDate = HMAC(EVP_sha256(), (const void *)k1.c_str(), (unsigned int)k1.size(), + (const unsigned char *) yyyymmdd.c_str(), yyyymmdd.size(), md, &md_len); + if (!kDate) + throw BESInternalError("Could not compute AWS V4 request signature.", __FILE__, __LINE__); + + md[md_len] = '\0'; + BESDEBUG(HTTP_MODULE, + prolog << "kDate: " << hmac_to_string(kDate) << " md_len: " << md_len << " md: " << hmac_to_string(md) + << std::endl); + + const unsigned char *kRegion = HMAC(EVP_sha256(), md, md_len, + (const unsigned char *) region.c_str(), region.size(), md, &md_len); + if (!kRegion) + throw BESInternalError("Could not compute AWS V4 request signature.", __FILE__, __LINE__); + + md[md_len] = '\0'; + BESDEBUG(HTTP_MODULE, + prolog << "kRegion: " << hmac_to_string(kRegion) << " md_len: " << md_len << " md: " << hmac_to_string(md) + << std::endl); + + const unsigned char *kService = HMAC(EVP_sha256(), md, md_len, + (const unsigned char *) service.c_str(), service.size(), md, &md_len); + if (!kService) + throw BESInternalError("Could not compute AWS V4 request signature.", __FILE__, __LINE__); + + md[md_len] = '\0'; + BESDEBUG(HTTP_MODULE, prolog << "kService: " << hmac_to_string(kService) << " md_len: " << md_len << " md: " + << hmac_to_string(md) << std::endl); + + const unsigned char *kSigning = HMAC(EVP_sha256(), md, md_len, + (const unsigned char *) AWS4_REQUEST.c_str(), AWS4_REQUEST.size(), md, &md_len); + if (!kSigning) + throw BESInternalError("Could not compute AWS V4 request signature.", __FILE__, __LINE__); + + md[md_len] = '\0'; + BESDEBUG(HTTP_MODULE, + prolog << "kSigning: " << hmac_to_string(kRegion) << " md_len: " << md_len << " md: " << hmac_to_string(md) + << std::endl); + + const unsigned char *kSig = HMAC(EVP_sha256(), md, md_len, + (const unsigned char *) string_to_sign.c_str(), string_to_sign.size(), md, &md_len); + if (!kSig) + throw BESInternalError("Could not compute AWS V4 request signature.", __FILE__, __LINE__); + + md[md_len] = '\0'; + auto sig = hmac_to_string(md); + BESDEBUG(HTTP_MODULE, prolog << "kSig: " << sig << " md_len: " << md_len << " md: " << hmac_to_string(md) << std::endl); + return sig; +} + +/** + * @brief Return the AWS V4 signature for a given GET request. + * + * This version takes strings for the path, query string and host. + * + * @param canonical_uri The path part of the URI + * @param canonical_query The URI query string + * @param host The host part of the URI + * @param request_date The current date & time + * @param secret_key The Secret key for this resource (the thing referenced by the URI). + * @param region The AWS region where the request is being made (us-west-2 by default) + * @param service The AWS service that is the target of the request (S3 by default) + * @return The AWS V4 Signature string. + */ +std::string compute_awsv4_signature(const std::string &canonical_uri, const std::string &canonical_query, + const std::string &host, const std::time_t &request_date, + const std::string &public_key, const std::string &secret_key, + const std::string ®ion, const std::string &service) { + // We can eliminate one call to sha256 if the payload is null, which + // is the case for a GET request. jhrg 11/25/19 + const std::string sha256_empty_payload = {"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}; + // All AWS V4 signature require x-amz-content-sha256. jhrg 11/24/19 + + // We used to do it like the code in the other half of this #if + // But it seems we don't need the x-amz-content-sha256 header for empty payload + // so here it is without. + // + // NOTE: Changing this will break the awsv4_test using tests. jhrg 1/3/20 + std::vector headers{"host: ", "x-amz-date: "}; + headers[0].append(host); + headers[1].append(ISO8601_date(request_date)); + + const auto canonical_headers_map = canonicalize_headers(headers); + if (canonical_headers_map.empty()) { + throw std::runtime_error("Empty header list while building AWS V4 request signature"); + } + const auto headers_string = map_headers_string(canonical_headers_map); + const auto signed_headers = map_signed_headers(canonical_headers_map); + const auto canonical_request = canonicalize_request(AWSV4::GET, + canonical_uri, + canonical_query, + headers_string, + signed_headers, + sha256_empty_payload); + + BESDEBUG(HTTP_MODULE, prolog << "Canonical Request: " << canonical_request << std::endl); + + auto hashed_canonical_request = sha256_base16(canonical_request); + auto credential_scope = AWSV4::credential_scope(request_date, region, service); + auto string_to_sign = AWSV4::string_to_sign(STRING_TO_SIGN_ALGO, + request_date, + credential_scope, + hashed_canonical_request); + + BESDEBUG(HTTP_MODULE, prolog << "String to Sign: " << string_to_sign << std::endl); + + auto signature = calculate_signature(request_date, + secret_key, + region, + service, + string_to_sign); + + BESDEBUG(HTTP_MODULE, prolog << "signature: " << signature << std::endl); + + std::string authorization_header = STRING_TO_SIGN_ALGO + " Credential=" + public_key + "/" + + credential_scope + ", SignedHeaders=" + signed_headers + ", Signature=" + + signature; + + BESDEBUG(HTTP_MODULE, prolog << "authorization_header: " << authorization_header << std::endl); + + return authorization_header; +} + +/** + * @brief Return the AWS V4 signature for a given GET request + * + * This version takes an http::url object for the path, query string and host. + * @todo Remove when we retire the shared_ptr interface. jhrg 2/20/25 + * @param uri_str The URI to fetch + * @param request_date The current date & time + * @param secret_key The Secret key for this resource (the thing referenced by the URI). + * @param region The AWS region where the request is being made (us-west-2 by default) + * @param service The AWS service that is the target of the request (S3 by default) + * @return The AWS V4 Signature string. + */ +std::string compute_awsv4_signature( + const std::shared_ptr &uri, + const std::time_t &request_date, + const std::string &public_key, + const std::string &secret_key, + const std::string ®ion, + const std::string &service) { + return compute_awsv4_signature(uri->path(), uri->query(), uri->host(), request_date, public_key, secret_key, + region, service); +} + +/** + * @brief Return the AWS V4 signature for a given GET request + * + * This version takes an http::url object for the path, query string and host. + * + * @param uri_str The URI to fetch. This is an http::url object. + * @param request_date The current date & time + * @param secret_key The Secret key for this resource (the thing referenced by the URI). + * @param region The AWS region where the request is being made (us-west-2 by default) + * @param service The AWS service that is the target of the request (S3 by default) + * @return The AWS V4 Signature string. + */ +std::string compute_awsv4_signature( + const http::url &uri, + const std::time_t &request_date, + const std::string &public_key, + const std::string &secret_key, + const std::string ®ion, + const std::string &service) { + return compute_awsv4_signature(uri.path(), uri.query(), uri.host(), request_date, public_key, secret_key, + region, service); +} + +} diff --git a/http/retired/awsv4.h b/http/retired/awsv4.h new file mode 100644 index 0000000000..3a55b430e0 --- /dev/null +++ b/http/retired/awsv4.h @@ -0,0 +1,106 @@ + + +// -*- mode: c++; c-basic-offset:4 -*- + +// This file is part of the Hyrax data server. + +// This code is derived from https://github.com/bradclawsie/awsv4-cpp +// Copyright (c) 2013, brad clawsie +// All rights reserved. +// see the file AWSV4_LICENSE + +// Copyright (c) 2019 OPeNDAP, Inc. +// Modifications Author: James Gallagher +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. + +#ifndef AWSV4_HPP +#define AWSV4_HPP + +#include +#include +#include +#include +#include +#include + +#include + +#include "url_impl.h" + +namespace AWSV4 { + +const std::string ENDL{"\n"}; +const std::string POST{"POST"}; +const std::string GET{"GET"}; +const std::string STRING_TO_SIGN_ALGO{"AWS4-HMAC-SHA256"}; +const std::string AWS4{"AWS4"}; +const std::string AWS4_REQUEST{"aws4_request"}; + +std::string join(const std::vector &ss, const std::string &delim); + +std::string sha256_base16(const std::string &str); + +std::map canonicalize_headers(const std::vector &headers); + +std::string map_headers_string(const std::map &header_key2val); + +std::string map_signed_headers(const std::map &header_key2val); + +std::string canonicalize_request(const std::string &http_request_method, + const std::string &canonical_uri, + const std::string &canonical_query_string, + const std::string &canonical_headers, + const std::string &signed_headers, + const std::string &payload); + +std::string string_to_sign(const std::string &algorithm, + const std::time_t &request_date, + const std::string &credential_scope, + const std::string &hashed_canonical_request); + +std::string ISO8601_date(const std::time_t &t); + +std::string utc_yyyymmdd(const std::time_t &t); + +std::string credential_scope(const std::time_t &t, + const std::string ®ion, + const std::string &service); + +std::string calculate_signature(const std::time_t &request_date, + const std::string &secret, + const std::string ®ion, + const std::string &service, + const std::string &string_to_sign); + +// The whole enchilada. Added jhrg 11/25/19 +std::string compute_awsv4_signature(const std::shared_ptr &uri_str, const std::time_t &request_date, + const std::string &public_key, const std::string &secret_key, + const std::string ®ion, const std::string &service = "s3"); + +// Added these two as part of removing the use of std::shared_ptr. jhrg 2/20/25 +std::string compute_awsv4_signature(const http::url &uri, const std::time_t &request_date, + const std::string &public_key, const std::string &secret_key, + const std::string ®ion, const std::string &service = "s3"); + +std::string compute_awsv4_signature(const std::string &canonical_uri, const std::string &canonical_query, + const std::string &host, const std::time_t &request_date, + const std::string &public_key, const std::string &secret_key, + const std::string ®ion, const std::string &service); +} + +#endif diff --git a/http/retired/awsv4_master.cc b/http/retired/awsv4_master.cc new file mode 100644 index 0000000000..8a24e3f886 --- /dev/null +++ b/http/retired/awsv4_master.cc @@ -0,0 +1,387 @@ + + +// -*- mode: c++; c-basic-offset:4 -*- + +// This file is part of the Hyrax data server. + +// This code is derived from https://github.com/bradclawsie/awsv4-cpp +// Copyright (c) 2013, brad clawsie +// All rights reserved. +// see the file AWSV4_LICENSE + +// Copyright (c) 2019 OPeNDAP, Inc. +// Modifications Author: James Gallagher +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. + +#include "config.h" + +#include "awsv4.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "url_impl.h" +#include "BESInternalError.h" +#include "BESDebug.h" +#include "HttpNames.h" + +#define prolog std::string("AWSV4::").append(__func__).append("() - ") + +namespace AWSV4 { + +// used in sha256_base16() and hmac_to_string(). jhrg 1/5/20 +const int SHA256_DIGEST_STRING_LENGTH = (SHA256_DIGEST_LENGTH << 1); + +/** + * @brief join strings using a delimiter + * @param ss Strings to join + * @param delim Dilimiter to separate the strings + * @return The string result + */ +std::string join(const std::vector &ss, const std::string &delim) { + if (ss.empty()) + return ""; + + std::stringstream sstream; + const size_t l = ss.size() - 1; + for (size_t i = 0; i < l; i++) { + sstream << ss[i] << delim; + } + sstream << ss.back(); + return sstream.str(); +} + +std::string sha256_base16(const std::string &str) { + + unsigned char hashOut[SHA256_DIGEST_LENGTH]; + SHA256_CTX sha256; + SHA256_Init(&sha256); + SHA256_Update(&sha256, (const unsigned char *) str.c_str(), str.size()); + SHA256_Final(hashOut, &sha256); + + char outputBuffer[SHA256_DIGEST_STRING_LENGTH + 1]; + for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) { + snprintf(outputBuffer + (i * 2), 3, "%02x", hashOut[i]); + } + outputBuffer[SHA256_DIGEST_STRING_LENGTH] = 0; + return std::string{outputBuffer}; +} + +// From https://stackoverflow.com/questions/1798112/removing-leading-and-trailing-spaces-from-a-string +static std::string trim(const std::string &str, const std::string &whitespace = " \t") { + const auto strBegin = str.find_first_not_of(whitespace); + if (strBegin == std::string::npos) + return ""; // no content + + const auto strEnd = str.find_last_not_of(whitespace); + const auto strRange = strEnd - strBegin + 1; + + return str.substr(strBegin, strRange); +} + +// ----------------------------------------------------------------------------------- +// TASK 1 - create a canonical request +// http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html + +// create a map of the "canonicalized" headers +// will return empty map on malformed input. +// +// headers A vector where each element is a header name and value, separated by a colon. No spaces. +std::map canonicalize_headers(const std::vector &headers) { + std::map header_key2val; + for (const auto &header: headers) { + auto i = header.find(':'); + if (i == std::string::npos) { + header_key2val.clear(); + return header_key2val; + } + + std::string key = trim(header.substr(0, i)); + const std::string val = trim(header.substr(i + 1)); + if (key.empty() || val.empty()) { + header_key2val.clear(); + return header_key2val; + } + + std::transform(key.begin(), key.end(), key.begin(), ::tolower); + header_key2val[key] = val; + } + return header_key2val; +} + +// get a string representation of header:value lines +std::string map_headers_string(const std::map &header_key2val) { + const std::string pair_delim{":"}; + std::string h; + for (const auto &kv: header_key2val) { + h.append(kv.first).append(pair_delim).append(kv.second).append(ENDL); + } + return h; +} + +// get a string representation of the header names +std::string map_signed_headers(const std::map &header_key2val) { + const std::string signed_headers_delim{";"}; + std::vector ks; + for ( const auto &kv: header_key2val) { + ks.push_back(kv.first); + } + return join(ks, signed_headers_delim); +} + +std::string canonicalize_request(const std::string &http_request_method, + const std::string &canonical_uri, + const std::string &canonical_query_string, + const std::string &canonical_headers, + const std::string &signed_headers, + const std::string &shar256_of_payload) { + return std::string(http_request_method).append(ENDL).append(canonical_uri).append(ENDL) + .append(canonical_query_string).append(ENDL).append(canonical_headers).append(ENDL) + .append(signed_headers).append(ENDL).append(shar256_of_payload); +} + +// ----------------------------------------------------------------------------------- +// TASK 2 - create a string-to-sign +// http://docs.aws.amazon.com/general/latest/gr/sigv4-create-string-to-sign.html + +std::string string_to_sign(const std::string &algorithm, + const std::time_t &request_date, + const std::string &credential_scope, + const std::string &hashed_canonical_request) { + return algorithm + ENDL + + ISO8601_date(request_date) + ENDL + + credential_scope + ENDL + + hashed_canonical_request; +} + +std::string credential_scope(const std::time_t &request_date, + const std::string ®ion, + const std::string &service) { + const std::string s{"/"}; + return utc_yyyymmdd(request_date).append(s).append(region).append(s).append(service).append(s).append(AWS4_REQUEST); +} + +// time_t -> 20131222T043039Z +std::string ISO8601_date(const std::time_t &t) { + char buf[sizeof "20111008T070709Z"]; + struct tm tm_buf{}; + std::strftime(buf, sizeof buf, "%Y%m%dT%H%M%SZ", gmtime_r(&t, &tm_buf)); + return buf; +} + +// time_t -> 20131222 +std::string utc_yyyymmdd(const std::time_t &t) { + char buf[sizeof "20111008"]; + struct tm tm_buf{}; + std::strftime(buf, sizeof buf, "%Y%m%d", gmtime_r(&t, &tm_buf)); + return buf; +} + +// HMAC --> string. jhrg 11/25/19 +std::string hmac_to_string(const unsigned char *hmac) { + // Added to print the kSigning value to check against AWS example. jhrg 11/24/19 + char buf[SHA256_DIGEST_STRING_LENGTH + 1]; + for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) { + // size is 3 for each call (2 chars plus null). jhrg 1/3/20 + snprintf(buf + (i * 2), 3, "%02x", hmac[i]); + } + buf[SHA256_DIGEST_STRING_LENGTH] = 0; + return buf; +} + +// ----------------------------------------------------------------------------------- +// TASK 3 +// http://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html + +/* + * unsigned char *HMAC(const EVP_MD *evp_md, + * const void *key, int key_len, + * const unsigned char *d, int n, + * unsigned char *md, unsigned int *md_len); + * where md must be EVP_MAX_MD_SIZE in size + */ + +std::string calculate_signature(const std::time_t &request_date, + const std::string &secret, + const std::string ®ion, + const std::string &service, + const std::string &string_to_sign) { + + // These are used/re-used for the various signatures. jhrg 1/3/20 + unsigned char md[EVP_MAX_MD_SIZE + 1]; + unsigned int md_len; + + const std::string k1 = AWS4 + secret; + const std::string yyyymmdd = utc_yyyymmdd(request_date); + // NB: The third argument for HMAC is an unsigned int. jhrg 10/31/22 + const unsigned char *kDate = HMAC(EVP_sha256(), (const void *)k1.c_str(), (unsigned int)k1.size(), + (const unsigned char *) yyyymmdd.c_str(), yyyymmdd.size(), md, &md_len); + if (!kDate) + throw BESInternalError("Could not compute AWS V4 request signature.", __FILE__, __LINE__); + + md[md_len] = '\0'; + BESDEBUG(HTTP_MODULE, + prolog << "kDate: " << hmac_to_string(kDate) << " md_len: " << md_len << " md: " << hmac_to_string(md) + << std::endl); + + const unsigned char *kRegion = HMAC(EVP_sha256(), md, md_len, + (const unsigned char *) region.c_str(), region.size(), md, &md_len); + if (!kRegion) + throw BESInternalError("Could not compute AWS V4 request signature.", __FILE__, __LINE__); + + md[md_len] = '\0'; + BESDEBUG(HTTP_MODULE, + prolog << "kRegion: " << hmac_to_string(kRegion) << " md_len: " << md_len << " md: " << hmac_to_string(md) + << std::endl); + + const unsigned char *kService = HMAC(EVP_sha256(), md, md_len, + (const unsigned char *) service.c_str(), service.size(), md, &md_len); + if (!kService) + throw BESInternalError("Could not compute AWS V4 request signature.", __FILE__, __LINE__); + + md[md_len] = '\0'; + BESDEBUG(HTTP_MODULE, prolog << "kService: " << hmac_to_string(kService) << " md_len: " << md_len << " md: " + << hmac_to_string(md) << std::endl); + + const unsigned char *kSigning = HMAC(EVP_sha256(), md, md_len, + (const unsigned char *) AWS4_REQUEST.c_str(), AWS4_REQUEST.size(), md, &md_len); + if (!kSigning) + throw BESInternalError("Could not compute AWS V4 request signature.", __FILE__, __LINE__); + + md[md_len] = '\0'; + BESDEBUG(HTTP_MODULE, + prolog << "kSigning: " << hmac_to_string(kRegion) << " md_len: " << md_len << " md: " << hmac_to_string(md) + << std::endl); + + const unsigned char *kSig = HMAC(EVP_sha256(), md, md_len, + (const unsigned char *) string_to_sign.c_str(), string_to_sign.size(), md, &md_len); + if (!kSig) + throw BESInternalError("Could not compute AWS V4 request signature.", __FILE__, __LINE__); + + md[md_len] = '\0'; + auto sig = hmac_to_string(md); + BESDEBUG(HTTP_MODULE, prolog << "kSig: " << sig << " md_len: " << md_len << " md: " << hmac_to_string(md) << std::endl); + return sig; +} + +/** + * @brief Return the AWS V4 signature for a given GET request. + * + * This version takes strings for the path, query string and host. + * + * @param canonical_uri The path part of the URI + * @param canonical_query The URI query string + * @param host The host part of the URI + * @param request_date The current date & time + * @param secret_key The Secret key for this resource (the thing referenced by the URI). + * @param region The AWS region where the request is being made (us-west-2 by default) + * @param service The AWS service that is the target of the request (S3 by default) + * @return The AWS V4 Signature string. + */ +std::string compute_awsv4_signature(const std::string &canonical_uri, const std::string &canonical_query, + const std::string &host, const std::time_t &request_date, + const std::string &public_key, const std::string &secret_key, + const std::string ®ion, const std::string &service) { + // We can eliminate one call to sha256 if the payload is null, which + // is the case for a GET request. jhrg 11/25/19 + const std::string sha256_empty_payload = {"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}; + // All AWS V4 signature require x-amz-content-sha256. jhrg 11/24/19 + + // We used to do it like the code in the other half of this #if + // But it seems we don't need the x-amz-content-sha256 header for empty payload + // so here it is without. + // + // NOTE: Changing this will break the awsv4_test using tests. jhrg 1/3/20 + std::vector headers{"host:", "x-amz-date:"}; + headers[0].append(host); + headers[1].append(ISO8601_date(request_date)); + + const auto canonical_headers_map = canonicalize_headers(headers); + if (canonical_headers_map.empty()) { + throw std::runtime_error("Empty header list while building AWS V4 request signature"); + } + const auto headers_string = map_headers_string(canonical_headers_map); + const auto signed_headers = map_signed_headers(canonical_headers_map); + const auto canonical_request = canonicalize_request(AWSV4::GET, + canonical_uri, + canonical_query, + headers_string, + signed_headers, + sha256_empty_payload); + + BESDEBUG(HTTP_MODULE, prolog << "Canonical Request: " << canonical_request << std::endl); + + auto hashed_canonical_request = sha256_base16(canonical_request); + auto credential_scope = AWSV4::credential_scope(request_date, region, service); + auto string_to_sign = AWSV4::string_to_sign(STRING_TO_SIGN_ALGO, + request_date, + credential_scope, + hashed_canonical_request); + + BESDEBUG(HTTP_MODULE, prolog << "String to Sign: " << string_to_sign << std::endl); + + auto signature = calculate_signature(request_date, + secret_key, + region, + service, + string_to_sign); + + BESDEBUG(HTTP_MODULE, prolog << "signature: " << signature << std::endl); + + std::string authorization_header = STRING_TO_SIGN_ALGO + " Credential=" + public_key + "/" + + credential_scope + ", SignedHeaders=" + signed_headers + ", Signature=" + + signature; + + BESDEBUG(HTTP_MODULE, prolog << "authorization_header: " << authorization_header << std::endl); + + return authorization_header; +} + +/** + * @brief Return the AWS V4 signature for a given GET request + * + * This version takes a http::url object for the path, query string and host. + * + * @param uri The URI to fetch. This is a http::url object. + * @param request_date The current date & time + * @param secret_key The Secret key for this resource (the thing referenced by the URI). + * @param region The AWS region where the request is being made (us-west-2 by default) + * @param service The AWS service that is the target of the request (S3 by default) + * @return The AWS V4 Signature string. + */ +std::string compute_awsv4_signature( + const http::url &uri, + const std::time_t &request_date, + const std::string &public_key, + const std::string &secret_key, + const std::string ®ion, + const std::string &service) { + return compute_awsv4_signature(uri.path(), uri.query(), uri.host(), request_date, public_key, secret_key, + region, service); +} + +} diff --git a/http/retired/awsv4_master.h b/http/retired/awsv4_master.h new file mode 100644 index 0000000000..3a55b430e0 --- /dev/null +++ b/http/retired/awsv4_master.h @@ -0,0 +1,106 @@ + + +// -*- mode: c++; c-basic-offset:4 -*- + +// This file is part of the Hyrax data server. + +// This code is derived from https://github.com/bradclawsie/awsv4-cpp +// Copyright (c) 2013, brad clawsie +// All rights reserved. +// see the file AWSV4_LICENSE + +// Copyright (c) 2019 OPeNDAP, Inc. +// Modifications Author: James Gallagher +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. + +#ifndef AWSV4_HPP +#define AWSV4_HPP + +#include +#include +#include +#include +#include +#include + +#include + +#include "url_impl.h" + +namespace AWSV4 { + +const std::string ENDL{"\n"}; +const std::string POST{"POST"}; +const std::string GET{"GET"}; +const std::string STRING_TO_SIGN_ALGO{"AWS4-HMAC-SHA256"}; +const std::string AWS4{"AWS4"}; +const std::string AWS4_REQUEST{"aws4_request"}; + +std::string join(const std::vector &ss, const std::string &delim); + +std::string sha256_base16(const std::string &str); + +std::map canonicalize_headers(const std::vector &headers); + +std::string map_headers_string(const std::map &header_key2val); + +std::string map_signed_headers(const std::map &header_key2val); + +std::string canonicalize_request(const std::string &http_request_method, + const std::string &canonical_uri, + const std::string &canonical_query_string, + const std::string &canonical_headers, + const std::string &signed_headers, + const std::string &payload); + +std::string string_to_sign(const std::string &algorithm, + const std::time_t &request_date, + const std::string &credential_scope, + const std::string &hashed_canonical_request); + +std::string ISO8601_date(const std::time_t &t); + +std::string utc_yyyymmdd(const std::time_t &t); + +std::string credential_scope(const std::time_t &t, + const std::string ®ion, + const std::string &service); + +std::string calculate_signature(const std::time_t &request_date, + const std::string &secret, + const std::string ®ion, + const std::string &service, + const std::string &string_to_sign); + +// The whole enchilada. Added jhrg 11/25/19 +std::string compute_awsv4_signature(const std::shared_ptr &uri_str, const std::time_t &request_date, + const std::string &public_key, const std::string &secret_key, + const std::string ®ion, const std::string &service = "s3"); + +// Added these two as part of removing the use of std::shared_ptr. jhrg 2/20/25 +std::string compute_awsv4_signature(const http::url &uri, const std::time_t &request_date, + const std::string &public_key, const std::string &secret_key, + const std::string ®ion, const std::string &service = "s3"); + +std::string compute_awsv4_signature(const std::string &canonical_uri, const std::string &canonical_query, + const std::string &host, const std::time_t &request_date, + const std::string &public_key, const std::string &secret_key, + const std::string ®ion, const std::string &service); +} + +#endif diff --git a/modules/dmrpp_module/demo/3B42.20190110.06.7.HDF b/modules/dmrpp_module/demo/3B42.20190110.06.7.HDF new file mode 100644 index 0000000000..c8b0332b9f Binary files /dev/null and b/modules/dmrpp_module/demo/3B42.20190110.06.7.HDF differ diff --git a/modules/dmrpp_module/demo/3B42.20190110.06.7.HDF.dmrpp b/modules/dmrpp_module/demo/3B42.20190110.06.7.HDF.dmrpp new file mode 100644 index 0000000000..3765b1c44a --- /dev/null +++ b/modules/dmrpp_module/demo/3B42.20190110.06.7.HDF.dmrpp @@ -0,0 +1,164 @@ + + + + + + + + + + + degrees_north + + + lat -50.000000 0.250000 + + eJwV1E1MzwEcBvCfohIqoRJSqSSEUpL8q3+vc+jg0MzBrIO1Dg4OZg7GMDMZhpnRWsPMsJjMzEvystYwGmYma01mRsMwMywfh8/2bM/2PXwPT7C97m6wvZYaqqkiTCUVlBNiJWWsoJTllLCMYopYSiEFLGExi8hnIQuYTx7zyGUuOWSTxRwyySCd2aQxi5nMIJXppJBMEtOYyhQSmUwC8cQxiYlMIJbxxBBNFOMYSyQRjCG4GwSjPUHwl9/84ic/+MZXPjPCRz7wnne8ZYhB3vCaV7zkBc/o5wmPeUgfvTzgHj10c4sbXOcaV7nCZTq5yHnOcZYznKKDdto4wXGOcZTDHOIA+9nHXvawm53sYBtb2cwmNtLCBppYx1oaWU0Dq6glTIhSiikgnzxyyCSNVJJIJI5Yoojgz50g+M4nhhngOY+4z026uMBpTnKEVnaxhWbWUE8JuaQQw5fuIHjKJQ6ynnTu3A6C4L+QTHq5joNc4ilfiKlwi1xKqGcNzWxhF60c4SSnuUAXN7nPI54zwDCf+M4fIir9gljiSCSJVNLIJIc88imgmFJChKllFQ2sppG1rKOJDbSwkU1sZivb2MFOdrOHvexjPwc4xGGOcozjnKCNdjo4xRnOco7zXKSTy1zhKte4zg1u0U0P93hAL3085DFP6OcZL3jJK17zhkGGeMs73vOBj4zwma984wc/+cVv/jJaaQPCtoAIIhnLOKKIJobxxDKBiUwijngSmEwiU5jKNJJIJoXppDKDmcwijdmkk0Emc8gimxzmkss88pjPAhaSzyIWs4QCCllKEcUso4TllLKCMlYSopwKKglTRTU11FIX/gczErpU + + + + + degrees_east + + + lon -180.000000 0.250000 + + eJwV1lUUFlUbhuFPRARUVEREVNyiIiCigh34it3dNXZ3d3d369gBit3Ki9jdHdvu7v6v/+Ba9zxr1pqDOdhrd+rIiZ2WhkIdYdNQqPPbNBTqfDYNhTqvTUOhDrdpKNR5bBoKdZhNQ6HObdNQqENtGgp1iE1DoQ62aSjUuWwaCnWQTUOhzmnTUKhz2DQU6uw2DYU60KahUGezaSjUYtNQqLPaNBTqAJuGQp3FpqFQZ7ZpKNSZbBoKtb9NQ6HOaNNQqP1sGgp1BpuGQu1r01Co09s0FGofm4ZCnc6moVB72zQU6rQ2DYU6jU1DoU5t01CovWwaCnUqm4ZCndKmoVCnsGko1J42DYXaw6ahULvbNBTq5DYNhdrNpqFQJ7NpKNSuNg2FOqlNQ6F2sWko1ElsGgq1Y9NQyP8e7gT5r5L/KPm3kn8p+aeSfyj5u5K/Kfmrkr8o+bOSPyn5o5I/KPm9kt8p+a2S3yj5tZJfKfmlkl8o+bmSnyn5qZKfKPmxkh8p+aGSHyhZlXxfyfeUfFfJd5R8W8m3lHxTyTeUfF3J15R8VclXlHxZyZeUfFHJF5R8XsnnlHxWyWeUfFrJp5R8UsknlHxcyceUfFTJR5ScqOTDSk5QMpUcr+RDSj6o5ANK3q/kfUreq+Q9St6t5F1K3qnkHUreruRtSt6q5C1KjlPyZiVvUnKskmOUvFHJG5S8XsnrlLxWyWuUvFrJq5S8UskrlGyVvFzJy5S8VMlLlLxYyYuUvFDJC5Q8X8nzlDxXyXOUPFvJs5Q8U8kzlDxdydOUPFXJU5Q8WcmTlDxRyROUPF7J45Q8VsljlDxayaOUPFLJI5QjDucwDuUQDuYgDuQA9mc/9mUf9mYv9mQPdmc3dmUXdmYndmQHtmc7tmUbtmYrtqRhCzZnMzZlEzZmIzZkA9ZnPdZlHdZmLdZkDVZnNVZlFVZmJVZkBZZnOZZlGUazNMFSjGJJlmBxFmNRFmFhFmJBFmAkI5if+ZiX4czDMOZmKEMYzFwMYk7mYHYGMhuFWRnALMzMTPRnRvoxA32Znj5MR2+mZRqmphdTMSVT0JMedGdyujEZXZmULkxC5+FO578Jnc4//MUf/MYv/MQPfMc3fMUXfMYnfMQHvM+7vM2bvM6rvMyLPM+zPM2TPM6jTGQC43mQ+7mXu7mT27mVcdzEGG7gOq7hKq7gci7lYi7kfM7lbM7kdE7lZE7keI7laI7kMA5iP/ZiN3ZiO7ZiczZmfdZmdVZmeUYzisVYiBEMZyiDGMgA+tOX3vSiJ93owt/Z6fzM13zMO7zCMzzCA9zBWK7mEs7hFI7hAHZgQ1ZkEQbTj+58P77TeYFbOIOGQj7U6XT+b5RnylLecQa38ALf0z18i8EswopsyA4cwDGcwjlcwtWM5Q4e4BGe4RXe4WO+5mf+psvS/gU96UVv+tKfAQxkEEMZzggWYjFGMZrlWZnVWZv12ZjN2Yrt2Ind2Iv9OIjDOJKjOZbjOZGTOZXTOZOzOZfzuZCLuZTLuYKruIbruIEx3MQ4buV27uRu7uV+HmQ8E5jIozzOkzzNszzPi7zMq7zOm7zNu7zPB3zEJ3zGF3zFN3zHD/zEL/zGH/zFP/y3tDNgtLOALkxKVyajG5PTnR70ZAqmZCp6MTXTMC29mY4+TE9fZqAfM9KfmZiZWRjArBRmYyCzMwdzMoi5GMwQhjI3w5iH4czLfMzPCEayAAuyEAuzCIuyGIuzBEsyiqUIlmY0y7Asy7E8K7AiK7Eyq7Aqq7E6a7Ama7E267Au67E+G7AhG7Exm7Apm7E5W9CwJVuxNduwLduxPTuwIzuxM7uwK7uxO3uwJ3uxN/uwL/uxPwdwIAdxMIdwKIdx+OhOHDHaXUCPVOIoJY5W4hgljlXiOCWOV+IEJU5U4iQlTlbiFCVOVeI0JU5X4gwlzlTiLCXOVuIcJc5V4jwlzlfiAiUuVOIiJS5W4hIlLlXiMiUuV6JV4golrlTiKiWuVuIaJa5V4jolrlfiBiVuVGKMEmOVuEmJm5UYp8QtStyqxG1K3K7EHUrcqcRdStytxD1K3KvEfUrcr8QDSjyoxENKjFcilZigxMNKTFTiESUeVeIxJR5X4gklnlTiKSWeVuIZJZ5V4jklnlfiBSVeVOIlJV5W4hUlXlXiNSVeV+INJd5U4i0l3lbiHSXeVeI9Jd5XoirxgRIfKvGREh8r8YkSnyrxmRKfK/GFEl8q8ZUSXyvxjRLfKvGdEt8r8YMSPyrxkxI/K/GLEr8q8ZsSvyvxhxJ/KvGXEn8r8Y8S/yrxn1I6y3QaWiplEpuWSuli01Ipk9q0VEpXm5ZKmcympVK62bRUyuQ2LZXS3aalUnrYtFRKT5uWSpnCpqVSprRpqZSpbFoqpZdNS6VMbdNSKdPYtFTKtDYtldLbpqVSprNpqZQ+Ni2VMr1NS6X0tWmplBlsWiqln01Lpcxo01Ip/W1aKmUmm5ZKmdmmpVJmsWmplAE2LZUyq01LpRSblkqZzaalUgbatFTK7DYtlTKHTUulzGnTUimDbFoqZS6blkoZbNNSKUNsWiplqE1Lpcxt01Ipw2xaKmUem5ZKGW7TUinz2rRUynw2LZUyv01LpYywaamUkTYtdeQy/wPg1ahm + + + AlgorithmID=3B42; +AlgorithmVersion=3B42_7.0; +FileName=3B42.20190110.06.7.HDF; +GenerationDateTime=2019-03-29T13:09:11.000Z; +StartGranuleDateTime=2019-01-10T04:30:00.000Z; +StopGranuleDateTime=2019-01-10T07:29:59.999Z; +GranuleNumber=; +NumberOfSwaths=0; +NumberOfGrids=1; +GranuleStart=; +TimeInterval=3_HOUR; +ProcessingSystem=PPS; +ProductVersion=7; +MissingData=; + + + + DataFormatVersion=m; +TKCodeBuildVersion=1; +MetadataVersion=m; +FormatPackage=HDF Version 4.2 Release 4, January 25, 2009; +BlueprintFilename=TRMM.V7.3B42.blueprint.xml; +BlueprintVersion=BV_13; +TKIOVersion=1.6; +MetadataStyle=PVL; +EndianType=LITTLE_ENDIAN; + + + + BinMethod=ARITHMETIC_MEAN; +Registration=CENTER; +LatitudeResolution=0.25; +LongitudeResolution=0.25; +NorthBoundingCoordinate=50; +SouthBoundingCoordinate=-50; +EastBoundingCoordinate=180; +WestBoundingCoordinate=-180; +Origin=SOUTHWEST; + + + + + + + + mm/hr + + + 4 + + + + + + + + + + mm/hr + + + 6 + + + + + + + + + + 8 + + + + + + + + + + mm/hr + + + 10 + + + -9999.9 + + + + + + + + + + mm/hr + + + 12 + + + + + + + + + + minutes + + + 14 + + + + + + + BinMethod=ARITHMETIC_MEAN; +Registration=CENTER; +LatitudeResolution=0.25; +LongitudeResolution=0.25; +NorthBoundingCoordinate=50; +SouthBoundingCoordinate=-50; +EastBoundingCoordinate=180; +WestBoundingCoordinate=-180; +Origin=SOUTHWEST; + + + + diff --git a/modules/dmrpp_module/demo/3B42.20190110.09.7.HDF b/modules/dmrpp_module/demo/3B42.20190110.09.7.HDF new file mode 100644 index 0000000000..31cbbcb8ef Binary files /dev/null and b/modules/dmrpp_module/demo/3B42.20190110.09.7.HDF differ diff --git a/modules/dmrpp_module/demo/3B42.20190110.09.7.HDF.dmrpp b/modules/dmrpp_module/demo/3B42.20190110.09.7.HDF.dmrpp new file mode 100644 index 0000000000..ec9bec99a8 --- /dev/null +++ b/modules/dmrpp_module/demo/3B42.20190110.09.7.HDF.dmrpp @@ -0,0 +1,162 @@ + + + + + + + + + degrees_north + + + lat -50.000000 0.250000 + + eJwV1E1MzwEcBvCfohIqoRJSqSSEUpL8q3+vc+jg0MzBrIO1Dg4OZg7GMDMZhpnRWsPMsJjMzEvystYwGmYma01mRsMwMywfh8/2bM/2PXwPT7C97m6wvZYaqqkiTCUVlBNiJWWsoJTllLCMYopYSiEFLGExi8hnIQuYTx7zyGUuOWSTxRwyySCd2aQxi5nMIJXppJBMEtOYyhQSmUwC8cQxiYlMIJbxxBBNFOMYSyQRjCG4GwSjPUHwl9/84ic/+MZXPjPCRz7wnne8ZYhB3vCaV7zkBc/o5wmPeUgfvTzgHj10c4sbXOcaV7nCZTq5yHnOcZYznKKDdto4wXGOcZTDHOIA+9nHXvawm53sYBtb2cwmNtLCBppYx1oaWU0Dq6glTIhSiikgnzxyyCSNVJJIJI5Yoojgz50g+M4nhhngOY+4z026uMBpTnKEVnaxhWbWUE8JuaQQw5fuIHjKJQ6ynnTu3A6C4L+QTHq5joNc4ilfiKlwi1xKqGcNzWxhF60c4SSnuUAXN7nPI54zwDCf+M4fIir9gljiSCSJVNLIJIc88imgmFJChKllFQ2sppG1rKOJDbSwkU1sZivb2MFOdrOHvexjPwc4xGGOcozjnKCNdjo4xRnOco7zXKSTy1zhKte4zg1u0U0P93hAL3085DFP6OcZL3jJK17zhkGGeMs73vOBj4zwma984wc/+cVv/jJaaQPCtoAIIhnLOKKIJobxxDKBiUwijngSmEwiU5jKNJJIJoXppDKDmcwijdmkk0Emc8gimxzmkss88pjPAhaSzyIWs4QCCllKEcUso4TllLKCMlYSopwKKglTRTU11FIX/gczErpU + + + + + degrees_east + + + lon -180.000000 0.250000 + + eJwV1lUUFlUbhuFPRARUVEREVNyiIiCigh34it3dNXZ3d3d369gBit3Ki9jdHdvu7v6v/+Ba9zxr1pqDOdhrd+rIiZ2WhkIdYdNQqPPbNBTqfDYNhTqvTUOhDrdpKNR5bBoKdZhNQ6HObdNQqENtGgp1iE1DoQ62aSjUuWwaCnWQTUOhzmnTUKhz2DQU6uw2DYU60KahUGezaSjUYtNQqLPaNBTqAJuGQp3FpqFQZ7ZpKNSZbBoKtb9NQ6HOaNNQqP1sGgp1BpuGQu1r01Co09s0FGofm4ZCnc6moVB72zQU6rQ2DYU6jU1DoU5t01CovWwaCnUqm4ZCndKmoVCnsGko1J42DYXaw6ahULvbNBTq5DYNhdrNpqFQJ7NpKNSuNg2FOqlNQ6F2sWko1ElsGgq1Y9NQyP8e7gT5r5L/KPm3kn8p+aeSfyj5u5K/Kfmrkr8o+bOSPyn5o5I/KPm9kt8p+a2S3yj5tZJfKfmlkl8o+bmSnyn5qZKfKPmxkh8p+aGSHyhZlXxfyfeUfFfJd5R8W8m3lHxTyTeUfF3J15R8VclXlHxZyZeUfFHJF5R8XsnnlHxWyWeUfFrJp5R8UsknlHxcyceUfFTJR5ScqOTDSk5QMpUcr+RDSj6o5ANK3q/kfUreq+Q9St6t5F1K3qnkHUreruRtSt6q5C1KjlPyZiVvUnKskmOUvFHJG5S8XsnrlLxWyWuUvFrJq5S8UskrlGyVvFzJy5S8VMlLlLxYyYuUvFDJC5Q8X8nzlDxXyXOUPFvJs5Q8U8kzlDxdydOUPFXJU5Q8WcmTlDxRyROUPF7J45Q8VsljlDxayaOUPFLJI5QjDucwDuUQDuYgDuQA9mc/9mUf9mYv9mQPdmc3dmUXdmYndmQHtmc7tmUbtmYrtqRhCzZnMzZlEzZmIzZkA9ZnPdZlHdZmLdZkDVZnNVZlFVZmJVZkBZZnOZZlGUazNMFSjGJJlmBxFmNRFmFhFmJBFmAkI5if+ZiX4czDMOZmKEMYzFwMYk7mYHYGMhuFWRnALMzMTPRnRvoxA32Znj5MR2+mZRqmphdTMSVT0JMedGdyujEZXZmULkxC5+FO578Jnc4//MUf/MYv/MQPfMc3fMUXfMYnfMQHvM+7vM2bvM6rvMyLPM+zPM2TPM6jTGQC43mQ+7mXu7mT27mVcdzEGG7gOq7hKq7gci7lYi7kfM7lbM7kdE7lZE7keI7laI7kMA5iP/ZiN3ZiO7ZiczZmfdZmdVZmeUYzisVYiBEMZyiDGMgA+tOX3vSiJ93owt/Z6fzM13zMO7zCMzzCA9zBWK7mEs7hFI7hAHZgQ1ZkEQbTj+58P77TeYFbOIOGQj7U6XT+b5RnylLecQa38ALf0z18i8EswopsyA4cwDGcwjlcwtWM5Q4e4BGe4RXe4WO+5mf+psvS/gU96UVv+tKfAQxkEEMZzggWYjFGMZrlWZnVWZv12ZjN2Yrt2Ind2Iv9OIjDOJKjOZbjOZGTOZXTOZOzOZfzuZCLuZTLuYKruIbruIEx3MQ4buV27uRu7uV+HmQ8E5jIozzOkzzNszzPi7zMq7zOm7zNu7zPB3zEJ3zGF3zFN3zHD/zEL/zGH/zFP/y3tDNgtLOALkxKVyajG5PTnR70ZAqmZCp6MTXTMC29mY4+TE9fZqAfM9KfmZiZWRjArBRmYyCzMwdzMoi5GMwQhjI3w5iH4czLfMzPCEayAAuyEAuzCIuyGIuzBEsyiqUIlmY0y7Asy7E8K7AiK7Eyq7Aqq7E6a7Ama7E267Au67E+G7AhG7Exm7Apm7E5W9CwJVuxNduwLduxPTuwIzuxM7uwK7uxO3uwJ3uxN/uwL/uxPwdwIAdxMIdwKIdx+OhOHDHaXUCPVOIoJY5W4hgljlXiOCWOV+IEJU5U4iQlTlbiFCVOVeI0JU5X4gwlzlTiLCXOVuIcJc5V4jwlzlfiAiUuVOIiJS5W4hIlLlXiMiUuV6JV4golrlTiKiWuVuIaJa5V4jolrlfiBiVuVGKMEmOVuEmJm5UYp8QtStyqxG1K3K7EHUrcqcRdStytxD1K3KvEfUrcr8QDSjyoxENKjFcilZigxMNKTFTiESUeVeIxJR5X4gklnlTiKSWeVuIZJZ5V4jklnlfiBSVeVOIlJV5W4hUlXlXiNSVeV+INJd5U4i0l3lbiHSXeVeI9Jd5XoirxgRIfKvGREh8r8YkSnyrxmRKfK/GFEl8q8ZUSXyvxjRLfKvGdEt8r8YMSPyrxkxI/K/GLEr8q8ZsSvyvxhxJ/KvGXEn8r8Y8S/yrxn1I6y3QaWiplEpuWSuli01Ipk9q0VEpXm5ZKmcympVK62bRUyuQ2LZXS3aalUnrYtFRKT5uWSpnCpqVSprRpqZSpbFoqpZdNS6VMbdNSKdPYtFTKtDYtldLbpqVSprNpqZQ+Ni2VMr1NS6X0tWmplBlsWiqln01Lpcxo01Ip/W1aKmUmm5ZKmdmmpVJmsWmplAE2LZUyq01LpRSblkqZzaalUgbatFTK7DYtlTKHTUulzGnTUimDbFoqZS6blkoZbNNSKUNsWiplqE1Lpcxt01Ipw2xaKmUem5ZKGW7TUinz2rRUynw2LZUyv01LpYywaamUkTYtdeQy/wPg1ahm + + + AlgorithmID=3B42; +AlgorithmVersion=3B42_7.0; +FileName=3B42.20190110.09.7.HDF; +GenerationDateTime=2019-03-29T13:09:11.000Z; +StartGranuleDateTime=2019-01-10T07:30:00.000Z; +StopGranuleDateTime=2019-01-10T10:29:59.999Z; +GranuleNumber=; +NumberOfSwaths=0; +NumberOfGrids=1; +GranuleStart=; +TimeInterval=3_HOUR; +ProcessingSystem=PPS; +ProductVersion=7; +MissingData=; + + + + DataFormatVersion=m; +TKCodeBuildVersion=1; +MetadataVersion=m; +FormatPackage=HDF Version 4.2 Release 4, January 25, 2009; +BlueprintFilename=TRMM.V7.3B42.blueprint.xml; +BlueprintVersion=BV_13; +TKIOVersion=1.6; +MetadataStyle=PVL; +EndianType=LITTLE_ENDIAN; + + + + BinMethod=ARITHMETIC_MEAN; +Registration=CENTER; +LatitudeResolution=0.25; +LongitudeResolution=0.25; +NorthBoundingCoordinate=50; +SouthBoundingCoordinate=-50; +EastBoundingCoordinate=180; +WestBoundingCoordinate=-180; +Origin=SOUTHWEST; + + + + + + + + mm/hr + + + 4 + + + + + + + + + + mm/hr + + + 6 + + + + + + + + + + 8 + + + + + + + + + + mm/hr + + + 10 + + + -9999.9 + + + + + + + + + + mm/hr + + + 12 + + + + + + + + + + minutes + + + 14 + + + + + + + BinMethod=ARITHMETIC_MEAN; +Registration=CENTER; +LatitudeResolution=0.25; +LongitudeResolution=0.25; +NorthBoundingCoordinate=50; +SouthBoundingCoordinate=-50; +EastBoundingCoordinate=180; +WestBoundingCoordinate=-180; +Origin=SOUTHWEST; + + + + diff --git a/modules/dmrpp_module/demo/3B42.20190110.12.7.HDF b/modules/dmrpp_module/demo/3B42.20190110.12.7.HDF new file mode 100644 index 0000000000..37f5e739d8 Binary files /dev/null and b/modules/dmrpp_module/demo/3B42.20190110.12.7.HDF differ diff --git a/modules/dmrpp_module/demo/3B42.20190110.12.7.HDF.dmrpp b/modules/dmrpp_module/demo/3B42.20190110.12.7.HDF.dmrpp new file mode 100644 index 0000000000..78e50fb151 --- /dev/null +++ b/modules/dmrpp_module/demo/3B42.20190110.12.7.HDF.dmrpp @@ -0,0 +1,163 @@ + + + + + + + + + + degrees_north + + + lat -50.000000 0.250000 + + eJwV1E1MzwEcBvCfohIqoRJSqSSEUpL8q3+vc+jg0MzBrIO1Dg4OZg7GMDMZhpnRWsPMsJjMzEvystYwGmYma01mRsMwMywfh8/2bM/2PXwPT7C97m6wvZYaqqkiTCUVlBNiJWWsoJTllLCMYopYSiEFLGExi8hnIQuYTx7zyGUuOWSTxRwyySCd2aQxi5nMIJXppJBMEtOYyhQSmUwC8cQxiYlMIJbxxBBNFOMYSyQRjCG4GwSjPUHwl9/84ic/+MZXPjPCRz7wnne8ZYhB3vCaV7zkBc/o5wmPeUgfvTzgHj10c4sbXOcaV7nCZTq5yHnOcZYznKKDdto4wXGOcZTDHOIA+9nHXvawm53sYBtb2cwmNtLCBppYx1oaWU0Dq6glTIhSiikgnzxyyCSNVJJIJI5Yoojgz50g+M4nhhngOY+4z026uMBpTnKEVnaxhWbWUE8JuaQQw5fuIHjKJQ6ynnTu3A6C4L+QTHq5joNc4ilfiKlwi1xKqGcNzWxhF60c4SSnuUAXN7nPI54zwDCf+M4fIir9gljiSCSJVNLIJIc88imgmFJChKllFQ2sppG1rKOJDbSwkU1sZivb2MFOdrOHvexjPwc4xGGOcozjnKCNdjo4xRnOco7zXKSTy1zhKte4zg1u0U0P93hAL3085DFP6OcZL3jJK17zhkGGeMs73vOBj4zwma984wc/+cVv/jJaaQPCtoAIIhnLOKKIJobxxDKBiUwijngSmEwiU5jKNJJIJoXppDKDmcwijdmkk0Emc8gimxzmkss88pjPAhaSzyIWs4QCCllKEcUso4TllLKCMlYSopwKKglTRTU11FIX/gczErpU + + + + + degrees_east + + + lon -180.000000 0.250000 + + eJwV1lUUFlUbhuFPRARUVEREVNyiIiCigh34it3dNXZ3d3d369gBit3Ki9jdHdvu7v6v/+Ba9zxr1pqDOdhrd+rIiZ2WhkIdYdNQqPPbNBTqfDYNhTqvTUOhDrdpKNR5bBoKdZhNQ6HObdNQqENtGgp1iE1DoQ62aSjUuWwaCnWQTUOhzmnTUKhz2DQU6uw2DYU60KahUGezaSjUYtNQqLPaNBTqAJuGQp3FpqFQZ7ZpKNSZbBoKtb9NQ6HOaNNQqP1sGgp1BpuGQu1r01Co09s0FGofm4ZCnc6moVB72zQU6rQ2DYU6jU1DoU5t01CovWwaCnUqm4ZCndKmoVCnsGko1J42DYXaw6ahULvbNBTq5DYNhdrNpqFQJ7NpKNSuNg2FOqlNQ6F2sWko1ElsGgq1Y9NQyP8e7gT5r5L/KPm3kn8p+aeSfyj5u5K/Kfmrkr8o+bOSPyn5o5I/KPm9kt8p+a2S3yj5tZJfKfmlkl8o+bmSnyn5qZKfKPmxkh8p+aGSHyhZlXxfyfeUfFfJd5R8W8m3lHxTyTeUfF3J15R8VclXlHxZyZeUfFHJF5R8XsnnlHxWyWeUfFrJp5R8UsknlHxcyceUfFTJR5ScqOTDSk5QMpUcr+RDSj6o5ANK3q/kfUreq+Q9St6t5F1K3qnkHUreruRtSt6q5C1KjlPyZiVvUnKskmOUvFHJG5S8XsnrlLxWyWuUvFrJq5S8UskrlGyVvFzJy5S8VMlLlLxYyYuUvFDJC5Q8X8nzlDxXyXOUPFvJs5Q8U8kzlDxdydOUPFXJU5Q8WcmTlDxRyROUPF7J45Q8VsljlDxayaOUPFLJI5QjDucwDuUQDuYgDuQA9mc/9mUf9mYv9mQPdmc3dmUXdmYndmQHtmc7tmUbtmYrtqRhCzZnMzZlEzZmIzZkA9ZnPdZlHdZmLdZkDVZnNVZlFVZmJVZkBZZnOZZlGUazNMFSjGJJlmBxFmNRFmFhFmJBFmAkI5if+ZiX4czDMOZmKEMYzFwMYk7mYHYGMhuFWRnALMzMTPRnRvoxA32Znj5MR2+mZRqmphdTMSVT0JMedGdyujEZXZmULkxC5+FO578Jnc4//MUf/MYv/MQPfMc3fMUXfMYnfMQHvM+7vM2bvM6rvMyLPM+zPM2TPM6jTGQC43mQ+7mXu7mT27mVcdzEGG7gOq7hKq7gci7lYi7kfM7lbM7kdE7lZE7keI7laI7kMA5iP/ZiN3ZiO7ZiczZmfdZmdVZmeUYzisVYiBEMZyiDGMgA+tOX3vSiJ93owt/Z6fzM13zMO7zCMzzCA9zBWK7mEs7hFI7hAHZgQ1ZkEQbTj+58P77TeYFbOIOGQj7U6XT+b5RnylLecQa38ALf0z18i8EswopsyA4cwDGcwjlcwtWM5Q4e4BGe4RXe4WO+5mf+psvS/gU96UVv+tKfAQxkEEMZzggWYjFGMZrlWZnVWZv12ZjN2Yrt2Ind2Iv9OIjDOJKjOZbjOZGTOZXTOZOzOZfzuZCLuZTLuYKruIbruIEx3MQ4buV27uRu7uV+HmQ8E5jIozzOkzzNszzPi7zMq7zOm7zNu7zPB3zEJ3zGF3zFN3zHD/zEL/zGH/zFP/y3tDNgtLOALkxKVyajG5PTnR70ZAqmZCp6MTXTMC29mY4+TE9fZqAfM9KfmZiZWRjArBRmYyCzMwdzMoi5GMwQhjI3w5iH4czLfMzPCEayAAuyEAuzCIuyGIuzBEsyiqUIlmY0y7Asy7E8K7AiK7Eyq7Aqq7E6a7Ama7E267Au67E+G7AhG7Exm7Apm7E5W9CwJVuxNduwLduxPTuwIzuxM7uwK7uxO3uwJ3uxN/uwL/uxPwdwIAdxMIdwKIdx+OhOHDHaXUCPVOIoJY5W4hgljlXiOCWOV+IEJU5U4iQlTlbiFCVOVeI0JU5X4gwlzlTiLCXOVuIcJc5V4jwlzlfiAiUuVOIiJS5W4hIlLlXiMiUuV6JV4golrlTiKiWuVuIaJa5V4jolrlfiBiVuVGKMEmOVuEmJm5UYp8QtStyqxG1K3K7EHUrcqcRdStytxD1K3KvEfUrcr8QDSjyoxENKjFcilZigxMNKTFTiESUeVeIxJR5X4gklnlTiKSWeVuIZJZ5V4jklnlfiBSVeVOIlJV5W4hUlXlXiNSVeV+INJd5U4i0l3lbiHSXeVeI9Jd5XoirxgRIfKvGREh8r8YkSnyrxmRKfK/GFEl8q8ZUSXyvxjRLfKvGdEt8r8YMSPyrxkxI/K/GLEr8q8ZsSvyvxhxJ/KvGXEn8r8Y8S/yrxn1I6y3QaWiplEpuWSuli01Ipk9q0VEpXm5ZKmcympVK62bRUyuQ2LZXS3aalUnrYtFRKT5uWSpnCpqVSprRpqZSpbFoqpZdNS6VMbdNSKdPYtFTKtDYtldLbpqVSprNpqZQ+Ni2VMr1NS6X0tWmplBlsWiqln01Lpcxo01Ip/W1aKmUmm5ZKmdmmpVJmsWmplAE2LZUyq01LpRSblkqZzaalUgbatFTK7DYtlTKHTUulzGnTUimDbFoqZS6blkoZbNNSKUNsWiplqE1Lpcxt01Ipw2xaKmUem5ZKGW7TUinz2rRUynw2LZUyv01LpYywaamUkTYtdeQy/wPg1ahm + + + AlgorithmID=3B42; +AlgorithmVersion=3B42_7.0; +FileName=3B42.20190110.12.7.HDF; +GenerationDateTime=2019-03-29T13:09:12.000Z; +StartGranuleDateTime=2019-01-10T10:30:00.000Z; +StopGranuleDateTime=2019-01-10T13:29:59.999Z; +GranuleNumber=; +NumberOfSwaths=0; +NumberOfGrids=1; +GranuleStart=; +TimeInterval=3_HOUR; +ProcessingSystem=PPS; +ProductVersion=7; +MissingData=; + + + + DataFormatVersion=m; +TKCodeBuildVersion=1; +MetadataVersion=m; +FormatPackage=HDF Version 4.2 Release 4, January 25, 2009; +BlueprintFilename=TRMM.V7.3B42.blueprint.xml; +BlueprintVersion=BV_13; +TKIOVersion=1.6; +MetadataStyle=PVL; +EndianType=LITTLE_ENDIAN; + + + + BinMethod=ARITHMETIC_MEAN; +Registration=CENTER; +LatitudeResolution=0.25; +LongitudeResolution=0.25; +NorthBoundingCoordinate=50; +SouthBoundingCoordinate=-50; +EastBoundingCoordinate=180; +WestBoundingCoordinate=-180; +Origin=SOUTHWEST; + + + + + + + + mm/hr + + + 4 + + + + + + + + + + mm/hr + + + 6 + + + + + + + + + + 8 + + + + + + + + + + mm/hr + + + 10 + + + -9999.9 + + + + + + + + + + mm/hr + + + 12 + + + + + + + + + + minutes + + + 14 + + + + + + + BinMethod=ARITHMETIC_MEAN; +Registration=CENTER; +LatitudeResolution=0.25; +LongitudeResolution=0.25; +NorthBoundingCoordinate=50; +SouthBoundingCoordinate=-50; +EastBoundingCoordinate=180; +WestBoundingCoordinate=-180; +Origin=SOUTHWEST; + + + + diff --git a/modules/dmrpp_module/tests/demo/bescmd.xml b/modules/dmrpp_module/tests/demo/bescmd.xml new file mode 100644 index 0000000000..5feba16678 --- /dev/null +++ b/modules/dmrpp_module/tests/demo/bescmd.xml @@ -0,0 +1,18 @@ + + + 300 + {"$schema":"https:\/\/harmony.earthdata.nasa.gov\/schemas\/history\/0.1.0\/history-0.1.0.json","date_time":"2024-06-16T22:50:52.661+0000","program":"hyrax","version":"metrics-0.2","parameters":[{"request_url":"http:\/\/localhost:8080\/opendap\/demo\/3B42.20190110.09.7.HDF.dmrpp.dap.nc4?dap4.ce=\/nlat%5B0:1:399%5D;\/nlon%5B0:1:1439%5D;\/Grid\/precipitation%5B0:1:1439%5D%5B0:1:399%5D"},{"decoded_constraint":"dap4.ce=\/nlat[0:1:399];\/nlon[0:1:1439];\/Grid\/precipitation[0:1:1439][0:1:399]"}]} + 2024-06-16 22:50:52 GMT hyrax-metrics-0.2 http://localhost:8080/opendap/demo/3B42.20190110.09.7.HDF.dmrpp.dap.nc4?dap4.ce=/nlat%5B0:1:399%5D;/nlon%5B0:1:1439%5D;/Grid/precipitation%5B0:1:1439%5D%5B0:1:399%5D + no + xml + 0 + 0 + not_logged_in + /demo/3B42.20190110.09.7.HDF.dmrpp + + + /nlat[0:1:399];/nlon[0:1:1439];/Grid/precipitation[0:1:1439][0:1:399] + + + + diff --git a/modules/dmrpp_module/tests/demo/bescmd_2.xml b/modules/dmrpp_module/tests/demo/bescmd_2.xml new file mode 100644 index 0000000000..fd74e63d02 --- /dev/null +++ b/modules/dmrpp_module/tests/demo/bescmd_2.xml @@ -0,0 +1,18 @@ + + + 300 + {"$schema":"https:\/\/harmony.earthdata.nasa.gov\/schemas\/history\/0.1.0\/history-0.1.0.json","date_time":"2024-06-16T22:50:52.661+0000","program":"hyrax","version":"metrics-0.2","parameters":[{"request_url":"http:\/\/localhost:8080\/opendap\/demo\/3B42.20190110.09.7.HDF.dmrpp.dap.nc4?dap4.ce=\/nlat%5B0:1:399%5D;\/nlon%5B0:1:1439%5D;\/Grid\/precipitation%5B0:1:1439%5D%5B0:1:399%5D"},{"decoded_constraint":"dap4.ce=\/nlat[0:1:399];\/nlon[0:1:1439];\/Grid\/precipitation[0:1:1439][0:1:399]"}]} + 2024-06-16 22:50:52 GMT hyrax-metrics-0.2 http://localhost:8080/opendap/demo/3B42.20190110.09.7.HDF.dmrpp.dap.nc4?dap4.ce=/nlat%5B0:1:399%5D;/nlon%5B0:1:1439%5D;/Grid/precipitation%5B0:1:1439%5D%5B0:1:399%5D + no + xml + 0 + 0 + not_logged_in + /demo/3B42.20190110.09.7.HDF.dmrpp + + + /nlat[0:1:399];/nlon[0:1:1439] + + + + diff --git a/modules/dmrpp_module/tests/demo/bescmd_3.xml b/modules/dmrpp_module/tests/demo/bescmd_3.xml new file mode 100644 index 0000000000..2d92d81896 --- /dev/null +++ b/modules/dmrpp_module/tests/demo/bescmd_3.xml @@ -0,0 +1,18 @@ + + + 300 + {"$schema":"https:\/\/harmony.earthdata.nasa.gov\/schemas\/history\/0.1.0\/history-0.1.0.json","date_time":"2024-06-16T22:50:52.661+0000","program":"hyrax","version":"metrics-0.2","parameters":[{"request_url":"http:\/\/localhost:8080\/opendap\/demo\/3B42.20190110.09.7.HDF.dmrpp.dap.nc4?dap4.ce=\/nlat%5B0:1:399%5D;\/nlon%5B0:1:1439%5D;\/Grid\/precipitation%5B0:1:1439%5D%5B0:1:399%5D"},{"decoded_constraint":"dap4.ce=\/nlat[0:1:399];\/nlon[0:1:1439];\/Grid\/precipitation[0:1:1439][0:1:399]"}]} + 2024-06-16 22:50:52 GMT hyrax-metrics-0.2 http://localhost:8080/opendap/demo/3B42.20190110.09.7.HDF.dmrpp.dap.nc4?dap4.ce=/nlat%5B0:1:399%5D;/nlon%5B0:1:1439%5D;/Grid/precipitation%5B0:1:1439%5D%5B0:1:399%5D + no + xml + 0 + 0 + not_logged_in + /demo/3B42.20190110.09.7.HDF.dmrpp + + + /grid/precipitation + + + + diff --git a/modules/dmrpp_module/tests/testsuite_dmrpp_builder.dir/1/run b/modules/dmrpp_module/tests/testsuite_dmrpp_builder.dir/1/run new file mode 100755 index 0000000000..190da6ad3e --- /dev/null +++ b/modules/dmrpp_module/tests/testsuite_dmrpp_builder.dir/1/run @@ -0,0 +1,5 @@ +#! /bin/sh +test ${ZSH_VERSION+y} && alias -g '${1+"$@"}'='"$@"' +cd '/Users/jimg/src/opendap/hyrax/bes/modules/dmrpp_module/tests' +exec ${CONFIG_SHELL-/bin/sh} "/Users/jimg/src/opendap/hyrax/bes/modules/dmrpp_module/tests/./testsuite_dmrpp_builder" -v -d 1 ${1+"$@"} +exit 1 diff --git a/modules/dmrpp_module/tests/testsuite_dmrpp_builder.dir/1/stdout b/modules/dmrpp_module/tests/testsuite_dmrpp_builder.dir/1/stdout new file mode 100644 index 0000000000..a6c02ad7e3 --- /dev/null +++ b/modules/dmrpp_module/tests/testsuite_dmrpp_builder.dir/1/stdout @@ -0,0 +1,14 @@ + + + + + 3 + Unable to add container 'c' to container storage 'builddmrpp'. Store does not exist. + support@opendap.org + + BESSetContainerResponseHandler.cc + 101 + + + + diff --git a/retired/modules/dmrpp_module/ngap_container/NgapModule.cc b/retired/modules/dmrpp_module/ngap_container/NgapModule.cc new file mode 100644 index 0000000000..eb7e4bb465 --- /dev/null +++ b/retired/modules/dmrpp_module/ngap_container/NgapModule.cc @@ -0,0 +1,85 @@ +// -*- mode: c++; c-basic-offset:4 -*- + +// This file is part of ngap_module, A C++ module that can be loaded in to +// the OPeNDAP Back-End Server (BES) and is able to handle remote requests. + +// Copyright (c) 2020 OPeNDAP, Inc. +// Author: Nathan Potter +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. + + +#include "config.h" + +#include +#include +#include + +#include +#include +#include + +#include "NgapModule.h" +#include "NgapRequestHandler.h" +#include "NgapOwnedContainerStorage.h" + +using namespace std; +using namespace ngap; + +void NgapModule::initialize(const string &modname) +{ + BESDEBUG(modname, "Initializing NGAP Module " << modname << endl); + + BESDEBUG(modname, " adding " << modname << " request handler" << endl); + BESRequestHandlerList::TheList()->add_handler(modname, new NgapRequestHandler(modname)); + + BESDEBUG(modname, " adding OWNED " << modname << " container storage" << endl); + // FIXME Do NOT merge this code as is since it breaks the handler needed for NGAP. + // This is a POC modification to test access to data using DMR++ documents that + // OPeNDAP 'owns.' jhrg 5/17/24 + BESContainerStorageList::TheList()->add_persistence(new NgapOwnedContainerStorage(modname)); + + BESDEBUG(modname, " adding NGAP debug context" << endl); + BESDebug::Register(modname); + + BESDEBUG(modname, "Done Initializing NGAP Module " << modname << endl); +} + +void NgapModule::terminate(const string &modname) +{ + BESDEBUG(modname, "Cleaning NGAP module " << modname << endl); + + BESDEBUG(modname, " removing " << modname << " request handler" << endl); + BESRequestHandler *rh = BESRequestHandlerList::TheList()->remove_handler(modname); + delete rh; + + BESContainerStorageList::TheList()->deref_persistence(modname); + + BESDEBUG(modname, "Done Cleaning NGAP module " << modname << endl); +} + +void NgapModule::dump(ostream &strm) const +{ + strm << BESIndent::LMarg << "NgapModule::dump - (" << (void *) this << ")" << endl; +} + +extern "C" +BESAbstractModule *maker() +{ + return new NgapModule; +} + diff --git a/retired/modules/dmrpp_module/ngap_container/NgapModule.h b/retired/modules/dmrpp_module/ngap_container/NgapModule.h new file mode 100644 index 0000000000..0f1377596a --- /dev/null +++ b/retired/modules/dmrpp_module/ngap_container/NgapModule.h @@ -0,0 +1,51 @@ +// NgapContainer.cc + +// -*- mode: c++; c-basic-offset:4 -*- + +// This file is part of ngap_module, A C++ module that can be loaded in to +// the OPeNDAP Back-End Server (BES) and is able to handle remote requests. + +// Copyright (c) 2020 OPeNDAP, Inc. +// Author: Nathan Potter +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. +// Authors: +// ndp Nathan Potter + +#ifndef I_NgapModule_H +#define I_NgapModule_H 1 + +#include +#include + +#include "BESAbstractModule.h" + +namespace ngap { + +class NgapModule : public BESAbstractModule { +public: + NgapModule() = default; + ~NgapModule() override = default; + + void initialize(const std::string &modname) override; + void terminate(const std::string &modname) override; + void dump(std::ostream &strm) const override; +}; + +} //namespace ngap + +#endif // I_NgapModule_H diff --git a/retired/modules/dmrpp_module/writer/h5common.cc b/retired/modules/dmrpp_module/writer/h5common.cc new file mode 100644 index 0000000000..c21ad2b11b --- /dev/null +++ b/retired/modules/dmrpp_module/writer/h5common.cc @@ -0,0 +1,435 @@ +// data server. + +// Copyright (c) 2007-2023 The HDF Group, Inc. and OPeNDAP, Inc. +// +// This is free software; you can redistribute it and/or modify it under the +// terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 2.1 of the License, or (at your +// option) any later version. +// +// This software is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +// License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. +// You can contact The HDF Group, Inc. at 410 E University Ave, +// Suite 200, Champaign, IL 61820 + +/////////////////////////////////////////////////////////////////////////////// +/// \file h5common.cc +/// +/// Common helper functions to access HDF5 data for both the CF and the default options. +/// +/// +/////////////////////////////////////////////////////////////////////////////// + +#include "h5common.h" + +#include +#include "libdap/InternalErr.h" +#include + + +using namespace std; +using namespace libdap; + +/////////////////////////////////////////////////////////////////////////////// +/// \fn get_data(hid_t dset, void *buf) +/// will get all data of a \a dset dataset and put it into \a buf. +/// Note: this routine is only used to access HDF5 integer,float and fixed-size string. +// variable length string is handled by function read_vlen_string. +/// +/// \param[in] dset dataset id(dset) +/// \param[out] buf pointer to a buffer +/////////////////////////////////////////////////////////////////////////////// +void get_data(hid_t dset, void *buf) +{ + BESDEBUG("h5", ">get_data()" << endl); + + hid_t dtype = -1; + if ((dtype = H5Dget_type(dset)) < 0) { + throw InternalErr(__FILE__, __LINE__, "Failed to get the datatype of the dataset"); + } + hid_t dspace = -1; + if ((dspace = H5Dget_space(dset)) < 0) { + H5Tclose(dtype); + throw InternalErr(__FILE__, __LINE__, "Failed to get the data space of the dataset"); + } + // Use HDF5 H5Tget_native_type API + hid_t memtype = H5Tget_native_type(dtype, H5T_DIR_ASCEND); + if (memtype < 0) { + H5Tclose(dtype); + H5Sclose(dspace); + throw InternalErr(__FILE__, __LINE__, "failed to get memory type"); + } + + if (H5Dread(dset, memtype, dspace, dspace, H5P_DEFAULT, buf) + < 0) { + H5Tclose(dtype); + H5Tclose(memtype); + H5Sclose(dspace); + throw InternalErr(__FILE__, __LINE__, "failed to read data"); + } + + if (H5Tclose(dtype) < 0){ + H5Tclose(memtype); + H5Sclose(dspace); + throw InternalErr(__FILE__, __LINE__, "Unable to release the dtype."); + } + + if (H5Tclose(memtype) < 0){ + H5Sclose(dspace); + throw InternalErr(__FILE__, __LINE__, "Unable to release the memtype."); + } + + if(H5Sclose(dspace)<0) { + throw InternalErr(__FILE__, __LINE__, "Unable to release the data space."); + } +#if 0 + // Supposed to release the resource at the release at the HDF5Array destructor. + //if (H5Dclose(dset) < 0){ + // throw InternalErr(__FILE__, __LINE__, "Unable to close the dataset."); + //} + } +#endif + + BESDEBUG("h5", "get_strdata(): " + << " strindex=" << strindex << " allbuf=" << allbuf << endl); + + // Tokenize the convbuf. + // The following line causes the degradation of the performance. + // The code seems a leftover of a debugging process. +#if 0 + for (int i = 0; i < strindex; i++) { + tempvalue = tempvalue + elesize; + } +#endif + tempvalue = tempvalue +strindex *elesize; + + strncpy(buf, tempvalue, elesize); + buf[elesize] = '\0'; +} + +/////////////////////////////////////////////////////////////////////////////// +/// \fn get_slabdata(hid_t dset, int *offset, int *step, int *count, +/// int num_dim, void *buf) +/// will get hyperslab data of a dataset and put it into buf. +/// +/// \param[in] dset dataset id +/// \param[in] offset starting point +/// \param[in] step stride +/// \param[in] count count +/// \param[in] num_dim number of array dimensions +/// \param[out] buf pointer to a buffer +/////////////////////////////////////////////////////////////////////////////// +int +get_slabdata(hid_t dset, const int64_t *offset, const int64_t *step, const int64_t *count, const int num_dim, + void *buf) +{ + BESDEBUG("h5", ">get_slabdata() " << endl); + + hid_t dtype = H5Dget_type(dset); + if (dtype < 0) { + throw InternalErr(__FILE__, __LINE__, "could not get data type"); + } + // Using H5T_get_native_type API + hid_t memtype = H5Tget_native_type(dtype, H5T_DIR_ASCEND); + if (memtype < 0) { + H5Tclose(dtype); + throw InternalErr(__FILE__, __LINE__, "could not get memory type"); + } + + hid_t dspace = H5Dget_space(dset); + if (dspace < 0) { + H5Tclose(dtype); + H5Tclose(memtype); + throw InternalErr(__FILE__, __LINE__, "could not get data space"); + } + + + vectordyn_count; + vectordyn_step; + vectordyn_offset; + dyn_count.resize(num_dim); + dyn_step.resize(num_dim); + dyn_offset.resize(num_dim); + + for (int i = 0; i < num_dim; i++) { + dyn_count[i] = (hsize_t) (*count); + dyn_step[i] = (hsize_t) (*step); + dyn_offset[i] = (hssize_t) (*offset); + BESDEBUG("h5", + "count:" << dyn_count[i] + << " step:" << dyn_step[i] + << " offset:" << dyn_step[i] + << endl); + count++; + step++; + offset++; + } + + if (H5Sselect_hyperslab(dspace, H5S_SELECT_SET, + (const hsize_t *)dyn_offset.data(), dyn_step.data(), + dyn_count.data(), nullptr) < 0) { + H5Tclose(dtype); + H5Tclose(memtype); + H5Sclose(dspace); + throw InternalErr(__FILE__, __LINE__, "could not select hyperslab"); + } + + hid_t memspace = H5Screate_simple(num_dim, dyn_count.data(), nullptr); + if (memspace < 0) { + H5Tclose(dtype); + H5Tclose(memtype); + H5Sclose(dspace); + throw InternalErr(__FILE__, __LINE__, "could not open space"); + } + + if (H5Dread(dset, memtype, memspace, dspace, H5P_DEFAULT, buf) < 0) { + H5Tclose(dtype); + H5Tclose(memtype); + H5Sclose(dspace); + H5Sclose(memspace); + throw InternalErr(__FILE__, __LINE__, "could not get data"); + } + + if (H5Sclose(dspace) < 0){ + H5Tclose(dtype); + H5Tclose(memtype); + H5Sclose(memspace); + throw InternalErr(__FILE__, __LINE__, "Unable to close the dspace."); + } + if (H5Sclose(memspace) < 0){ + H5Tclose(dtype); + H5Tclose(memtype); + throw InternalErr(__FILE__, __LINE__, "Unable to close the memspace."); + } + if (H5Tclose(dtype) < 0){ + H5Tclose(memtype); + throw InternalErr(__FILE__, __LINE__, "Unable to close the dtype."); + } + + if (H5Tclose(memtype) < 0){ + throw InternalErr(__FILE__, __LINE__, "Unable to close the memtype."); + } + + BESDEBUG("h5", " &finstrval) +{ + + hid_t dspace = -1; + hid_t mspace = -1; + hid_t dtypeid = -1; + hid_t memtype = -1; + bool is_scalar = false; + + + if ((dspace = H5Dget_space(dsetid))<0) { + throw InternalErr (__FILE__, __LINE__, "Cannot obtain data space."); + } + + if(H5S_SCALAR == H5Sget_simple_extent_type(dspace)) + is_scalar = true; + + + if (!is_scalar) { + if (H5Sselect_hyperslab(dspace, H5S_SELECT_SET, + hoffset, hstep, + hcount, nullptr) < 0) { + H5Sclose(dspace); + throw InternalErr (__FILE__, __LINE__, "Cannot generate the hyperslab of the HDF5 dataset."); + } + + int d_num_dim = H5Sget_simple_extent_ndims(dspace); + if(d_num_dim < 0) { + H5Sclose(dspace); + throw InternalErr (__FILE__, __LINE__, "Cannot obtain the number of dimensions of the data space."); + } + + mspace = H5Screate_simple(d_num_dim, hcount,nullptr); + if (mspace < 0) { + H5Sclose(dspace); + throw InternalErr (__FILE__, __LINE__, "Cannot create the memory space."); + } + } + + + if ((dtypeid = H5Dget_type(dsetid)) < 0) { + + if (!is_scalar) + H5Sclose(mspace); + H5Sclose(dspace); + throw InternalErr (__FILE__, __LINE__, "Cannot obtain the datatype."); + + } + + if ((memtype = H5Tget_native_type(dtypeid, H5T_DIR_ASCEND))<0) { + + if (!is_scalar) + H5Sclose(mspace); + H5Tclose(dtypeid); + H5Sclose(dspace); + throw InternalErr (__FILE__, __LINE__, "Fail to obtain memory datatype."); + + } + + size_t ty_size = H5Tget_size(memtype); + + vector strval; + strval.resize(nelms*ty_size); + hid_t read_ret = -1; + if (is_scalar) + read_ret = H5Dread(dsetid, + memtype, + H5S_ALL, + H5S_ALL, + H5P_DEFAULT, + (void*)strval.data()); + else + read_ret = H5Dread(dsetid, + memtype, + mspace, + dspace, + H5P_DEFAULT, + (void*)strval.data()); + + if (read_ret < 0) { + if (!is_scalar) + H5Sclose(mspace); + H5Tclose(memtype); + H5Tclose(dtypeid); + H5Sclose(dspace); + throw InternalErr (__FILE__, __LINE__, "Fail to read the HDF5 variable length string dataset."); + } + +#if 0 + // For scalar, nelms is 1. + char *temp_bp = strval.data(); + for (int i =0;i &strval, vector&finstrval, size_t ty_size ) { + // For scalar, nelms is 1. + const char *temp_bp = strval.data(); + for (int i =0;i &strval, + bool is_scalar) { + + if (false == strval.empty()) { + herr_t ret_vlen_claim; + if (true == is_scalar) + ret_vlen_claim = H5Dvlen_reclaim(memtype,dspace,H5P_DEFAULT,(void*)strval.data()); + else + ret_vlen_claim = H5Dvlen_reclaim(memtype,mspace,H5P_DEFAULT,(void*)strval.data()); + if (ret_vlen_claim < 0){ + if (false == is_scalar) + H5Sclose(mspace); + H5Tclose(memtype); + H5Tclose(dtypeid); + H5Sclose(dspace); + throw InternalErr (__FILE__, __LINE__, "Cannot reclaim the memory buffer of the HDF5 variable length string."); + + } + } +} +bool promote_char_to_short(H5T_class_t type_cls, hid_t type_id) { + + bool ret_value = false; + if(type_cls == H5T_INTEGER) { + size_t size = H5Tget_size(type_id); + int sign = H5Tget_sign(type_id); + if(size == 1 && sign == H5T_SGN_2) + ret_value = true; + } + + return ret_value; + +} + +void get_vlen_str_data(const char*temp_bp,string &finalstr_val) { + + const char *onestring = *(const char**)temp_bp; + if(onestring!=nullptr ) + finalstr_val =string(onestring); + else // We will add a nullptr is onestring is nullptr. + finalstr_val=""; + +} diff --git a/retired/modules/dmrpp_module/writer/h5common.h b/retired/modules/dmrpp_module/writer/h5common.h new file mode 100644 index 0000000000..6c38620ec0 --- /dev/null +++ b/retired/modules/dmrpp_module/writer/h5common.h @@ -0,0 +1,56 @@ +// This file is part of hdf5_handler a HDF5 file handler for the OPeNDAP +// data server. + +// Copyright (c) 2007-2023 The HDF Group, Inc. and OPeNDAP, Inc. +// +// This is free software; you can redistribute it and/or modify it under the +// terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 2.1 of the License, or (at your +// option) any later version. +// +// This software is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +// License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. +// You can contact The HDF Group, Inc. at 410 E University Ave, +// Suite 200, Champaign, IL 61820 +//////////////////////////////////////////////////////////////////////////////// +/// \file h5common.h +/// Common helper functions to access HDF5 data for both the CF and the default options. +/// +/// +/// + + +#ifndef _H5COMMON_H +#define _H5COMMON_H +#include +#include +#include + +void get_data(hid_t dset, void *buf); + +int get_slabdata(hid_t dset, const int64_t *, const int64_t *, const int64_t *, const int num_dim, void *); + +void get_strdata(int64_t, char *, char *, int); + +bool read_vlen_string(hid_t d_dset_id, const int64_t nelms, const hsize_t *offset, const hsize_t *step, + const hsize_t *count,std::vector &finstrval); +void read_vlen_string_value(const int64_t nelms, std::vector &strval,std::vector&finstrval, + size_t ty_size); +void claim_vlen_string_memory(hid_t memtype, hid_t dspace, hid_t dtypeid, hid_t mspace, std::vector &strval, + bool is_scalar) ; +void get_vlen_str_data(const char*src,std::string &finalstrval); + + +bool promote_char_to_short(H5T_class_t type_cls, hid_t type_id); + + + +#endif //_H5COMMON_H diff --git a/retired/modules/ngap_module/.gitignore b/retired/modules/ngap_module/.gitignore new file mode 100644 index 0000000000..5208181b25 --- /dev/null +++ b/retired/modules/ngap_module/.gitignore @@ -0,0 +1,12 @@ +/DapRequestHandler.cc.merge.from.stash +/DapRequestHandler.h.merge.from.stash +/dmrpp.conf +/data/mds +/data/mds_ledger.txt + +*.trace +/build_dmrpp + +tests/hyrax_ngap_cache/* +unit-tests/owned-cache/* + diff --git a/retired/modules/ngap_module/Makefile.am b/retired/modules/ngap_module/Makefile.am new file mode 100644 index 0000000000..cd318cd1a7 --- /dev/null +++ b/retired/modules/ngap_module/Makefile.am @@ -0,0 +1,65 @@ +# Automake file for ngap_module +# +# 07/25/18 +# +AUTOMAKE_OPTIONS = foreign + +ACLOCAL_AMFLAGS = -I conf + +# Set the module version here, in the spec file and in configure.ac +M_NAME=ngap_module +M_VER=1.1.0 + +AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/dispatch -I$(top_srcdir)/dap -I$(top_srcdir)/xmlcommand \ +-I$(top_srcdir)/http $(DAP_CFLAGS) +LIBADD = $(BES_DISPATCH_LIB) $(BES_HTTP_LIB) $(DAP_SERVER_LIBS) $(DAP_CLIENT_LIBS) + +AM_CPPFLAGS += -DMODULE_NAME=\"$(M_NAME)\" -DMODULE_VERSION=\"$(M_VER)\" + +AM_CXXFLAGS= +AM_LDFLAGS = +include $(top_srcdir)/coverage.mk + +SUBDIRS = . unit-tests tests + +lib_besdir=$(libdir)/bes + +lib_bes_LTLIBRARIES = libngap_module.la +libngap_module_la_SOURCES = $(NGAP_SRC) $(NGAP_HDR) +libngap_module_la_LDFLAGS = -avoid-version -module +libngap_module_la_LIBADD = $(LIBADD) + +NGAP_SRC = NgapRequestHandler.cc \ + NgapModule.cc \ + NgapOwnedContainer.cc \ + NgapOwnedContainerStorage.cc \ + NgapApi.cc + +# MemoryCache.cc NgapContainer.cc NgapContainerStorage.cc + +NGAP_HDR = NgapNames.h \ + NgapRequestHandler.h \ + NgapModule.h \ + NgapOwnedContainer.h \ + NgapOwnedContainerStorage.h \ + NgapApi.h \ + MemoryCache.h + +# NgapContainer.h NgapContainerStorage.h + +EXTRA_DIST = ngap.conf.in + +CLEANFILES = *~ ngap.conf + +moduledir = $(sysconfdir)/bes/modules +module_DATA = ngap.conf + +ngap.conf: ngap.conf.in $(top_builddir)/config.status + sed -e "s%[@]bes_modules_dir[@]%${lib_besdir}%" $< > ngap.conf + +C4_DIR=./cccc +.PHONY: cccc +cccc: + cccc --outdir=$(C4_DIR) $(NGAP_SRC) $(NGAP_HDR) + + diff --git a/retired/modules/ngap_module/MemoryCache.h b/retired/modules/ngap_module/MemoryCache.h new file mode 100644 index 0000000000..8412241855 --- /dev/null +++ b/retired/modules/ngap_module/MemoryCache.h @@ -0,0 +1,171 @@ +// -*- mode: c++; c-basic-offset:4 -*- + +// This file is part of ngap_module, A C++ module that can be loaded in to +// the OPeNDAP Back-End Server (BES) and is able to handle remote requests. + +// Copyright (c) 2023 OPeNDAP, Inc. +// Author: James Gallagher +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. + +// +// Created by James Gallagher on 10/16/23. +// + +#ifndef BES_MEMORYCACHE_H +#define BES_MEMORYCACHE_H + +#include +#include +#include + +#ifndef BESInternalError_h_ +#include "BESInternalError.h" +#endif + +namespace ngap { + +/** + * @brief A simple memory cache. + * + * This is a header-only class. It is used by NgapRequestHandler to cache + * string values. It could be tested more completely and used in other places. + * + * The cache implements a simple FIFO queue to purge the oldest entries when + * the cache is full. Purging is done when the count of cached items exceeds + * the maximum number of items allowed in the cache. The private purge method + * will remove the oldest P entries from the cache where P is the number of + * 'purge items' as set with the initialize() method. + * + * Instead of initializing the cache (setting the max and purge item counts) + * using a constructor, am initialize() method is used. The constructors never + * throw exceptions. If initialize() fails, it returns false. The get() and put() + * methods may throw exceptions. + * + * The cache is not thread-safe. + * + * @tparam VALUE As of 10/17/23 only tested with std::string + */ +template +class MemoryCache { + unsigned int d_max_items = 100; //< Max number of items to cache (not bytes, but items) + unsigned int d_purge_items = 20; //< When purging, remove this many items + + std::deque d_fifo_keys; //< FIFO queue of keys; used by purge() + std::unordered_map d_cache; + + /// Purge the cache of the oldest entries. + void purge() { + // if number of elements > threshold, purge + for (int entries = 0; entries < d_purge_items; ++entries) { + std::string key = d_fifo_keys.front(); + + d_cache.erase(d_cache.find(key)); + d_fifo_keys.pop_front(); + } + } + + /// Check the cache for consistency. + bool invariant(bool expensive = true) const { + if (d_cache.size() > d_max_items) + return false; + if (d_fifo_keys.size() > d_max_items) + return false; + if (d_cache.size() != d_fifo_keys.size()) + return false; + + if (expensive) { + // check that the keys in the queue are also in the map + for (const auto &key : d_fifo_keys) { + if (d_cache.find(key) == d_cache.end()) + return false; + } + } + + return true; + } + + friend class MemoryCacheTest; + +public: + MemoryCache() = default; // this makes testing easier + MemoryCache(const MemoryCache *src) = delete; + + virtual ~MemoryCache() = default; + MemoryCache &operator=(const MemoryCache *src) = delete; + + /** + * @brief Initialize the cache. + * @param max_items Must be greater than zero + * @param purge_items Must be greater than zero + * @return Return True if the cache was initialized, false otherwise. + */ + virtual bool initialize(int max_items, int purge_items) { + if (max_items <= 0 || purge_items <= 0) + return false; + + d_max_items = (unsigned int)max_items; + d_purge_items = (unsigned int)purge_items; + return true; + } + + /** + * @brief Get the item from the cache. + * If the item is not in the cache, the value-result parameter is not modified. + * @param key + * @param value Value-result parameter; operator=() is used to copy the value of the cached item. + * @return Return True if the item is in the cache, false otherwise. + */ + virtual bool get(const std::string &key, VALUE &value) { + if (d_cache.find(key) != d_cache.end()) { + value = d_cache[key]; + return true; + } + else { + return false; + } + } + + /** + * @brief Put the item in the cache. + * If the key is already in the cache, the value is updated. + * @param key + * @param value + */ + virtual void put(const std::string &key, const VALUE &value) { + // add key, value to the queue of entries if key is not in the cache + // add or overwrite/update the value associated with key + if (d_cache.find(key) == d_cache.end()) { + d_cache.insert(std::pair(key, value)); + d_fifo_keys.push_back(key); + if (d_cache.size() > d_max_items) + purge(); + } + else + d_cache[key] = value; + } + + /// @brief How many items are in the cache + virtual unsigned long size() const { return d_cache.size(); } + + /// @brief Clear the cache + virtual void clear() { d_cache.clear(); d_fifo_keys.clear(); } +}; + +} // ngap + +#endif //BES_MEMORYCACHE_H diff --git a/retired/modules/ngap_module/NgapApi.cc b/retired/modules/ngap_module/NgapApi.cc new file mode 100644 index 0000000000..7aa3cc0cf6 --- /dev/null +++ b/retired/modules/ngap_module/NgapApi.cc @@ -0,0 +1,526 @@ +// -*- mode: c++; c-basic-offset:4 -*- + +// This file is part of ngap_module, A C++ module that can be loaded in to +// the OPeNDAP Back-End Server (BES) and is able to handle remote requests. + +// Copyright (c) 2020 OPeNDAP, Inc. +// Author: Nathan Potter +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. + +#include "config.h" + +#include +#include + +#include +#include "rapidjson/document.h" + +#include "BESNotFoundError.h" +#include "BESSyntaxUserError.h" +#include "BESInternalError.h" +#include "BESDebug.h" +#include "BESUtil.h" +#include "TheBESKeys.h" +#include "CurlUtils.h" +#include "HttpError.h" + +#include "NgapApi.h" +#include "NgapNames.h" + +using namespace std; + +#define prolog string("NgapApi::").append(__func__).append("() - ") + +namespace ngap { + +const unsigned int REFRESH_THRESHOLD = 3600; // An hour + +/** + * @brief Get the CMR search endpoint URL using information from the BES Keys. + * This method only reads the BES keys once and caches the results, including + * the assembled URL. + * @return The URL used to access CMR. + */ +std::string NgapApi::get_cmr_search_endpoint_url() { + static string cmr_search_endpoint_url; + if (cmr_search_endpoint_url.empty()) { + string cmr_hostname = TheBESKeys::TheKeys()->read_string_key(NGAP_CMR_HOSTNAME_KEY, DEFAULT_CMR_ENDPOINT_URL); + string cmr_search_endpoint_path = TheBESKeys::TheKeys()->read_string_key(NGAP_CMR_SEARCH_ENDPOINT_PATH_KEY, + DEFAULT_CMR_SEARCH_ENDPOINT_PATH); + cmr_search_endpoint_url = BESUtil::assemblePath(cmr_hostname, cmr_search_endpoint_path); + } + + return cmr_search_endpoint_url; +} + +/** + * @brief Converts an NGAP restified path into the corresponding CMR query URL. + * + * @param restified_path The restified path to convert + * @return The CMR query URL that will return the granules.umm_json_v1_4 from CMR for the + * granule specified in the restified path. + */ +std::string NgapApi::build_cmr_query_url_old_rpath_format(const std::string &restified_path) { + + // Make sure it starts with a '/' (see key strings above) + string r_path = (restified_path[0] != '/' ? "/" : "") + restified_path; + + size_t provider_index = r_path.find(NGAP_PROVIDERS_KEY); + if (provider_index == string::npos) { + stringstream msg; + msg << prolog << "The specified path '" << r_path << "'"; + msg << " does not contain the required path element '" << NGAP_PROVIDERS_KEY << "'"; + throw BESSyntaxUserError(msg.str(), __FILE__, __LINE__); + } + if (provider_index != 0) { + stringstream msg; + msg << prolog << "The specified path '" << r_path << "'"; + msg << " has the path element '" << NGAP_PROVIDERS_KEY << "' located in the incorrect position ("; + msg << provider_index << ") expected 0."; + throw BESSyntaxUserError(msg.str(), __FILE__, __LINE__); + } + provider_index += string(NGAP_PROVIDERS_KEY).size(); + + bool use_collection_concept_id = false; + size_t collection_index = r_path.find(NGAP_COLLECTIONS_KEY); + if (collection_index == string::npos) { + size_t concepts_index = r_path.find(NGAP_CONCEPTS_KEY); + if (concepts_index == string::npos) { + stringstream msg; + msg << prolog << "The specified path '" << r_path << "'"; + msg << " contains neither the '" << NGAP_COLLECTIONS_KEY << "'"; + msg << " nor the '" << NGAP_CONCEPTS_KEY << "'"; + msg << " key, one must be provided."; + throw BESSyntaxUserError(msg.str(), __FILE__, __LINE__); + } + collection_index = concepts_index; + use_collection_concept_id = true; + } + if (collection_index <= provider_index + 1) { // The value of provider has to be at least 1 character + stringstream msg; + msg << prolog << "The specified path '" << r_path << "'"; + msg << " has the path element '" << (use_collection_concept_id ? NGAP_CONCEPTS_KEY : NGAP_COLLECTIONS_KEY) + << "' located in the incorrect position ("; + msg << collection_index << ") expected at least " << provider_index + 1; + throw BESSyntaxUserError(msg.str(), __FILE__, __LINE__); + } + string provider = r_path.substr(provider_index, collection_index - provider_index); + collection_index += use_collection_concept_id ? string(NGAP_CONCEPTS_KEY).size() : string( + NGAP_COLLECTIONS_KEY).size(); + + size_t granule_index = r_path.find(NGAP_GRANULES_KEY); + if (granule_index == string::npos) { + stringstream msg; + msg << prolog << "The specified path '" << r_path << "'"; + msg << " does not contain the required path element '" << NGAP_GRANULES_KEY << "'"; + throw BESSyntaxUserError(msg.str(), __FILE__, __LINE__); + } + if (granule_index <= collection_index + 1) { // The value of collection must have at least one character. + stringstream msg; + msg << prolog << "The specified path '" << r_path << "'"; + msg << " has the path element '" << NGAP_GRANULES_KEY << "' located in the incorrect position ("; + msg << granule_index << ") expected at least " << collection_index + 1; + throw BESSyntaxUserError(msg.str(), __FILE__, __LINE__); + } + string collection = r_path.substr(collection_index, granule_index - collection_index); + granule_index += string(NGAP_GRANULES_KEY).size(); + + // The granule value is the path terminus so it's every thing after the key + string granule = r_path.substr(granule_index); + + // Build the CMR query URL for the dataset + string cmr_url = get_cmr_search_endpoint_url() + "?"; + { + // This easy handle is only created so we can use the curl_easy_escape() on the token values + CURL *ceh = curl_easy_init(); + char *esc_url_content; + + // Add provider + esc_url_content = curl_easy_escape(ceh, provider.c_str(), provider.size()); + cmr_url += string(CMR_PROVIDER).append("=").append(esc_url_content).append("&"); + curl_free(esc_url_content); + + esc_url_content = curl_easy_escape(ceh, collection.c_str(), collection.size()); + if (use_collection_concept_id) { + // Add collection_concept_id + cmr_url += string(CMR_COLLECTION_CONCEPT_ID).append("=").append(esc_url_content).append("&"); + } else { + // Add entry_title + cmr_url += string(CMR_ENTRY_TITLE).append("=").append(esc_url_content).append("&"); + + } + curl_free(esc_url_content); + + esc_url_content = curl_easy_escape(ceh, granule.c_str(), granule.size()); + cmr_url += string(CMR_GRANULE_UR).append("=").append(esc_url_content); + curl_free(esc_url_content); + + curl_easy_cleanup(ceh); + } + + return cmr_url; +} + +/** + * @brief Converts an NGAP restified path into the corresponding CMR query URL. + * + * There are two mandatory and one optional query parameters in the URL + * MANDATORY: " /collections/UMM-C:{concept-id} " + * OPTIONAL: "/UMM-C:{ShortName} '.' UMM-C:{Version} " + * MANDATORY: "/granules/UMM-G:{GranuleUR}" + * Example: + * https://opendap.earthdata.nasa.gov/collections/C1443727145-LAADS/MOD08_D3.v6.1/granules/MOD08_D3.A2020308.061.2020309092644.hdf.nc + * + * More Info Here: https://wiki.earthdata.nasa.gov/display/DUTRAIN/Feature+analysis%3A+Restified+URL+for+OPENDAP+Data+Access + * + * @param restified_path The restified path to convert + * @return The CMR query URL that will return the granules.umm_json_v1_4 from CMR for the + * granule specified in the restified path. + */ +std::string NgapApi::build_cmr_query_url(const std::string &restified_path) { + + // Make sure it starts with a '/' (see key strings above) + string r_path = (restified_path[0] != '/' ? "/" : "") + restified_path; + + size_t provider_index = r_path.find(NGAP_PROVIDERS_KEY); + if (provider_index != string::npos) { + return build_cmr_query_url_old_rpath_format(restified_path); + } + + size_t collections_key_index = r_path.find(NGAP_COLLECTIONS_KEY); + if (collections_key_index == string::npos) { + stringstream msg; + msg << prolog << "The specified path '" << r_path << "'"; + msg << " contains neither the '" << NGAP_COLLECTIONS_KEY << "'"; + msg << " nor the '" << NGAP_CONCEPTS_KEY << "'"; + msg << " one must be provided."; + throw BESSyntaxUserError(msg.str(), __FILE__, __LINE__); + } + if (collections_key_index != 0) { // The COLLECTIONS_KEY comes first + stringstream msg; + msg << prolog << "The specified path '" << r_path << "'"; + msg << " has the path element '" << NGAP_COLLECTIONS_KEY << "' located in the incorrect position ("; + msg << collections_key_index << ") expected at least " << provider_index + 1; + throw BESSyntaxUserError(msg.str(), __FILE__, __LINE__); + } + // This is now the beginning of the collection_concept_id value. + size_t collections_index = collections_key_index + string(NGAP_COLLECTIONS_KEY).size(); + + size_t granules_key_index = r_path.find(NGAP_GRANULES_KEY); + if (granules_key_index == string::npos) { + stringstream msg; + msg << prolog << "The specified path '" << r_path << "'"; + msg << " does not contain the required path element '" << NGAP_GRANULES_KEY << "'"; + throw BESSyntaxUserError(msg.str(), __FILE__, __LINE__); + } + + // The collection key must precede the granules key in the path, + // and the collection name must have at least one character. + if (granules_key_index <= collections_index + 1) { + stringstream msg; + msg << prolog << "The specified path '" << r_path << "'"; + msg << " has the path element '" << NGAP_GRANULES_KEY << "' located in the incorrect position ("; + msg << granules_key_index << ") expected at least " << collections_index + 1; + throw BESSyntaxUserError(msg.str(), __FILE__, __LINE__); + } + size_t granules_index = granules_key_index + string(NGAP_GRANULES_KEY).size(); + // The granule_name value is the path terminus so it's every thing after the key + string granule_name = r_path.substr(granules_index); + + // Now we need to work on the collections value to eliminate the optional parts. + // This is the entire collections string including any optional components. + string collection_name = r_path.substr(collections_index, granules_key_index - collections_index); + + // Since there may be optional parameters we need to strip them off to get the collection_concept_id + // And, since we know that collection_concept_id will never contain a '/', and we know that the optional + // part is separated from the collection_concept_id by a '/' we look for that and of we find it we truncate + // the value at that spot. + string optional_part; + size_t slash_pos = collection_name.find('/'); + if (slash_pos != string::npos) { + optional_part = collection_name.substr(slash_pos); + BESDEBUG(MODULE, prolog << "Found optional collections name component: " << optional_part << endl); + collection_name = collection_name.substr(0, slash_pos); + } + BESDEBUG(MODULE, prolog << "Found collection_name (aka collection_concept_id): " << collection_name << endl); + + // Build the CMR query URL for the dataset + string cmr_url = get_cmr_search_endpoint_url() + "?"; + { + // This easy handle is only created so we can use the curl_easy_escape() on the token values + CURL *ceh = curl_easy_init(); + char *esc_url_content; + + esc_url_content = curl_easy_escape(ceh, collection_name.c_str(), collection_name.size()); + cmr_url += string(CMR_COLLECTION_CONCEPT_ID).append("=").append(esc_url_content).append("&"); + curl_free(esc_url_content); + + esc_url_content = curl_easy_escape(ceh, granule_name.c_str(), granule_name.size()); + cmr_url += string(CMR_GRANULE_UR).append("=").append(esc_url_content); + curl_free(esc_url_content); + + curl_easy_cleanup(ceh); + } + return cmr_url; +} + +/** + * @brief Locates the "GET DATA" URL for a granule in the granules.umm_json_v1_4 document. + * + * A single granule query is built by convert_restified_path_to_cmr_query_url() from the + * NGAP API restified path. This method will parse the CMR response to the query and extract the + * granule's "GET DATA" URL and return it. + * + * @note This method uses a heuristic to get an HTTPS URL to the granule from the CMR UMM-G + * JSON. The process it follows is, look in the RelatedUrls array for an entry with a + * 1. A TYPE of Type 'GET DATA' with a URL that uses the https:// protocol where that URL does + * not end in 'xml'. The latter characteristic was added for records added by LPDAAC. jhrg 5/22/24 + * + * @param rest_path The REST path used to form the CMR query (only used for error messages) + * @param cmr_granules The CMR response (granules.umm_json_v1_4) to evaluate + * @return The "GET DATA" URL for the granule. + */ +std::string NgapApi::find_get_data_url_in_granules_umm_json_v1_4(const std::string &rest_path, + rapidjson::Document &cmr_granule_response) { + const rapidjson::Value &val = cmr_granule_response["hits"]; + int hits = val.GetInt(); + if (hits < 1) { + throw BESNotFoundError(string("The specified path '") + rest_path + + "' does not identify a granule in CMR.", __FILE__, __LINE__); + } + + rapidjson::Value &items = cmr_granule_response["items"]; + if (!items.IsArray()) { + throw BESInternalError(string("ERROR! The CMR response did not contain the data URL information: ") + + rest_path, __FILE__, __LINE__); + } else { + // Search the items array for the first item that contains a RelatedUrls array + if (BESISDEBUG(MODULE)) { + stringstream ss; + const string RJ_TYPE_NAMES[] = {string("kNullType"), string("kFalseType"), string("kTrueType"), + string("kObjectType"), string("kArrayType"), string("kStringType"), + string("kNumberType")}; + for (rapidjson::SizeType i = 0; i < items.Size(); i++) // Uses SizeType instead of size_t + ss << "items[" << i << "]: " << RJ_TYPE_NAMES[items[i].GetType()] << endl; + BESDEBUG(MODULE, prolog << "items size: " << items.Size() << endl << ss.str() << endl); + } + + rapidjson::Value &items_obj = items[0]; + auto mitr = items_obj.FindMember("umm"); + + rapidjson::Value &umm = mitr->value; + mitr = umm.FindMember("RelatedUrls"); + if (mitr == umm.MemberEnd()) { + throw BESInternalError("Error! The umm/RelatedUrls object was not located!", __FILE__, __LINE__); + } + + rapidjson::Value &related_urls = mitr->value; + + if (!related_urls.IsArray()) { + throw BESNotFoundError("Error! The RelatedUrls object in the CMR response is not an array!", __FILE__, + __LINE__); + } + + BESDEBUG(MODULE, prolog << " Found RelatedUrls array in CMR response." << endl); + + string data_access_url; + for (rapidjson::SizeType i = 0; i < related_urls.Size() && data_access_url.empty(); i++) { + rapidjson::Value &obj = related_urls[i]; + mitr = obj.FindMember("URL"); + if (mitr == obj.MemberEnd()) { + stringstream err; + err << "Error! The umm/RelatedUrls[" << i << "] does not contain the URL object"; + throw BESInternalError(err.str(), __FILE__, __LINE__); + } + + const rapidjson::Value &r_url = mitr->value; + + mitr = obj.FindMember("Type"); + if (mitr == obj.MemberEnd()) { + stringstream err; + err << "Error! The umm/RelatedUrls[" << i << "] does not contain the Type object"; + throw BESInternalError(err.str(), __FILE__, __LINE__); + } + + const rapidjson::Value &r_type = mitr->value; + + bool noSubtype = obj.FindMember("Subtype") == obj.MemberEnd(); + + BESDEBUG(MODULE, prolog << "RelatedUrl Object:" << + " URL: '" << r_url.GetString() << "'" << + " Type: '" << r_type.GetString() << "'" << + " SubType: '" << (noSubtype ? "Absent" : "Present") << "'" << endl); + + if ((r_type.GetString() == string(CMR_URL_TYPE_GET_DATA)) && noSubtype) { + + // Because a member of RelatedUrls may contain a URL of Type GET DATA with the s3:// protocol + // as well as a Type GET DATA URL which uses https:// or http:// + // Added test that the URL does not end in 'xml' to avoid the LPDAAC .cmr.xml records. jhrg 5/22/24 + string candidate_url = r_url.GetString(); + + if ((candidate_url.rfind("https://", 0) == 0 || candidate_url.rfind("http://", 0) == 0) + && candidate_url.find(".xml", candidate_url.size()-5) == string::npos) { + data_access_url = candidate_url; + } + } + } + + if (data_access_url.empty()) { + throw BESInternalError(string("ERROR! Failed to locate a data access URL for the path: ") + rest_path, + __FILE__, __LINE__); + } + + return data_access_url; + } +} + +/** + * @brief Converts an NGAP restified granule path into a CMR metadata query for the granule. + * + * The NGAP module's "restified" interface utilizes a google-esque set of + * ordered key value pairs using the "/" character as field separator. + * + * The NGAP container the "restified_path" will follow the template: + * + * provider/daac_name/datasets/collection_name/granules/granule_name(s?) + * + * Where "provider", "datasets", and "granules" are NGAP keys and + * "ddac_name", "collection_name", and "granule_name" the their respective values. + * + * For example, "provider/GHRC_CLOUD/datasets/ACES_CONTINUOUS_DATA_V1/granules/aces1cont.nc" + * + * https://cmr.earthdata.nasa.gov/search/granules.umm_json_v1_4? + * provider=GHRC_CLOUD &entry_title=ACES_CONTINUOUS_DATA_V1 &native_id=aces1cont.nc + * provider=GHRC_CLOUD &entry_title=ACES CONTINUOUS DATA V1 &native_id=aces1cont_2002.191_v2.50.tar + * provider=GHRC_CLOUD &native_id=olslit77.nov_analog.hdf &pretty=true + * + * @param restified_path The name to decompose. + */ +string NgapApi::convert_ngap_resty_path_to_data_access_url(const std::string &restified_path) { + BESDEBUG(MODULE, prolog << "BEGIN" << endl); + string data_access_url; + + string cmr_query_url = build_cmr_query_url(restified_path); + + BESDEBUG(MODULE, prolog << "CMR Request URL: " << cmr_query_url << endl); + + string cmr_json_string; + try { + curl::http_get(cmr_query_url, cmr_json_string); + } + catch (http::HttpError &http_error) { + string err_msg = prolog + "Hyrax encountered a Service Chaining Error while " + "attempting to retrieve a CMR record. " + http_error.get_message(); + http_error.set_message(err_msg); + throw; + } + + rapidjson::Document cmr_response; + cmr_response.Parse(cmr_json_string.c_str()); + data_access_url = find_get_data_url_in_granules_umm_json_v1_4(restified_path, cmr_response); + + BESDEBUG(MODULE, prolog << "END (data_access_url: " << data_access_url << ")" << endl); + + return data_access_url; +} + +/** + * @brief Has the signed S3 URL expired? + * If neither the CloudFront Expires header nor the AWS Expires header are present, then + * this function returns true. + * @note This function is ony used in unit tests (jhrg 10/16/23) + * @param signed_url + * @return True if the signed URL has expired, false otherwise. + * @todo Remove this since it is only used by tests and duplicates http::url::is_expired(). jhrg 10/18/23 + * @see http::url::is_expired() + */ +bool NgapApi::signed_url_is_expired(const http::url &signed_url) { + bool is_expired; + time_t now; + time(&now); /* get current time; same as: timer = time(NULL) */ + BESDEBUG(MODULE, prolog << "now: " << now << endl); + + time_t expires = now; + string cf_expires = signed_url.query_parameter_value(CLOUDFRONT_EXPIRES_HEADER_KEY); + string aws_expires = signed_url.query_parameter_value(AMS_EXPIRES_HEADER_KEY); + time_t ingest_time = signed_url.ingest_time(); + + // If both cf_expires and aws_expires are empty, this code returns true. jhrg 10/13/23 + if (!cf_expires.empty()) { // CloudFront expires header? + expires = stoll(cf_expires); + BESDEBUG(MODULE, prolog << "Using " << CLOUDFRONT_EXPIRES_HEADER_KEY << ": " << expires << endl); + } else if (!aws_expires.empty()) { + // AWS Expires header? + // + // By default we'll use the time we made the URL object, ingest_time + time_t start_time = ingest_time; + // But if there's an AWS Date we'll parse that and compute the time + string aws_date = signed_url.query_parameter_value(AWS_DATE_HEADER_KEY); + if (!aws_date.empty()) { + string year = aws_date.substr(0, 4); + string month = aws_date.substr(4, 2); + string day = aws_date.substr(6, 2); + string hour = aws_date.substr(9, 2); + string minute = aws_date.substr(11, 2); + string second = aws_date.substr(13, 2); + + BESDEBUG(MODULE, prolog << "date: " << aws_date << + " year: " << year << " month: " << month << " day: " << day << + " hour: " << hour << " minute: " << minute << " second: " << second << endl); + + struct tm ti{}; // NB: Calling gmtime_r() is an initialization hack since some fields are not set here. + if (gmtime_r(&now, &ti) == nullptr) + throw BESInternalError("Could not get the current time, gmtime_r() failed!", __FILE__, __LINE__); + ti.tm_year = stoi(year) - 1900; + ti.tm_mon = stoi(month) - 1; + ti.tm_mday = stoi(day); + ti.tm_hour = stoi(hour); + ti.tm_min = stoi(minute); + ti.tm_sec = stoi(second); + + BESDEBUG(MODULE, prolog << "ti.tm_year: " << ti.tm_year << + " ti.tm_mon: " << ti.tm_mon << + " ti.tm_mday: " << ti.tm_mday << + " ti.tm_hour: " << ti.tm_hour << + " ti.tm_min: " << ti.tm_min << + " ti.tm_sec: " << ti.tm_sec << endl); + + start_time = mktime(&ti); + BESDEBUG(MODULE, prolog << "AWS (computed) start_time: " << start_time << endl); + } + + expires = start_time + stoll(aws_expires); + BESDEBUG(MODULE, prolog << "Using " << AMS_EXPIRES_HEADER_KEY << ": " << aws_expires << + " (expires: " << expires << ")" << endl); + } + + // If both cf_expires and aws_expires are empty, 'expires' == 'now' and 'remaining' is 0 so + // this code returns true. jhrg 10/13/23 + time_t remaining = expires - now; + BESDEBUG(MODULE, prolog << "expires_time: " << expires << + " remaining_time: " << remaining << + " refresh_threshold: " << REFRESH_THRESHOLD << endl); + + is_expired = remaining < REFRESH_THRESHOLD; + BESDEBUG(MODULE, prolog << "is_expired: " << (is_expired ? "true" : "false") << endl); + + return is_expired; +} + +} // namespace ngap + diff --git a/retired/modules/ngap_module/NgapApi.h b/retired/modules/ngap_module/NgapApi.h new file mode 100644 index 0000000000..6673ad2ed8 --- /dev/null +++ b/retired/modules/ngap_module/NgapApi.h @@ -0,0 +1,70 @@ +// -*- mode: c++; c-basic-offset:4 -*- + +// This file is part of ngap_module, A C++ module that can be loaded in to +// the OPeNDAP Back-End Server (BES) and is able to handle remote requests. + +// Copyright (c) 2020 OPeNDAP, Inc. +// Author: Nathan Potter +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. + +/* + * NgapApi.h + * + * Created on: July, 13 2018 + * Author: ndp + */ + +#ifndef MODULES_NGAP_MODULE_NGAPAPI_H_ +#define MODULES_NGAP_MODULE_NGAPAPI_H_ + +#include +#include +#include + +#include "rapidjson/document.h" + +namespace http { +class url; +} + +namespace ngap { + +class NgapApi { +private: + static std::string get_cmr_search_endpoint_url(); + static std::string find_get_data_url_in_granules_umm_json_v1_4(const std::string &rest_path, + rapidjson::Document &cmr_granule_response); + static std::string build_cmr_query_url(const std::string &restified_path); + static std::string build_cmr_query_url_old_rpath_format(const std::string &restified_path); + + friend class NgapApiTest; + +public: + NgapApi() = default; + ~NgapApi() = default; + NgapApi(const NgapApi &other) = delete; + NgapApi &operator=(const NgapApi &other) = delete; + + static std::string convert_ngap_resty_path_to_data_access_url(const std::string &restified_path); + + static bool signed_url_is_expired(const http::url &signed_url) ; +}; + +} // namespace ngap + +#endif /* MODULES_NGAP_MODULE_NGAPAPI_H_ */ diff --git a/retired/modules/ngap_module/NgapModule.cc b/retired/modules/ngap_module/NgapModule.cc new file mode 100644 index 0000000000..eb7e4bb465 --- /dev/null +++ b/retired/modules/ngap_module/NgapModule.cc @@ -0,0 +1,85 @@ +// -*- mode: c++; c-basic-offset:4 -*- + +// This file is part of ngap_module, A C++ module that can be loaded in to +// the OPeNDAP Back-End Server (BES) and is able to handle remote requests. + +// Copyright (c) 2020 OPeNDAP, Inc. +// Author: Nathan Potter +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. + + +#include "config.h" + +#include +#include +#include + +#include +#include +#include + +#include "NgapModule.h" +#include "NgapRequestHandler.h" +#include "NgapOwnedContainerStorage.h" + +using namespace std; +using namespace ngap; + +void NgapModule::initialize(const string &modname) +{ + BESDEBUG(modname, "Initializing NGAP Module " << modname << endl); + + BESDEBUG(modname, " adding " << modname << " request handler" << endl); + BESRequestHandlerList::TheList()->add_handler(modname, new NgapRequestHandler(modname)); + + BESDEBUG(modname, " adding OWNED " << modname << " container storage" << endl); + // FIXME Do NOT merge this code as is since it breaks the handler needed for NGAP. + // This is a POC modification to test access to data using DMR++ documents that + // OPeNDAP 'owns.' jhrg 5/17/24 + BESContainerStorageList::TheList()->add_persistence(new NgapOwnedContainerStorage(modname)); + + BESDEBUG(modname, " adding NGAP debug context" << endl); + BESDebug::Register(modname); + + BESDEBUG(modname, "Done Initializing NGAP Module " << modname << endl); +} + +void NgapModule::terminate(const string &modname) +{ + BESDEBUG(modname, "Cleaning NGAP module " << modname << endl); + + BESDEBUG(modname, " removing " << modname << " request handler" << endl); + BESRequestHandler *rh = BESRequestHandlerList::TheList()->remove_handler(modname); + delete rh; + + BESContainerStorageList::TheList()->deref_persistence(modname); + + BESDEBUG(modname, "Done Cleaning NGAP module " << modname << endl); +} + +void NgapModule::dump(ostream &strm) const +{ + strm << BESIndent::LMarg << "NgapModule::dump - (" << (void *) this << ")" << endl; +} + +extern "C" +BESAbstractModule *maker() +{ + return new NgapModule; +} + diff --git a/retired/modules/ngap_module/NgapModule.h b/retired/modules/ngap_module/NgapModule.h new file mode 100644 index 0000000000..0f1377596a --- /dev/null +++ b/retired/modules/ngap_module/NgapModule.h @@ -0,0 +1,51 @@ +// NgapContainer.cc + +// -*- mode: c++; c-basic-offset:4 -*- + +// This file is part of ngap_module, A C++ module that can be loaded in to +// the OPeNDAP Back-End Server (BES) and is able to handle remote requests. + +// Copyright (c) 2020 OPeNDAP, Inc. +// Author: Nathan Potter +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. +// Authors: +// ndp Nathan Potter + +#ifndef I_NgapModule_H +#define I_NgapModule_H 1 + +#include +#include + +#include "BESAbstractModule.h" + +namespace ngap { + +class NgapModule : public BESAbstractModule { +public: + NgapModule() = default; + ~NgapModule() override = default; + + void initialize(const std::string &modname) override; + void terminate(const std::string &modname) override; + void dump(std::ostream &strm) const override; +}; + +} //namespace ngap + +#endif // I_NgapModule_H diff --git a/retired/modules/ngap_module/NgapNames.h b/retired/modules/ngap_module/NgapNames.h new file mode 100644 index 0000000000..865c3b9c77 --- /dev/null +++ b/retired/modules/ngap_module/NgapNames.h @@ -0,0 +1,74 @@ +// NgapContainer.cc + +// -*- mode: c++; c-basic-offset:4 -*- + +// This file is part of ngap_module, A C++ module that can be loaded in to +// the OPeNDAP Back-End Server (BES) and is able to handle remote requests. + +// Copyright (c) 2020 OPeNDAP, Inc. +// Author: Nathan Potter +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. +// Authors: +// ndp Nathan Potter + +#ifndef E_NgapNames_H +#define E_NgapNames_H 1 + +// This could be a 'global' debug key. jhrg 9/20/23 +constexpr static auto const NGAP_CACHE = "cache"; + +constexpr static auto const NGAP_NAME = "ngap"; +#define MODULE NGAP_NAME + +constexpr static auto const DATA_ACCESS_URL_KEY = "OPeNDAP_DMRpp_DATA_ACCESS_URL"; +constexpr static auto const MISSING_DATA_ACCESS_URL_KEY = "OPeNDAP_DMRpp_SC_DATA_ACCESS_URL"; +constexpr static auto const NGAP_INJECT_DATA_URL_KEY = "NGAP.inject_data_urls"; +constexpr static auto const NGAP_CMR_HOSTNAME_KEY = "NGAP.cmr_host_url"; +constexpr static auto const NGAP_CMR_SEARCH_ENDPOINT_PATH_KEY = "NGAP.cmr_search_endpoint_path"; + +constexpr static auto const NGAP_PROVIDERS_KEY = "/providers/"; +constexpr static auto const NGAP_COLLECTIONS_KEY = "/collections/"; +constexpr static auto const NGAP_CONCEPTS_KEY = "/concepts/"; +constexpr static auto const NGAP_GRANULES_KEY = "/granules/"; + +constexpr static auto const DEFAULT_CMR_ENDPOINT_URL = "https://cmr.earthdata.nasa.gov"; +constexpr static auto const DEFAULT_CMR_SEARCH_ENDPOINT_PATH = "/search/granules.umm_json_v1_4"; +constexpr static auto const CMR_URL_TYPE_GET_DATA = "GET DATA"; + +constexpr static auto const USE_CMR_CACHE = "NGAP.UseCMRCache"; +constexpr static auto const CMR_CACHE_THRESHOLD = "NGAP.CMRCacheSize.Items"; +constexpr static auto const CMR_CACHE_SPACE = "NGAP.CMRCachePurge.Items"; + +constexpr static auto const USE_DMRPP_CACHE = "NGAP.UseDMRppCache"; +constexpr static auto const DMRPP_CACHE_THRESHOLD = "NGAP.DMRppCacheSize.Items"; +constexpr static auto const DMRPP_CACHE_SPACE = "NGAP.DMRppCachePurge.Items"; + +constexpr static auto const DMRPP_FILE_CACHE_THRESHOLD = "NGAP.DMRppFileCacheSize.MB"; // in MB +constexpr static auto const DMRPP_FILE_CACHE_SPACE = "NGAP.DMRppFileCachePurge.MB"; // in MB +constexpr static auto const DMRPP_FILE_CACHE_DIR = "NGAP.DMRppFileCacheDir"; + +constexpr static auto const DATA_SOURCE_LOCATION = "NGAP.DataSourceLocation"; +constexpr static auto const USE_OPENDAP_BUCKET = "NGAP.UseOPeNDAPBucket"; + +// These are used only in NgapApiTest.cc. jhrg 9/28/23 +#define CMR_PROVIDER "provider" +#define CMR_ENTRY_TITLE "entry_title" +#define CMR_COLLECTION_CONCEPT_ID "collection_concept_id" +#define CMR_GRANULE_UR "granule_ur" + +#endif // E_NgapNames_H diff --git a/retired/modules/ngap_module/NgapOwnedContainer.cc b/retired/modules/ngap_module/NgapOwnedContainer.cc new file mode 100644 index 0000000000..c8e6f26b43 --- /dev/null +++ b/retired/modules/ngap_module/NgapOwnedContainer.cc @@ -0,0 +1,486 @@ +// NgapOwnedContainer.cc + +// -*- mode: c++; c-basic-offset:4 -*- + +// This file is part of ngap_module, A C++ module that can be loaded in to +// the OPeNDAP Back-End Server (BES) and is able to handle remote requests. + +// Copyright (c) 2020, 2024 OPeNDAP, Inc. +// Author: Nathan Potter +// James Gallagher +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. +// Authors: +// ndp Nathan Potter +// jhrg James Gallagher + +#include "config.h" + +#include +#include + +#include +#include + +#include "BESContextManager.h" +#include "BESDebug.h" +#include "BESLog.h" +#include "BESStopWatch.h" +#include "BESSyntaxUserError.h" +#include "BESUtil.h" +#include "CurlUtils.h" +#include "HttpError.h" +#include "TheBESKeys.h" + +#include "NgapApi.h" +#include "NgapNames.h" +#include "NgapOwnedContainer.h" +#include "NgapRequestHandler.h" + +#define prolog std::string("NgapOwnedContainer::").append(__func__).append("() - ") +// CACHE_LOG is defined separately from INFO_LOG so that we can turn it off easily. jhrg 11/19/23 +#define CACHE_LOG(x) INFO_LOG(x) + +using namespace std; +using namespace bes; + +namespace ngap { + +// This data source location currently (8/10/24) is a S3 bucket where the DMR++ files are stored +// for the OPeNDAP-owned data used by the tests. jhrg 8/10/24 +std::string NgapOwnedContainer::d_data_source_location = "https://cloudydap.s3.us-east-1.amazonaws.com"; +bool NgapOwnedContainer::d_support_source_prefix = true; +bool NgapOwnedContainer::d_inject_data_url = true; + +/** + * @brief Creates an instances of NgapOwnedContainer with symbolic name and real + * name, which is the remote request. + * + * The real_name is the remote request URL. + * + * @param sym_name symbolic name representing this remote container + * @param real_name The NGAP REST path. + * @throws BESSyntaxUserError if the url does not validate + * @see NgapUtils + */ +NgapOwnedContainer::NgapOwnedContainer(const string &sym_name, const string &real_name, const string &) + : BESContainer(sym_name, real_name, "owned-ngap"), d_ngap_path(real_name) { + NgapOwnedContainer::d_data_source_location = + TheBESKeys::read_string_key(DATA_SOURCE_LOCATION, NgapOwnedContainer::d_data_source_location); + NgapOwnedContainer::d_support_source_prefix = + TheBESKeys::read_bool_key(USE_OPENDAP_BUCKET, NgapOwnedContainer::d_support_source_prefix); + NgapOwnedContainer::d_inject_data_url = + TheBESKeys::read_bool_key(NGAP_INJECT_DATA_URL_KEY, NgapOwnedContainer::d_inject_data_url); +} + +/** + * @brief Read data from a file descriptor into a string. + * @param fd The file descriptor to read from. + * @param content The string to read the data into. + * @return True if all the bytes were read, false otherwise. + */ +bool NgapOwnedContainer::file_to_string(int fd, string &content) { + // The file size is needed later; this doubles as a check that the file in open. + struct stat statbuf = {}; + if (fstat(fd, &statbuf) < 0) { + ERROR_LOG("NgapOwnedContainer::file_to_string() - failed to get file descriptor status\n"); + return false; + } + + // read the data in 4k chunks + vector buffer(4096); + ssize_t bytes_read; + while ((bytes_read = read(fd, buffer.data(), buffer.size())) > 0) { + content.append(buffer.data(), bytes_read); + } + + // did we get it all + if (statbuf.st_size != content.size()) { + ERROR_LOG("NgapOwnedContainer::file_to_string() - failed to read all bytes from file cache\n"); + return false; + } + + return true; +} + +/** + * @brief Set the real name of the container using the CMR or cache. + * + * This uses CMR to translate a REST path to a true NGAP URL for the granule. + * Once this is done, the result is cached in an unordered_map keyed using the the + * REST path and the UID. The REST path is initially the value of the + * real_name property of the Container, but the action of performing the translation + * changes the name of the real_name property to the true NGAP URL. The REST + * path is stored in the d_ngap_path property of the NgapContainer instance. + * + * @note: The cache is global to the NgapRequestHandler class. This is a per-process + * cache and it is not thread-safe. + */ +string NgapOwnedContainer::build_data_url_to_daac_bucket(const string &rest_path) { + BES_MODULE_TIMING(prolog + rest_path); + + bool found; + string uid = BESContextManager::TheManager()->get_context(EDL_UID_KEY, found); + BESDEBUG(MODULE, prolog << "EDL_UID_KEY(" << EDL_UID_KEY << "): " << uid << endl); + + // If using the cache, look there. Note that the UID is part of the key to the cached data. + string url_key = rest_path + ':' + uid; + string data_url; + if (NgapRequestHandler::d_use_cmr_cache) { + if (NgapRequestHandler::d_cmr_mem_cache.get(url_key, data_url)) { + CACHE_LOG(prolog + "CMR Cache hit, translated URL: " + data_url + '\n'); + return data_url; + } else { + CACHE_LOG(prolog + "CMR Cache miss, REST path: " + url_key + '\n'); + } + } + + // Not cached or not using the cache; ask CMR. Throws on lookup failure, HTTP failure. jhrg 1/24/25 + data_url = NgapApi::convert_ngap_resty_path_to_data_access_url(rest_path); + + // If using the CMR cache, cache the response. + if (NgapRequestHandler::d_use_cmr_cache) { + NgapRequestHandler::d_cmr_mem_cache.put(url_key, data_url); + CACHE_LOG(prolog + "CMR Cache put, translated URL: " + data_url + '\n'); + } + + return data_url; +} + +/** + * @brief Build a URL to the granule in the OPeNDAP S3 bucket + * @param rest_path The REST path of the granule: '/collections//granules/' + * @param data_source The protocol and host name part of the URL + * @return The URL to the item in a S3 bucket + */ +string NgapOwnedContainer::build_dmrpp_url_to_owned_bucket(const string &rest_path, const string &data_source) { + // The PATH part of a URL to the NGAP/DMR++ is an 'NGAP REST path' that has the form: + // /collections//granules/. In our 'owned' S3 bucket, we use object + // names of the form: //.dmrpp. + BES_MODULE_TIMING(prolog + rest_path); + + auto parts = BESUtil::split(rest_path, '/'); + if (parts.size() != 4 || parts[0] != "collections" || parts[2] != "granules") { + throw BESSyntaxUserError("Invalid NGAP path: " + rest_path, __FILE__, __LINE__); + } + + string dmrpp_name = parts[1] + '/' + parts[3] + ".dmrpp"; + + // http://.s3.amazonaws.com/ + // Chane so the first part is read from a configuration file. + // That way it can be a file:// URL for testing, and later can be set + // in other ways. jhrg 5/1/24 + string dmrpp_url_str = data_source + '/' + dmrpp_name; + + return dmrpp_url_str; +} + +bool NgapOwnedContainer::get_item_from_dmrpp_cache(string &dmrpp_string) const { + + // Read the cache entry if it exists. jhrg 4/29/24 + if (NgapRequestHandler::d_dmrpp_mem_cache.get(get_real_name(), dmrpp_string)) { + CACHE_LOG(prolog + "Memory Cache hit, DMR++: " + get_real_name() + '\n'); + return true; + } else { + CACHE_LOG(prolog + "Memory Cache miss, DMR++: " + get_real_name() + '\n'); + } + + // Before going over the network to get the DMR++, look in the FileCache. + // If found, put it in the memory cache and return it as a string. + + FileCache::Item item; + if (NgapRequestHandler::d_dmrpp_file_cache.get(FileCache::hash_key(get_real_name()), item)) { // got it + // read data from the file into the string. + CACHE_LOG(prolog + "File Cache hit, DMR++: " + get_real_name() + '\n'); + if (file_to_string(item.get_fd(), dmrpp_string)) { + // put it in the memory cache + NgapRequestHandler::d_dmrpp_mem_cache.put(get_real_name(), dmrpp_string); + CACHE_LOG(prolog + "Memory Cache put, DMR++: " + get_real_name() + '\n'); + return true; + } else { + ERROR_LOG(prolog + "Failed to read DMR++ from file cache\n"); + return false; + } + } else { + CACHE_LOG(prolog + "File Cache miss, DMR++: " + get_real_name() + '\n'); + } + + return false; +} + +bool NgapOwnedContainer::put_item_in_dmrpp_cache(const std::string &dmrpp_string) const { + if (NgapRequestHandler::d_dmrpp_file_cache.put_data(FileCache::hash_key(get_real_name()), dmrpp_string)) { + CACHE_LOG(prolog + "File Cache put, DMR++: " + get_real_name() + '\n'); + } else { + // This might not be an error - put_data() records errors. jhrg 2/13/25 + CACHE_LOG(prolog + "Failed to put DMR++ in file cache\n"); + return false; + } + + if (!NgapRequestHandler::d_dmrpp_file_cache.purge()) { + ERROR_LOG(prolog + "Call to FileCache::purge() failed\n"); + } + + NgapRequestHandler::d_dmrpp_mem_cache.put(get_real_name(), dmrpp_string); + CACHE_LOG(prolog + "Memory Cache put, DMR++: " + get_real_name() + '\n'); + + return true; +} + +/** + * @brief Filter the cached resource. Each key in content_filters is replaced with its associated map value. + * + * WARNING: Does not lock cache. This method assumes that the process has already + * acquired an exclusive lock on the cache file. + * + * WARNING: This method will overwrite the cached data with the filtered result. + * + * @param content_filters A map of key value pairs which define the filter operation. Each key found in the + * resource will be replaced with its associated value. + * @param content A reference to the C++ string to filter + */ +void NgapOwnedContainer::filter_response(const map> &content_filters, string &content) { + for (const auto &filter : content_filters) { + unsigned int replace_count = BESUtil::replace_all(content, filter.first, filter.second); + BESDEBUG(MODULE, prolog << "Replaced " << replace_count << " instance(s) of template(" << filter.first + << ") with " << filter.second << " in cached RemoteResource" << endl); + } +} + +/** + * Build the content filters if needed + * @note If the filters are built, clear the content_filters value/result parameter first. + * @param content_filters Value-result parameter + * @return True if the filters were built, false otherwise + */ +bool NgapOwnedContainer::get_daac_content_filters(const string &data_url, + map> &content_filters) { + if (NgapOwnedContainer::d_inject_data_url) { + // data_url was get_real_name(). jhrg 8/9/24 + const string missing_data_url_str = data_url + "_mvs.h5"; + const string href = R"(href=")"; + const string trusted_url_hack = R"(" dmrpp:trust="true")"; + const string data_access_url_key = href + DATA_ACCESS_URL_KEY + "\""; + const string data_access_url_with_trusted_attr_str = href + data_url + trusted_url_hack; + const string missing_data_access_url_key = href + MISSING_DATA_ACCESS_URL_KEY + "\""; + const string missing_data_url_with_trusted_attr_str = href + missing_data_url_str + trusted_url_hack; + + content_filters.clear(); + content_filters.insert(pair(data_access_url_key, data_access_url_with_trusted_attr_str)); + content_filters.insert( + pair(missing_data_access_url_key, missing_data_url_with_trusted_attr_str)); + return true; + } + + return false; +} + +/** + * @brief Get the content filters for the OPeNDAP-owned DMR++. + * Build filters to use the BESUtils::replace_all() method to insert the 'dmrpp:trust="true"' + * XML attribute. Adding this means that we do not have to add the strange cloudfront host names + * to the BES AllowedHosts list. + * @param content_filters Value-result parameter that is the map of values to replace in the DMR++ + * @return True if the filters were built, false otherwise + */ +bool NgapOwnedContainer::get_opendap_content_filters(map> &content_filters) { + if (NgapOwnedContainer::d_inject_data_url) { // Hmmm, this is a bit of a hack. jhrg 8/22/24 + + const string version_attribute = "dmrpp:version"; + const string trusted_attribute = R"(dmrpp:trust="true" )"; + // The 'trust' attribute is inserted _before_ the 'version' attribute. jhrg 8/22/24 + const string trusted_and_version = trusted_attribute + version_attribute; + + content_filters.clear(); + content_filters.insert(pair(version_attribute, trusted_and_version)); + + return true; + } + + return false; +} + +/** + * @brief Read the DMR++ from the OPeNDAP S3 bucket + * @param dmrpp_string value-result parameter for the DMR++ doc as a string + * @return True if the document was found, false otherwise + * @exception Throw xxx on a 50x response from HTTP. + */ +bool NgapOwnedContainer::dmrpp_read_from_opendap_bucket(string &dmrpp_string) const { + BES_MODULE_TIMING(prolog + get_real_name()); + bool dmrpp_read = false; + try { + string dmrpp_url_str = build_dmrpp_url_to_owned_bucket(get_real_name(), get_data_source_location()); + INFO_LOG(prolog + "Look in the OPeNDAP-bucket for the DMRpp for: " + dmrpp_url_str); + curl::http_get(dmrpp_url_str, dmrpp_string); + map> content_filters; + if (!get_opendap_content_filters(content_filters)) { + throw BESInternalError("Could not build opendap content filters for DMR++", __FILE__, __LINE__); + } + filter_response(content_filters, dmrpp_string); + INFO_LOG(prolog + "Found the DMRpp in the OPeNDAP-bucket for: " + dmrpp_url_str); + dmrpp_read = true; + } catch (http::HttpError &http_error) { + // Assumption - when S3 returns a 404, the things is not there. jhrg 8/9/24 + // But, sometimes AWS/S3 returns 400 for a missing object. jhrg 9/10/24 + // + // for 400 and 500 errors, try the DAAC bucket. + // for a 404, do not log an error, just return false. + // for other errors, log the error and return false + switch (http_error.http_status()) { + case 400: + case 401: + case 403: + ERROR_LOG(prolog + "Looked in the OPeNDAP bucket for the DMRpp for: " + get_real_name() + + " but got HTTP Status: " + std::to_string(http_error.http_status())); + dmrpp_string.clear(); // ...because S3 puts an error message in the string. jhrg 8/9/24 + dmrpp_read = false; + break; + + case 404: + dmrpp_string.clear(); // ...because S3 puts an error message in the string. jhrg 8/9/24 + dmrpp_read = false; + break; + + default: + http_error.set_message(http_error.get_message() + + ". This error for a OPeNDAP-owned DMR++ could be from Hyrax or S3."); + throw; + } + } + + return dmrpp_read; +} + +/** + * @brief Read the DMR++ from a DAAC S3 bucket + * @param dmrpp_string value-result parameter for the DMR++ doc as a string + * @exception http::HttpError if the granule is not found + */ +void NgapOwnedContainer::dmrpp_read_from_daac_bucket(string &dmrpp_string) const { + BES_MODULE_TIMING(prolog + get_real_name()); + // This code may ask CMR and will throw exceptions that mention CMR on error. jhrg 1/24/25 + string data_url = build_data_url_to_daac_bucket(get_real_name()); + string dmrpp_url_str = data_url + ".dmrpp"; // This is the URL to the DMR++ in the DAAC-owned bucket. jhrg 8/9/24 + INFO_LOG(prolog + "Look in the DAAC-bucket for the DMRpp for: " + dmrpp_url_str); + + try { + curl::http_get(dmrpp_url_str, dmrpp_string); + // filter the DMRPP from the DAAC's bucket to replace the template href with the data_url + map> content_filters; + if (!get_daac_content_filters(data_url, content_filters)) { + throw BESInternalError("Could not build content filters for DMR++", __FILE__, __LINE__); + } + filter_response(content_filters, dmrpp_string); + INFO_LOG(prolog + "Found the DMRpp in the DAAC-bucket for: " + dmrpp_url_str); + } catch (http::HttpError &http_error) { + http_error.set_message(http_error.get_message() + + "NgapOwnedContainer::dmrpp_read_from_daac_bucket() failed to read the DMR++ from S3."); + throw; + } +} + +/** + * @brief Get the DMR++ from a remote source or a cache + * + * This method will try to read a DMR++ from an S3 bucket if that DMR++ cannot be found in the + * DMR++ cache. If the DMR++ cannot be read from a S3 bucket, it will throw an exception. The + * method returns false if the DMR++ was read but for some reason could not be cached. + * + * @param dmrpp_string Value-result parameter that will contain the DMR++ as a string + * + * @return True if the DMR++ was found and no caching issues were encountered, false if there + * was a failure of the caching system. Error messages are logged if there is a caching issue. + * Note that if this methods cannot get the DMR++ from the remote source, it will throw an exception. + * + * @exception http::HttpError if there is a problem making the remote request if one is needed. + */ +bool NgapOwnedContainer::get_dmrpp_from_cache_or_remote_source(string &dmrpp_string) const { + BES_MODULE_TIMING(prolog + get_real_name()); + + // If the DMR++ is cached, return it. NB: This cache holds OPeNDAP- and DAAC-owned DMR++ documents. + if (NgapRequestHandler::d_use_dmrpp_cache && get_item_from_dmrpp_cache(dmrpp_string)) { + return true; + } else { + // Else, the DMR++ is neither in the memory cache nor the file cache. + // Read it from S3, etc., and filter it. Put it in the memory cache + bool dmrpp_read = false; + + // If the server is set up to try the OPeNDAP bucket, look there first. + if (NgapOwnedContainer::d_support_source_prefix) { + // If we get the DMR++ from the OPeNDAP bucket, set dmrpp_read to true so + // we don't also try the DAAC bucket. + dmrpp_read = dmrpp_read_from_opendap_bucket(dmrpp_string); + } + + // Try the DAAC bucket if either the OPeNDAP bucket is not used or the OPeNDAP bucket failed + if (!dmrpp_read) { + dmrpp_read_from_daac_bucket(dmrpp_string); + } + } + + // if we get here, the DMR++ has been pulled over the network. Put it in both caches. + // The memory cache is for use by this process, the file cache for other processes/VMs + if (NgapRequestHandler::d_use_dmrpp_cache && !put_item_in_dmrpp_cache(dmrpp_string)) { + return false; + } + + return true; +} + +/** + * @brief Get the DMR++ from a remote source or a local cache + * + * @note The Container::access() methods are called by the framework when it + * runs execute_commands() and then, often, a second time in the RequestHandler + * code when it is looking for data. + * + * @return The DMR++ as a string. + * @throws BESError if there is a problem making the remote request + */ +string NgapOwnedContainer::access() { + + string dmrpp_string; + + // Get the DMR++ from the S3 bucket or the cache. + // get_dmrpp...() returns false for various caching errors, but throws if it cannot + // get the remote DMR++. jhrg 4/29/24 + get_dmrpp_from_cache_or_remote_source(dmrpp_string); + + set_attributes("as-string"); // This means access() returns a string. jhrg 10/19/23 + // Originally, this was either hard-coded (as it is now) or was set using the 'extension' + // on the URL. But it's always a DMR++. jhrg 11/16/23 + set_container_type("dmrpp"); + + return dmrpp_string; +} + +/** @brief dumps information about this object + * + * Displays the pointer value of this instance along with information about + * this container. + * + * @param strm C++ i/o stream to dump the information to + */ +void NgapOwnedContainer::dump(ostream &strm) const { + strm << BESIndent::LMarg << "NgapOwnedContainer::dump - (" << (void *)this << ")\n"; + BESIndent::Indent(); + BESContainer::dump(strm); + BESIndent::UnIndent(); +} + +} // namespace ngap diff --git a/retired/modules/ngap_module/NgapOwnedContainer.h b/retired/modules/ngap_module/NgapOwnedContainer.h new file mode 100644 index 0000000000..9ff3a9ca4b --- /dev/null +++ b/retired/modules/ngap_module/NgapOwnedContainer.h @@ -0,0 +1,130 @@ +// -*- mode: c++; c-basic-offset:4 -*- + +// This file is part of ngap_module, A C++ module that can be loaded in to +// the OPeNDAP Back-End Server (BES) and is able to handle remote requests. + +// Copyright (c) 2020, 2024 OPeNDAP, Inc. +// Author: Nathan Potter , +// James Gallagher +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. + +#ifndef NgapOwnedContainer_h_ +#define NgapOwnedContainer_h_ 1 + +#include +#include +#include + +#include "BESContainer.h" + +namespace http { +class RemoteResource; +} + +namespace ngap { + +/** + * @brief Container representing a data resource that is 'owned' by NGAP/EDC/NASA + * but that is described by a DMR++ that OPeNDAP 'owns.' + * + * This container nominally stores the 'restified' URL to a NASA granule. + * The container handles the operation needed to access a DMR++ file + * that can _then_ be used to read data from that granule. + * + * This operation is to retrieve that DMR++ file and store it in + * a cache as text (DMR++ files are XML). + * + * The NgapOwnedContainer::access() method performs this operation the first + * time it is called. Subsequent calls to NgapOwnedContainer::access() will return + * cached XML text. Like NgapContainer::access(), this object uses the container + * attributes to indicate that access() may return a string that holds the + * DMR++ XML text. + * + * @see NgapOwnedContainerStorage + */ +class NgapOwnedContainer : public BESContainer { + + std::string d_ngap_path; // The (in)famous REST path + static std::string d_data_source_location; + static bool d_support_source_prefix; + static bool d_inject_data_url; + + bool get_dmrpp_from_cache_or_remote_source(std::string &dmrpp_string) const; + + // I made these static so that they will be in the class' namespace but still + // be easy to test in the unit tests. jhrg 4/29/24 + static bool file_to_string(int fd, std::string &content); + + static bool get_daac_content_filters(const std::string &data_url, + std::map> &content_filters); + static bool get_opendap_content_filters(std::map> &content_filters); + static void filter_response(const std::map> &content_filters, + std::string &content); + + static std::string build_dmrpp_url_to_owned_bucket(const std::string &rest_path, const std::string &data_source); + static std::string build_data_url_to_daac_bucket(const std::string &rest_path); + + bool dmrpp_read_from_opendap_bucket(std::string &dmrpp_string) const; + void dmrpp_read_from_daac_bucket(std::string &dmrpp_string) const; + + bool get_item_from_dmrpp_cache(std::string &dmrpp_string) const; + bool put_item_in_dmrpp_cache(const std::string &dmrpp_string) const; + + friend class NgapOwnedContainerTest; + +protected: + void _duplicate(NgapOwnedContainer ©_to) { + copy_to.d_ngap_path = d_ngap_path; + BESContainer::_duplicate(copy_to); + } + +public: + NgapOwnedContainer() = default; + NgapOwnedContainer(const NgapOwnedContainer ©_from) = delete; + NgapOwnedContainer(NgapOwnedContainer &&move_from) = delete; + NgapOwnedContainer &operator=(const NgapOwnedContainer &rhs) = delete; + NgapOwnedContainer &operator=(NgapOwnedContainer &&rhs) = delete; + ~NgapOwnedContainer() override = default; + + NgapOwnedContainer(const std::string &sym_name, const std::string &real_name, const std::string &); + + BESContainer *ptr_duplicate() override { + auto container = std::make_unique(); + _duplicate(*container); + return container.release(); + } + + void set_ngap_path(const std::string &ngap_path) { d_ngap_path = ngap_path; } + std::string get_ngap_path() const { return d_ngap_path; } + + /// @brief Set the S3 bucket used for 'owned' DMR++ documents. + static void set_data_source_location(const std::string &data_source_location) { + d_data_source_location = data_source_location; + } + static std::string get_data_source_location() { return d_data_source_location; } + + std::string access() override; + + bool release() override { return true; } + + void dump(std::ostream &strm) const override; +}; + +} // namespace ngap + +#endif // NgapOwnedContainer_h_ diff --git a/retired/modules/ngap_module/NgapOwnedContainerStorage.cc b/retired/modules/ngap_module/NgapOwnedContainerStorage.cc new file mode 100644 index 0000000000..a5b58f8e52 --- /dev/null +++ b/retired/modules/ngap_module/NgapOwnedContainerStorage.cc @@ -0,0 +1,63 @@ +// -*- mode: c++; c-basic-offset:4 -*- + +// This file is part of ngap_module, A C++ module that can be loaded in to +// the OPeNDAP Back-End Server (BES) and is able to handle remote requests. + +// Copyright (c) 2020 OPeNDAP, Inc. +// Author: Nathan Potter +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. + + +#include "config.h" + +#include + +#include "NgapOwnedContainerStorage.h" +#include "NgapOwnedContainer.h" + +using namespace std; + +namespace ngap { + +/** @brief adds a container with the provided information + * + * @param s_name symbolic name for the container + * @param r_name the remote request url + * @param type ignored. The type of the target response is determined by the + * request response, or could be passed in + */ +void NgapOwnedContainerStorage::add_container(const string &s_name, const string &r_name, const string &type) { + auto c = new NgapOwnedContainer(s_name, r_name, type); + BESContainerStorageVolatile::add_container(c); +} + +/** @brief dumps information about this object + * + * Displays the pointer value of this instance along with information about + * each of the GatewayContainers already stored. + * + * @param strm C++ i/o stream to dump the information to + */ +void NgapOwnedContainerStorage::dump(ostream &strm) const { + strm << BESIndent::LMarg << "NgapOwnedContainerStorage::dump - (" << (void *) this << ")" << endl; + BESIndent::Indent(); + BESContainerStorageVolatile::dump(strm); + BESIndent::UnIndent(); +} + +} // namespace ngap diff --git a/retired/modules/ngap_module/NgapOwnedContainerStorage.h b/retired/modules/ngap_module/NgapOwnedContainerStorage.h new file mode 100644 index 0000000000..78aa6fee22 --- /dev/null +++ b/retired/modules/ngap_module/NgapOwnedContainerStorage.h @@ -0,0 +1,59 @@ +// -*- mode: c++; c-basic-offset:4 -*- + +// This file is part of ngap_module, A C++ module that can be loaded in to +// the OPeNDAP Back-End Server (BES) and is able to handle remote requests. + +// Copyright (c) 2020 OPeNDAP, Inc. +// Author: Nathan Potter +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. + + +#ifndef NgapOwnedContainerStorage_h_ +#define NgapOwnedContainerStorage_h_ 1 + +#include + +#include "BESContainerStorageVolatile.h" + +class BESCatalogUtils; + +namespace ngap { + +/** @brief implementation of BESContainerStorageVolatile that represents a + * resource managed by the NASA NGAP/EOSDIS cloud-based data system. These + * resources are stored in S3 and must be transferred to the server before + * they can be used. In the Hyrax server, these are DMR++ (i.e., XML) files, + * not the actual data files. The data files are stored in S3 but are subset + * directly from S3 using information in the (much smaller) DMR++ files + * + * @see BESContainerStorageVolatile + * @see GatewayContainer + */ +class NgapOwnedContainerStorage: public BESContainerStorageVolatile { +public: + explicit NgapOwnedContainerStorage(const std::string &n) : BESContainerStorageVolatile(n) {} + ~NgapOwnedContainerStorage() override = default; + + void add_container(const std::string &s_name, const std::string &r_name, const std::string &type) override; + + void dump(std::ostream &strm) const override; +}; + +} // namespace ngap + +#endif // NgapOwnedContainerStorage_h_ diff --git a/retired/modules/ngap_module/NgapRequestHandler.cc b/retired/modules/ngap_module/NgapRequestHandler.cc new file mode 100644 index 0000000000..d2a2ddfe03 --- /dev/null +++ b/retired/modules/ngap_module/NgapRequestHandler.cc @@ -0,0 +1,168 @@ +// NgapContainer.cc + +// -*- mode: c++; c-basic-offset:4 -*- + +// This file is part of ngap_module, A C++ module that can be loaded in to +// the OPeNDAP Back-End Server (BES) and is able to handle remote requests. + +// Copyright (c) 2020 OPeNDAP, Inc. +// Author: Nathan Potter +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. +// Authors: +// ndp Nathan Potter + +#include "config.h" + +// #include "libdap/InternalErr.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "NgapRequestHandler.h" +#include "NgapNames.h" + +#ifndef MODULE_NAME +#define MODULE_NAME "ngap_module" +#endif + +#ifndef MODULE_VERSION +#define MODULE_VERSION "1.1.0" +#endif + +using namespace std; +// using namespace libdap; +using namespace ngap; + +// CMR caching +int NgapRequestHandler::d_cmr_cache_size_items = 100; // Entries, not size in bytes, MB, etc. +int NgapRequestHandler::d_cmr_cache_purge_items = 20; + +bool NgapRequestHandler::d_use_cmr_cache = false; +MemoryCache NgapRequestHandler::d_cmr_mem_cache; + +// DMR++ caching +int NgapRequestHandler::d_dmrpp_mem_cache_size_items = 100; +int NgapRequestHandler::d_dmrpp_mem_cache_purge_items = 20; + +bool NgapRequestHandler::d_use_dmrpp_cache = false; +MemoryCache NgapRequestHandler::d_dmrpp_mem_cache; + +long long NgapRequestHandler::d_dmrpp_file_cache_size_mb = 10'000; // 10,000 MB ~= 10GB, roughly +long long NgapRequestHandler::d_dmrpp_file_cache_purge_size_mb = 2'000; // 2,000 MB ~= 2GB +string NgapRequestHandler::d_dmrpp_file_cache_dir = "/tmp/hyrax_dmrpp_cache"; + +FileCache NgapRequestHandler::d_dmrpp_file_cache; + +NgapRequestHandler::NgapRequestHandler(const string &name) : + BESRequestHandler(name) +{ + BESRequestHandler::add_method(VERS_RESPONSE, NgapRequestHandler::ngap_build_vers); + BESRequestHandler::add_method(HELP_RESPONSE, NgapRequestHandler::ngap_build_help); + + // Read BES keys to determine if the caches should be used. jhrg 9/22/23 + NgapRequestHandler::d_use_cmr_cache + = TheBESKeys::read_bool_key(USE_CMR_CACHE, NgapRequestHandler::d_use_cmr_cache); + if (NgapRequestHandler::d_use_cmr_cache) { + NgapRequestHandler::d_cmr_cache_size_items + = TheBESKeys::read_int_key(CMR_CACHE_THRESHOLD, NgapRequestHandler::d_cmr_cache_size_items); + NgapRequestHandler::d_cmr_cache_purge_items + = TheBESKeys::read_int_key(CMR_CACHE_SPACE, NgapRequestHandler::d_cmr_cache_purge_items); + if (!d_cmr_mem_cache.initialize(d_cmr_cache_size_items, d_cmr_cache_purge_items)) { + ERROR_LOG("NgapRequestHandler::NgapRequestHandler() - failed to initialize CMR cache"); + } + } + + NgapRequestHandler::d_use_dmrpp_cache + = TheBESKeys::read_bool_key(USE_DMRPP_CACHE, NgapRequestHandler::d_use_dmrpp_cache); + if (NgapRequestHandler::d_use_dmrpp_cache) { + NgapRequestHandler::d_dmrpp_mem_cache_size_items + = TheBESKeys::read_int_key(DMRPP_CACHE_THRESHOLD, NgapRequestHandler::d_dmrpp_mem_cache_size_items); + NgapRequestHandler::d_dmrpp_mem_cache_purge_items + = TheBESKeys::read_int_key(DMRPP_CACHE_SPACE, NgapRequestHandler::d_dmrpp_mem_cache_purge_items); + if (!d_dmrpp_mem_cache.initialize(d_dmrpp_mem_cache_size_items, d_dmrpp_mem_cache_purge_items)) { + ERROR_LOG("NgapRequestHandler::NgapRequestHandler() - failed to initialize DMR++ cache"); + } + + // Now set up the file cache. Note that the sizes in the bes.conf file are in MB, + // so convert them to bytes. jhrg 11/14/23 + NgapRequestHandler::d_dmrpp_file_cache_size_mb + = MEGABYTE * TheBESKeys::read_ulong_key(DMRPP_FILE_CACHE_THRESHOLD, + NgapRequestHandler::d_dmrpp_file_cache_size_mb); + NgapRequestHandler::d_dmrpp_file_cache_purge_size_mb + = MEGABYTE * TheBESKeys::read_ulong_key(DMRPP_FILE_CACHE_SPACE, + NgapRequestHandler::d_dmrpp_file_cache_purge_size_mb); + NgapRequestHandler::d_dmrpp_file_cache_dir + = TheBESKeys::read_string_key(DMRPP_FILE_CACHE_DIR, + NgapRequestHandler::d_dmrpp_file_cache_dir); + if (BESUtil::mkdir_p(NgapRequestHandler::d_dmrpp_file_cache_dir, 0775) != 0) { + ERROR_LOG("DMR++ file cache directory '" + NgapRequestHandler::d_dmrpp_file_cache_dir + "' error: " + + strerror(errno)); + } + if (!NgapRequestHandler::d_dmrpp_file_cache.initialize(NgapRequestHandler::d_dmrpp_file_cache_dir, + NgapRequestHandler::d_dmrpp_file_cache_size_mb, + NgapRequestHandler::d_dmrpp_file_cache_purge_size_mb)) { + ERROR_LOG("NgapRequestHandler::NgapRequestHandler() - failed to initialize DMR++ file cache"); + } + } +} + +bool NgapRequestHandler::ngap_build_vers(BESDataHandlerInterface &dhi) +{ + auto info = dynamic_cast(dhi.response_handler->get_response_object()); + if (!info) throw BESInternalError("Expected a BESVersionInfo instance", __FILE__, __LINE__); + + info->add_module(MODULE_NAME, MODULE_VERSION); + return true; +} + +bool NgapRequestHandler::ngap_build_help(BESDataHandlerInterface &dhi) +{ + auto info = dynamic_cast(dhi.response_handler->get_response_object()); + if (!info) throw BESInternalError("Expected a BESInfo instance", __FILE__, __LINE__); + + // This is an example. If you had a help file you could load it like + // this and if your handler handled the following responses. + map> attrs; + attrs["name"] = MODULE_NAME; + attrs["version"] = MODULE_VERSION; + + list services; + BESServiceRegistry::TheRegistry()->services_handled(NGAP_NAME, services); + if (!services.empty()) { + string handles = BESUtil::implode(services, ','); + attrs["handles"] = handles; + } + info->begin_tag("module", &attrs); + info->end_tag("module"); + + return true; +} + +void NgapRequestHandler::dump(ostream &strm) const +{ + strm << BESIndent::LMarg << "NgapRequestHandler::dump - (" << (void *) this << ")" << endl; + BESIndent::Indent(); + BESRequestHandler::dump(strm); + BESIndent::UnIndent(); +} diff --git a/retired/modules/ngap_module/NgapRequestHandler.h b/retired/modules/ngap_module/NgapRequestHandler.h new file mode 100644 index 0000000000..e838456ce2 --- /dev/null +++ b/retired/modules/ngap_module/NgapRequestHandler.h @@ -0,0 +1,89 @@ +// NgapContainer.cc + +// -*- mode: c++; c-basic-offset:4 -*- + +// This file is part of ngap_module, A C++ module that can be loaded in to +// the OPeNDAP Back-End Server (BES) and is able to handle remote requests. + +// Copyright (c) 2020 OPeNDAP, Inc. +// Author: Nathan Potter +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. +// Authors: +// ndp Nathan Potter + +#ifndef I_NgapRequestHandler_H +#define I_NgapRequestHandler_H + +#include +#include +#include +#include + +#include "MemoryCache.h" +#include "FileCache.h" +#include "BESRequestHandler.h" + +namespace ngap { + +class NgapRequestHandler : public BESRequestHandler { + + static int d_cmr_cache_size_items; // max number of entries + static int d_cmr_cache_purge_items; // remove this many during purge + + static bool d_use_cmr_cache; + static MemoryCache d_cmr_mem_cache; + + static int d_dmrpp_mem_cache_size_items; // max number of entries + static int d_dmrpp_mem_cache_purge_items; // remove this many during purge + + static bool d_use_dmrpp_cache; + static MemoryCache d_dmrpp_mem_cache; + + static long long d_dmrpp_file_cache_size_mb; + static long long d_dmrpp_file_cache_purge_size_mb; + static std::string d_dmrpp_file_cache_dir; + + static FileCache d_dmrpp_file_cache; + + friend class NgapContainer; // give NgapContainer access to the cache parameters + friend class NgapOwnedContainer; // give NgapOwnedContainer access to the cache parameters. jhrg 4/29/24 + friend class NgapContainerTest; + friend class NgapOwnedContainerTest; + friend class NgapRequestHandlerTest; + +public: + explicit NgapRequestHandler(const std::string &name); + + NgapRequestHandler() = delete; + + ~NgapRequestHandler() override = default; + + NgapRequestHandler(const NgapRequestHandler &src) = delete; + + NgapRequestHandler &operator=(const NgapRequestHandler &rhs) = delete; + + void dump(std::ostream &strm) const override; + + static bool ngap_build_vers(BESDataHandlerInterface &dhi); + + static bool ngap_build_help(BESDataHandlerInterface &dhi); +}; + +} // namespace ngap + +#endif // NgapRequestHandler.h diff --git a/retired/modules/ngap_module/ngap.conf b/retired/modules/ngap_module/ngap.conf new file mode 100644 index 0000000000..9f3a4b6a80 --- /dev/null +++ b/retired/modules/ngap_module/ngap.conf @@ -0,0 +1,36 @@ +BES.Include=dap.conf + +BES.modules+=ngap +BES.module.ngap=/Users/jimg/src/opendap/hyrax/build/lib/bes/libngap_module.so + +# Use this CMR endpoint URL for CMR queries. +# NGAP.cmr_host_url=https://cmr.uat.earthdata.nasa.gov +# NGAP.cmr_search_endpoint_path=/search/granules.umm_json_v1_4 + +NGAP.UseDMRppCache = true + +# Defaults: 100 entries and purge 20 entries when the threshold is exceeded. +# NGAP.DMRppCacheSize = 100 +# NGAP.DMRppCachePurge = 20 + +NGAP.UseCMRCache = true + +# Same defaults and meaning as for the DMRppCache cache +# NGAP.CMRCacheSize = 100 +# NGAP.CMRCachePurge = 20 + +NGAP.DMRppFileCacheDir = /tmp/hyrax_ngap_cache +NGAP.DMRppFileCacheSize.MB = 10000 +NGAP.DMRppFileCachePurge.MB = 2000 + +# This is the default value - used for 'OPeNDAP-Owned' S3 bucket tests. +# Set this to your own S3 bucket where DMR++ documents can be found. +# Not used when UseOPeNDAPBucket is false. +NGAP.DataSourceLocation = https://cloudydap.s3.us-east-1.amazonaws.com + +# Set this to true to try the OPeNDAP bucket for DMR++ documents. Default is false. +NGAP.UseOPeNDAPBucket = false + +# set this to true to substitute data URLs in the DMR++ for the template href value. +# Default is true. +NGAP.inject_data_urls = true diff --git a/retired/modules/ngap_module/ngap.conf.in b/retired/modules/ngap_module/ngap.conf.in new file mode 100644 index 0000000000..03f4bb82a1 --- /dev/null +++ b/retired/modules/ngap_module/ngap.conf.in @@ -0,0 +1,36 @@ +BES.Include=dap.conf + +BES.modules+=ngap +BES.module.ngap=@bes_modules_dir@/libngap_module.so + +# Use this CMR endpoint URL for CMR queries. +# NGAP.cmr_host_url=https://cmr.uat.earthdata.nasa.gov +# NGAP.cmr_search_endpoint_path=/search/granules.umm_json_v1_4 + +NGAP.UseDMRppCache = true + +# Defaults: 100 entries and purge 20 entries when the threshold is exceeded. +# NGAP.DMRppCacheSize = 100 +# NGAP.DMRppCachePurge = 20 + +NGAP.UseCMRCache = true + +# Same defaults and meaning as for the DMRppCache cache +# NGAP.CMRCacheSize = 100 +# NGAP.CMRCachePurge = 20 + +NGAP.DMRppFileCacheDir = /tmp/hyrax_ngap_cache +NGAP.DMRppFileCacheSize.MB = 10000 +NGAP.DMRppFileCachePurge.MB = 2000 + +# This is the default value - used for 'OPeNDAP-Owned' S3 bucket tests. +# Set this to your own S3 bucket where DMR++ documents can be found. +# Not used when UseOPeNDAPBucket is false. +NGAP.DataSourceLocation = https://cloudydap.s3.us-east-1.amazonaws.com + +# Set this to true to try the OPeNDAP bucket for DMR++ documents. Default is false. +NGAP.UseOPeNDAPBucket = false + +# set this to true to substitute data URLs in the DMR++ for the template href value. +# Default is true. +NGAP.inject_data_urls = true diff --git a/retired/modules/ngap_module/tests/.gitignore b/retired/modules/ngap_module/tests/.gitignore new file mode 100644 index 0000000000..4a5df89662 --- /dev/null +++ b/retired/modules/ngap_module/tests/.gitignore @@ -0,0 +1,4 @@ +mds_ledger.txt +CM.config +cache/ + diff --git a/retired/modules/ngap_module/tests/CM.config.template b/retired/modules/ngap_module/tests/CM.config.template new file mode 100644 index 0000000000..d8b42e9d11 --- /dev/null +++ b/retired/modules/ngap_module/tests/CM.config.template @@ -0,0 +1,22 @@ + +# This file holds credentials for the CredentialsManager. +# +# Note: The access permissions on this file must be 600. +# +# Example: +# 'url' is used to match the other information with any URL that matches the prefix +# 'id' is the user Id, 'key' is the matching secret key, 'region' is the AWS region and +# 'bucket' is the S3 bucket. Matching URLs will be signed using the AWS v4 algorithm. +# The name to the left (e.g., 'cloudydap') is arbitrary and only serves to group these +# five strings together. +# +cloudydap = url:https://cloudydap.s3.us-east-1.amazonaws.com +cloudydap += id:SOME_VALID_ID +cloudydap += key:SOME_VALID_KEY +cloudydap += region:us-east-1 +cloudydap += bucket:cloudydap + +# This can be used to bind other credentials to specific URLs + +podaac = url:https://archive.podaac.earthdata.nasa.gov/ +podaac += edl_token:BEARER diff --git a/retired/modules/ngap_module/tests/Makefile.am b/retired/modules/ngap_module/tests/Makefile.am new file mode 100644 index 0000000000..2a0fbde331 --- /dev/null +++ b/retired/modules/ngap_module/tests/Makefile.am @@ -0,0 +1,59 @@ + +AUTOMAKE_OPTIONS = foreign + +AM_CPPFLAGS = -I$(top_srcdir) + +AM_CXXFLAGS = + +BES_CONF_IN = bes.conf.in + +noinst_DATA = bes.conf + +CLEANFILES = bes.conf mds_ledger.txt bes.log + +EXTRA_DIST = ngap $(TESTSUITE).at $(TESTSUITE) atlocal.in \ +CM.config.template package.m4 $(BES_CONF_IN) bes-daac.conf + +DISTCLEANFILES = atconfig + +# Build the bes.conf used for testing so that the value substituted for +# @abs_top_srcdir@ does not contain '../'. This happens when using +# configure's value for the parameter when running the distcheck target. +bes.conf: $(BES_CONF_IN) $(top_srcdir)/configure.ac + @clean_abs_top_srcdir=`${PYTHON} -c "import os.path; print(os.path.abspath('${abs_top_srcdir}'))"`; \ + sed -e "s%[@]abs_top_srcdir[@]%$$clean_abs_top_srcdir%" \ + -e "s%[@]abs_top_builddir[@]%${abs_top_builddir}%" $< > bes.conf + +############## Autotest follows ##################### + +AUTOM4TE = autom4te + +TESTSUITE = $(srcdir)/testsuite + +check-local: atconfig atlocal $(srcdir)/package.m4 $(TESTSUITE) bes.conf bes-daac.conf + @if [ -f $(srcdir)/CM.config ]; then \ + $(SHELL) '$(TESTSUITE)' $(TESTSUITEFLAGS); \ + else \ + echo "No access credentials available, skipping tests that use S3"; \ + true;\ + fi + +clean-local: + test ! -f '$(TESTSUITE)' || $(SHELL) '$(TESTSUITE)' --clean + -rm -f $(TESTSUITE) $(srcdir)/package.m4 + +AUTOTEST = $(AUTOM4TE) --language=autotest + +$(TESTSUITE): $(TESTSUITE).at $(srcdir)/package.m4 $(top_srcdir)/modules/common/handler_tests_macros.m4 + $(AUTOTEST) -I '$(srcdir)' -o $@ $@.at + +# The `:;' works around a Bash 3.2 bug when the output is not writable. +$(srcdir)/package.m4: $(top_srcdir)/configure.ac + :;{ \ + echo '# Signature of the current package.' && \ + echo 'm4_define([AT_PACKAGE_NAME], [@PACKAGE_NAME@])' && \ + echo 'm4_define([AT_PACKAGE_TARNAME], [@PACKAGE_TARNAME@])' && \ + echo 'm4_define([AT_PACKAGE_VERSION], [@PACKAGE_VERSION@])' && \ + echo 'm4_define([AT_PACKAGE_STRING], [@PACKAGE_STRING@])' && \ + echo 'm4_define([AT_PACKAGE_BUGREPORT], [@PACKAGE_BUGREPORT@])'; \ + } >'$(srcdir)/package.m4' diff --git a/retired/modules/ngap_module/tests/atlocal.in b/retired/modules/ngap_module/tests/atlocal.in new file mode 100644 index 0000000000..e69de29bb2 diff --git a/retired/modules/ngap_module/tests/bes-daac.conf b/retired/modules/ngap_module/tests/bes-daac.conf new file mode 100644 index 0000000000..6496aeadf0 --- /dev/null +++ b/retired/modules/ngap_module/tests/bes-daac.conf @@ -0,0 +1,8 @@ +# +# Switch to only using the DAAC S3 buckets for the DMR++ documents. +# +BES.Include = bes.conf + +# Use this with tests to force the use of the DAAC bucket even though the granules +# are in our (cloudydap) bucket too. jhrg 8/9/24 +NGAP.UseOPeNDAPBucket = false diff --git a/retired/modules/ngap_module/tests/bes.conf.in b/retired/modules/ngap_module/tests/bes.conf.in new file mode 100644 index 0000000000..a427dbbef5 --- /dev/null +++ b/retired/modules/ngap_module/tests/bes.conf.in @@ -0,0 +1,55 @@ +# +# Test the NGAP Container with both DAAC- and OPeNDAP-Owned S3 buckets. +# + +BES.ServerAdministrator = admin.email.address@your.domain.name + +BES.User = user_name +BES.Group = group_name + +BES.LogName = ./bes.log +BES.LogVerbose = no + +BES.modules = dap,cmd,ngap,dmrpp +# ,fonc +BES.module.dap = @abs_top_builddir@/dap/.libs/libdap_module.so +BES.module.cmd = @abs_top_builddir@/xmlcommand/.libs/libdap_xml_module.so +BES.module.dmrpp = @abs_top_builddir@/modules/dmrpp_module/.libs/libdmrpp_module.so +BES.module.ngap = @abs_top_builddir@/modules/ngap_module/.libs/libngap_module.so +BES.module.fonc = @abs_top_builddir@/modules/fileout_netcdf/.libs/libfonc_module.so + +BES.Catalog.catalog.RootDirectory = @abs_top_srcdir@/modules/ngap_module +BES.Data.RootDirectory = /dev/null + +BES.Catalog.catalog.TypeMatch += dmrpp:.*\.dmrpp$; + +BES.Catalog.catalog.Include = ; +BES.Catalog.catalog.Exclude = ^\..*; + +# Note: Cache is off for these tests since we get the same data from two sources. +NGAP.UseDMRppCache = false + +# This is how we tell the server that it's OK to use HTTP GET to access the DMR++ documents. +AllowedHosts = ^https://cloudydap.s3.us-east-1.amazonaws.com/.*$ + +CredentialsManager.config = @abs_top_srcdir@/modules/ngap_module/tests/CM.config + +Http.cache.effective.urls = true +Http.cache.effective.urls.skip.regex.pattern = ^https://.*\.s3\..*\.amazonaws\.com/.*$ + +# Note: By default, the tests in this directory read from a DMR++ in an OPeNDAP-owned +# S3 bucket. Credentials to read from this bucket are provided in the CM.config file. +# An EDL token is needed to read the data. With that token, you can also read the DMR++ +# from the DAAC-owned S3 bucket. The DMR++ files are a little different and so the tests +# for that case will need different baselines, but it's easy to see that the responses +# OK. Neither of these buckets are public and so the tests are not run by CICD. jhrg 8/9/24 + +# This is the default value - used for 'OPeNDAP-Owned' S3 bucket tests. +# Set this to your own S3 bucket where DMR++ documents can be found. +NGAP.DataSourceLocation = https://cloudydap.s3.us-east-1.amazonaws.com + +# Set this to true to try the OPeNDAP bucket for DMR++ documents. +NGAP.UseOPeNDAPBucket = true + +# set this to true to substitute data URLs in the DMR++ for the template href value. +NGAP.inject_data_urls = true diff --git a/retired/modules/ngap_module/tests/ngap/20180101000000-OSISAF-L3C_GHRSST-cloudydap.dap.bescmd b/retired/modules/ngap_module/tests/ngap/20180101000000-OSISAF-L3C_GHRSST-cloudydap.dap.bescmd new file mode 100644 index 0000000000..674ae165c4 --- /dev/null +++ b/retired/modules/ngap_module/tests/ngap/20180101000000-OSISAF-L3C_GHRSST-cloudydap.dap.bescmd @@ -0,0 +1,18 @@ + + + + 300 + no + xml + 0 + + collections/C2036877806-POCLOUD/granules/20180101000000-OSISAF-L3C_GHRSST-SSTsubskin-GOES16-ssteqc_goes16_20180101_000000-v02.0-fv01.0 + + + + /lat;/lon + + + + + diff --git a/retired/modules/ngap_module/tests/ngap/20180101000000-OSISAF-L3C_GHRSST-cloudydap.dap.bescmd.baseline b/retired/modules/ngap_module/tests/ngap/20180101000000-OSISAF-L3C_GHRSST-cloudydap.dap.bescmd.baseline new file mode 100644 index 0000000000..2cdd585cfe --- /dev/null +++ b/retired/modules/ngap_module/tests/ngap/20180101000000-OSISAF-L3C_GHRSST-cloudydap.dap.bescmd.baseline @@ -0,0 +1,523 @@ + + + + + + + + latitude + + + latitude + + + Y + + + degrees_north + + + -90.00000000 + + + 90.00000000 + + + geographical coordinates, WGS84 projection + + + lat + + + /lat + + + removed checksum + + + + + + longitude + + + longitude + + + X + + + degrees_east + + + -180.0000000 + + + 180.0000000 + + + geographical coordinates, WGS84 projection + + + lon + + + /lon + + + removed checksum + + + + CF-1.4 + + + Sea Surface Temperature + + + The L3C product derived from GOES16/ABI brightness temperatures. + + + Geostationary Sea Surface Temperature Product User Manual, http://www.osi-saf.org + + + OSISAF + + + METEO-FRANCE/CMS SAFOS processor + + + All intellectual property rights of the Ocean & Sea Ice SAF products belong to EUMETSAT. The use of these products is granted to every user, free of charge. If users wish to use these products, EUMETSAT's copyright credit must be shown by displaying the words 'Copyright EUMETSAT' under each of the products shown. EUMETSAT offers no warranty and accepts no liability in respect of the Ocean & Sea Ice SAF products. EUMETSAT neither commits to nor guarantees the continuity, availability, or quality or suitability for any purpose of, the Ocean & Sea Ice SAF products. + + + GOES16-OSISAF-L3C-v1.0 + + + org.ghrsst + + + 1.0 + + + 2.0 + + + 0.05 degree + + + 60.00000000 + + + -60.00000000 + + + -15.00000000 + + + -135.0000000 + + + GOES_ABI + + + GOES16 + + + GOES_ABI + + + Unidata Dataset Discovery v1.0 + + + N/A + + + Oceans > Ocean Temperature > Sea Surface Temperature + + + NASA Global Change Master Directory (GCMD) Science Keywords + + + NetCDF Climate and Forecast (CF) Metadata Convention + + + degrees_north + + + 0.050000000000000003 + + + degrees_east + + + 0.050000000000000003 + + + In case SAF data (pre-operational or operational) has been used for the study described in a paper the following sentence would be an appropriate reference to the funding coming from EUMETSAT: The data from the EUMETSAT Satellite Application Facility on Ocean & Sea Ice used in this study are accessible through the SAF's homepage http://www.osi-saf.org + + + O&SI SAF + + + osi-saf.helpdesk@meteo.fr + + + http://www.osi-saf.org + + + Group for High Resolution Sea Surface Temperature + + + The GHRSST Project Office + + + http://www.ghrsst.org + + + ghrsst-po@nceo.ac.uk + + + L3C + + + grid + + + 20180101T020918Z + + + 2 + + + 20171231T233000Z + + + 20171231T233000Z + + + 20180101T003000Z + + + 20180101T003000Z + + + D9299038-EE98-11E7-B2C3-0024E836CC1A + + + removed-version + + + + time + + + + + removed-version + + + removed-version + + + libdap-removed-version + + + +# TheBESKeys::get_as_config() +AllowedHosts=^https?:\/\/localhost(:8080)?\/.*$ # needed for tests +AllowedHosts+=^https:\/\/(sit\.|uat\.)?urs\.earthdata\.nasa.gov\/.*$ +AllowedHosts+=^https:\/\/cmr.(uat.|sit.)?earthdata.nasa.gov\/.*$ +AllowedHosts+=^https:\/\/goldsmr4\.gesdisc\.eosdis\.nasa\.gov\/.*$ +AllowedHosts+=^file:\/\/\/home\/centos\/hyrax\/build\/share\/hyrax\/.*$ +BES.CancelTimeoutOnSend=true +BES.Catalog.CMR.RootDirectory=UNUSED +BES.Catalog.CMR.TypeMatch=nc:.*\.nc(4)?(\.bz2|\.gz|\.Z)?$; +BES.Catalog.CMR.TypeMatch+=h4:.*\.(hdf|HDF|eos|HDFEOS)(\.bz2|\.gz|\.Z)?$; +BES.Catalog.CMR.TypeMatch+=h5:.*\.(HDF5|h5|he5)(\.bz2|\.gz|\.Z)?$; +BES.Catalog.CMR.TypeMatch+=ncml:.*\.ncml(\.bz2|\.gz|\.Z)?$; +BES.Catalog.Default=catalog +BES.Catalog.RemoteResources.RootDirectory=UNUSED +BES.Catalog.RemoteResources.TypeMatch=unused:unused; +BES.Catalog.catalog.Exclude=(^\..*$)|(^.*\.das$); +BES.Catalog.catalog.FollowSymLinks=No +BES.Catalog.catalog.Include=; +BES.Catalog.catalog.RootDirectory=/usr/share/hyrax +BES.Catalog.catalog.TypeMatch=csv:.*\.csv(\.bz2|\.gz|\.Z)?$; +BES.Catalog.catalog.TypeMatch+=reader:.*\.(dds|dods|data_ddx|dmr|dap)$; +BES.Catalog.catalog.TypeMatch+=dmrpp:.*\.(dmrpp)(\.bz2|\.gz|\.Z)?$; +BES.Catalog.catalog.TypeMatch+=ff:.*\.dat(\.bz2|\.gz|\.Z)?$; +BES.Catalog.catalog.TypeMatch+=gdal:.*\.(tif|TIF)$|.*\.grb\.(bz2|gz|Z)?$|.*\.jp2$|.*/gdal/.*\.jpg$; +BES.Catalog.catalog.TypeMatch+=h4:.*\.(hdf|HDF|eos|HDFEOS)(\.bz2|\.gz|\.Z)?$; +BES.Catalog.catalog.TypeMatch+=h5:.*\.(HDF5|h5|he5|H5)(\.bz2|\.gz|\.Z)?$; +BES.Catalog.catalog.TypeMatch+=nc:.*\.nc(4)?(\.bz2|\.gz|\.Z)?$; +BES.Catalog.catalog.TypeMatch+=ncml:.*\.ncml(\.bz2|\.gz|\.Z)?$; +BES.Catalog.catalog.TypeMatch+=h5:.*\.(HDF5|h5|he5|nc|nc4)(\.bz2|\.gz|\.Z)?$; +BES.Container.Persistence=strict +BES.Data.RootDirectory=/dev/null +BES.FollowSymLinks=No +BES.Group=bes +BES.Help.HTML=/usr/share/bes/bes_help.html +BES.Help.TXT=/usr/share/bes/bes_help.txt +BES.Help.XML=/usr/share/bes/bes_help.xml +BES.Include=modules/.*\.conf$ +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=fonc.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=site.conf +BES.Info.Buffered=no +BES.Info.Type=xml +BES.LogName=/var/log/bes/bes.log +BES.LogUnixTime=true +BES.LogVerbose=false +BES.MaxResponseSize.bytes=8329006592 +BES.MaxVariableSize.bytes=8589934592 +BES.Memory.GlobalArea.ControlHeap=no +BES.Memory.GlobalArea.EmergencyPoolSize=1 +BES.Memory.GlobalArea.MaximumHeapSize=20 +BES.Memory.GlobalArea.Verbose=no +BES.ProcessManagerMethod=multiple +BES.ServerAdministrator=email:ngap@opendap.org +BES.ServerAdministrator+=organization:OPeNDAP Inc. +BES.ServerAdministrator+=street:165 NW Dean Knauss Dr. +BES.ServerAdministrator+=city:Narragansett +BES.ServerAdministrator+=region:RI +BES.ServerAdministrator+=postalCode:02882 +BES.ServerAdministrator+=country:US +BES.ServerAdministrator+=telephone:+removed-version.4835 +BES.ServerAdministrator+=website:http://www.opendap.org +BES.ServerPort=10022 +BES.ServerSecure=no +BES.SetSockRecvSize=No +BES.SetSockSendSize=No +BES.SockRecvSize=65535 +BES.SockSendSize=65535 +BES.UncompressCache.dir=/var/cache/bes/hyrax_ux +BES.UncompressCache.prefix=ux_ +BES.UncompressCache.size=500 +BES.User=bes +BES.module.ascii=/usr/lib64/bes/libascii_module.so +BES.module.builddmrpp=/usr/lib64/bes/libbuilddmrpp_module.so +BES.module.cmr=/usr/lib64/bes/libcmr_module.so +BES.module.csv=/usr/lib64/bes/libcsv_module.so +BES.module.dap=/usr/lib64/bes/libdap_module.so +BES.module.dapcmd=/usr/lib64/bes/libdap_xml_module.so +BES.module.dmrpp=/usr/lib64/bes/libdmrpp_module.so +BES.module.ff=/usr/lib64/bes/libff_module.so +BES.module.focovjson=/usr/lib64/bes/libfocovjson_module.so +BES.module.fojson=/usr/lib64/bes/libfojson_module.so +BES.module.fonc=/usr/lib64/bes/libfonc_module.so +BES.module.functions=/usr/lib64/bes/libfunctions_module.so +BES.module.gateway=/usr/lib64/bes/libgateway_module.so +BES.module.gdal=/usr/lib64/bes/libgdal_module.so +BES.module.h4=/usr/lib64/bes/libhdf4_module.so +BES.module.h5=/usr/lib64/bes/libhdf5_module.so +BES.module.httpd=/usr/lib64/bes/libhttpd_catalog_module.so +BES.module.nc=/usr/lib64/bes/libnc_module.so +BES.module.ncml=/usr/lib64/bes/libncml_module.so +BES.module.ngap=/usr/lib64/bes/libngap_module.so +BES.module.reader=/usr/lib64/bes/libdapreader_module.so +BES.module.s3=/usr/lib64/bes/libs3_reader.so +BES.module.sample=/usr/lib64/bes/libsample_module.so +BES.module.ugrid_functions=/usr/lib64/bes/libugrid_functions.so +BES.module.usage=/usr/lib64/bes/libusage_module.so +BES.module.w10n=/usr/lib64/bes/libw10n_handler.so +BES.module.xml_data=/usr/lib64/bes/libxml_data_module.so +BES.modules=dap,dapcmd +BES.modules+=ascii +BES.modules+=builddmrpp +BES.modules+=csv +BES.modules+=reader +BES.modules+=fonc +BES.modules+=dmrpp +BES.modules+=ff +BES.modules+=focovjson +BES.modules+=fojson +BES.modules+=functions +BES.modules+=gateway +BES.modules+=gdal +BES.modules+=h4 +BES.modules+=h5 +BES.modules+=nc +BES.modules+=ncml +BES.modules+=ngap +BES.modules+=s3 +BES.modules+=sample +BES.modules+=ugrid_functions +BES.modules+=usage +BES.modules+=w10n +BES.modules+=xml_data +CMR.Collections=C1276812863-GES_DISC +CMR.Collections+=C1222931489-GHRC_CLOUD +CMR.Collections+=C1222931739-GHRC_CLOUD +CMR.Facets=temporal +CMR.Reference=http://docs.opendap.org/index.php/BES_-_Modules_-_CMR_Catalog +CMR.host.url=https://cmr.earthdata.nasa.gov +DAP.Async.StyleSheet.Ref=/opendap/xsl/asyncResponse.xsl +DAP.FunctionResponseCache.path=/tmp/hyrax_func +DAP.FunctionResponseCache.prefix=func_ +DAP.FunctionResponseCache.size=20000 +DAP.GlobalMetadataStore.ledger=/usr/share/mds/mds_ledger.txt +DAP.GlobalMetadataStore.prefix=mds_ +DAP.GlobalMetadataStore.size=200 +DAP.Help.HTML=/usr/share/bes/dap_help.html +DAP.Help.TXT=/usr/share/bes/dap_help.txt +DAP.Help.XML=/usr/share/bes/dap_help.xml +DAP.StoredResultsCache.prefix=result_ +DAP.StoredResultsCache.size=20000 +DAP.StoredResultsCache.subdir=stored_results +DMRPP.MaxComputeThreads=512 +DMRPP.MaxParallelTransfers=16 +DMRPP.UseComputeThreads=true +DMRPP.UseParallelTransfers=false +DR.UseSeriesValues=false +DR.UseTestTypes=true +FONc.ChunkSize=4096 +FONc.ClassicModel=false +FONc.Reference=http://docs.opendap.org/index.php/BES_-_Modules_-_FileOut_Netcdf +FONc.RequestMaxSizeKB=0 +FONc.Tempdir=/tmp/hyrax_fonc +FONc.UseCompression=true +FONg.GeoTiff.band.type.byte=true +FONg.Reference=http://docs.opendap.org/index.php/BES_-_Modules_-_FileOut_GDAL +FONg.Tempdir=/tmp/hyrax_fong +FONg.default_gcs=WGS84 +FoCovJson.Reference=http://docs.opendap.org/index.php/BES_-_Modules_-_FileOut_CovJSON +FoCovJson.Tempdir=/tmp +FoJson.Reference=http://docs.opendap.org/index.php/BES_-_Modules_-_FileOut_JSON +FoJson.Tempdir=/tmp +Gateway.Cache.dir=/tmp/hyrax_gw +Gateway.Cache.prefix=gw_ +Gateway.Cache.size=500 +Gateway.MimeTypes=nc:application/x-netcdf +Gateway.MimeTypes+=h4:application/x-hdf +Gateway.MimeTypes+=h5:application/x-hdf5 +H4.Cache.metadata.path=/tmp/md +H4.DisableECSMetaDataAll=false +H4.DisableECSMetaDataMin=true +H4.DisableScaleOffsetComp=true +H4.DisableStructMetaAttr=true +H4.DisableSwathDimMap=false +H4.DisableVdataNameclashingCheck=true +H4.EnableCERESMERRAShortName=true +H4.EnableCERESVdata=false +H4.EnableCF=true +H4.EnableCheckMODISGeoFile=false +H4.EnableCheckScaleOffsetType=false +H4.EnableDataCacheFile=false +H4.EnableEOSGeoCacheFile=false +H4.EnableHybridVdata=true +H4.EnableMetaDataCacheFile=false +H4.EnablePassFileID=false +H4.EnableSpecialEOS=true +H4.EnableSwathGridAttr=true +H4.EnableVdataDescAttr=false +H4.EnableVdata_to_Attr=true +H4.EnableVgroupAttr=true +H5.Cache.latlon.path=/tmp/latlon +H5.Cache.latlon.prefix=l +H5.Cache.latlon.size=20000 +H5.CheckIgnoreObj=false +H5.DefaultHandleDimension=true +H5.DisableECSMetaAttr=false +H5.DisableStructMetaAttr=true +H5.DiskCacheComp=false +H5.DiskCacheCompThreshold=2.0 +H5.DiskCacheCompVarSize=100 +H5.DiskCacheDataPath=/tmp +H5.DiskCacheFilePrefix=c +H5.DiskCacheFloatOnlyComp=true +H5.DiskCacheSize=100000 +H5.EnableAddPathAttrs=true +H5.EnableCF=true +H5.EnableCFDMR=true +H5.EnableCheckNameClashing=false +H5.EnableCoorattrAddPath=true +H5.EnableDAP4Coverage=true +H5.EnableDMR64bitInt=true +H5.EnableDiskDataCache=false +H5.EnableDiskMetaDataCache=false +H5.EnableDropLongString=true +H5.EnableEOSGeoCacheFile=false +H5.EnableFillValueCheck=true +H5.EnablePassFileID=false +H5.EscapeUTF8Attr=true +H5.ForceFlattenNDCoorAttr=true +H5.KeepVarLeadingUnderscore=false +H5.LargeDataMemCacheConfig=false +H5.LargeDataMemCacheEntries=0 +H5.MetaDataMemCacheEntries=1000 +H5.NoZeroSizeFullnameAttr=false +H5.RmConventionAttrPath=true +H5.SmallDataMemCacheEntries=0 +HDF4.Cache.latlon.path=/tmp/latlon +HDF4.Cache.latlon.prefix=l +HDF4.Cache.latlon.size=20000 +HDF4.CacheDir=/tmp +Http.Cookies.File=/tmp/hyrax_cookies/cf +Http.MimeTypes=nc:application/x-netcdf +Http.MimeTypes+=h4:application/x-hdf +Http.MimeTypes+=h5:application/x-hdf5 +Http.No.Retry.Regex=^https:\/\/.*\?code\=.*$ +Http.UserAgent=hyrax-prod +Http.cache.effective.urls=true +Http.cache.effective.urls.skip.regex.pattern=^https:\/\/.*s3(\.|-).*\.amazonaws\.com\/.*$ +Http.netrc.file=/etc/bes/ngap_netrc +Httpd_Catalog.Collections=test:http://test.opendap.org/data/ +Httpd_Catalog.Reference=http://docs.opendap.org/index.php/BES_-_Modules_-_Httpd_Catalog +NC.CacheEntries=100 +NC.PromoteByteToShort=true +NC.ShowSharedDimensions=true +NC.UseMDS=false +NCML.DimensionCache.directory=/tmp/hyrax_ncml +NCML.DimensionCache.prefix=ncml_ +NCML.DimensionCache.size=2000 +NGAP.CMRCachePurge=20 +NGAP.CMRCacheSize=100 +NGAP.DMRppCachePurge=20 +NGAP.DMRppCacheSize=100 +NGAP.DMRppFileCacheDir=/tmp/hyrax_ngap_cache +NGAP.DMRppFileCachePurge.MB=2000 +NGAP.DMRppFileCacheSize.MB=10000 +NGAP.UseCMRCache=true +NGAP.UseDMRppCache=true +NGAP.cmr_host_url=https://cmr.earthdata.nasa.gov +NGAP.inject_data_urls=true +Say.LogName=@prefix@/var/say.log +SupportEmail=support@opendap.org +s3.inject_data_urls=true +w10n.Reference=http://docs.opendap.org/index.php/BES_-_Modules_-_w10n_handler +w10n.Tempdir=/tmp + + + + https://opendap.earthdata.nasa.gov/build_dmrpp/collections/C2036877806-POCLOUD/granules/20180101000000-OSISAF-L3C_GHRSST-SSTsubskin-GOES16-ssteqc_goes16_20180101_000000-v02.0-fv01.0 + + + + +The data: +Float32 lat[lat = 2400] = {-59.975, -59.925, -59.875, -59.825, -59.775, -59.725, -59.675, -59.625, -59.575, -59.525, -59.475, -59.425, -59.375, -59.325, -59.275, -59.225, -59.175, -59.125, -59.075, -59.025, -58.975, -58.925, -58.875, -58.825, -58.775, -58.725, -58.675, -58.625, -58.575, -58.525, -58.475, -58.425, -58.375, -58.325, -58.275, -58.225, -58.175, -58.125, -58.075, -58.025, -57.975, -57.925, -57.875, -57.825, -57.775, -57.725, -57.675, -57.625, -57.575, -57.525, -57.475, -57.425, -57.375, -57.325, -57.275, -57.225, -57.175, -57.125, -57.075, -57.025, -56.975, -56.925, -56.875, -56.825, -56.775, -56.725, -56.675, -56.625, -56.575, -56.525, -56.475, -56.425, -56.375, -56.325, -56.275, -56.225, -56.175, -56.125, -56.075, -56.025, -55.975, -55.925, -55.875, -55.825, -55.775, -55.725, -55.675, -55.625, -55.575, -55.525, -55.475, -55.425, -55.375, -55.325, -55.275, -55.225, -55.175, -55.125, -55.075, -55.025, -54.975, -54.925, -54.875, -54.825, -54.775, -54.725, -54.675, -54.625, -54.575, -54.525, -54.475, -54.425, -54.375, -54.325, -54.275, -54.225, -54.175, -54.125, -54.075, -54.025, -53.975, -53.925, -53.875, -53.825, -53.775, -53.725, -53.675, -53.625, -53.575, -53.525, -53.475, -53.425, -53.375, -53.325, -53.275, -53.225, -53.175, -53.125, -53.075, -53.025, -52.975, -52.925, -52.875, -52.825, -52.775, -52.725, -52.675, -52.625, -52.575, -52.525, -52.475, -52.425, -52.375, -52.325, -52.275, -52.225, -52.175, -52.125, -52.075, -52.025, -51.975, -51.925, -51.875, -51.825, -51.775, -51.725, -51.675, -51.625, -51.575, -51.525, -51.475, -51.425, -51.375, -51.325, -51.275, -51.225, -51.175, -51.125, -51.075, -51.025, -50.975, -50.925, -50.875, -50.825, -50.775, -50.725, -50.675, -50.625, -50.575, -50.525, -50.475, -50.425, -50.375, -50.325, -50.275, -50.225, -50.175, -50.125, -50.075, -50.025, -49.975, -49.925, -49.875, -49.825, -49.775, -49.725, -49.675, -49.625, -49.575, -49.525, -49.475, -49.425, -49.375, -49.325, -49.275, -49.225, -49.175, -49.125, -49.075, -49.025, -48.975, -48.925, -48.875, -48.825, -48.775, -48.725, -48.675, -48.625, -48.575, -48.525, -48.475, -48.425, -48.375, -48.325, -48.275, -48.225, -48.175, -48.125, -48.075, -48.025, -47.975, -47.925, -47.875, -47.825, -47.775, -47.725, -47.675, -47.625, -47.575, -47.525, -47.475, -47.425, -47.375, -47.325, -47.275, -47.225, -47.175, -47.125, -47.075, -47.025, -46.975, -46.925, -46.875, -46.825, -46.775, -46.725, -46.675, -46.625, -46.575, -46.525, -46.475, -46.425, -46.375, -46.325, -46.275, -46.225, -46.175, -46.125, -46.075, -46.025, -45.975, -45.925, -45.875, -45.825, -45.775, -45.725, -45.675, -45.625, -45.575, -45.525, -45.475, -45.425, -45.375, -45.325, -45.275, -45.225, -45.175, -45.125, -45.075, -45.025, -44.975, -44.925, -44.875, -44.825, -44.775, -44.725, -44.675, -44.625, -44.575, -44.525, -44.475, -44.425, -44.375, -44.325, -44.275, -44.225, -44.175, -44.125, -44.075, -44.025, -43.975, -43.925, -43.875, -43.825, -43.775, -43.725, -43.675, -43.625, -43.575, -43.525, -43.475, -43.425, -43.375, -43.325, -43.275, -43.225, -43.175, -43.125, -43.075, -43.025, -42.975, -42.925, -42.875, -42.825, -42.775, -42.725, -42.675, -42.625, -42.575, -42.525, -42.475, -42.425, -42.375, -42.325, -42.275, -42.225, -42.175, -42.125, -42.075, -42.025, -41.975, -41.925, -41.875, -41.825, -41.775, -41.725, -41.675, -41.625, -41.575, -41.525, -41.475, -41.425, -41.375, -41.325, -41.275, -41.225, -41.175, -41.125, -41.075, -41.025, -40.975, -40.925, -40.875, -40.825, -40.775, -40.725, -40.675, -40.625, -40.575, -40.525, -40.475, -40.425, -40.375, -40.325, -40.275, -40.225, -40.175, -40.125, -40.075, -40.025, -39.975, -39.925, -39.875, -39.825, -39.775, -39.725, -39.675, -39.625, -39.575, -39.525, -39.475, -39.425, -39.375, -39.325, -39.275, -39.225, -39.175, -39.125, -39.075, -39.025, -38.975, -38.925, -38.875, -38.825, -38.775, -38.725, -38.675, -38.625, -38.575, -38.525, -38.475, -38.425, -38.375, -38.325, -38.275, -38.225, -38.175, -38.125, -38.075, -38.025, -37.975, -37.925, -37.875, -37.825, -37.775, -37.725, -37.675, -37.625, -37.575, -37.525, -37.475, -37.425, -37.375, -37.325, -37.275, -37.225, -37.175, -37.125, -37.075, -37.025, -36.975, -36.925, -36.875, -36.825, -36.775, -36.725, -36.675, -36.625, -36.575, -36.525, -36.475, -36.425, -36.375, -36.325, -36.275, -36.225, -36.175, -36.125, -36.075, -36.025, -35.975, -35.925, -35.875, -35.825, -35.775, -35.725, -35.675, -35.625, -35.575, -35.525, -35.475, -35.425, -35.375, -35.325, -35.275, -35.225, -35.175, -35.125, -35.075, -35.025, -34.975, -34.925, -34.875, -34.825, -34.775, -34.725, -34.675, -34.625, -34.575, -34.525, -34.475, -34.425, -34.375, -34.325, -34.275, -34.225, -34.175, -34.125, -34.075, -34.025, -33.975, -33.925, -33.875, -33.825, -33.775, -33.725, -33.675, -33.625, -33.575, -33.525, -33.475, -33.425, -33.375, -33.325, -33.275, -33.225, -33.175, -33.125, -33.075, -33.025, -32.975, -32.925, -32.875, -32.825, -32.775, -32.725, -32.675, -32.625, -32.575, -32.525, -32.475, -32.425, -32.375, -32.325, -32.275, -32.225, -32.175, -32.125, -32.075, -32.025, -31.975, -31.925, -31.875, -31.825, -31.775, -31.725, -31.675, -31.625, -31.575, -31.525, -31.475, -31.425, -31.375, -31.325, -31.275, -31.225, -31.175, -31.125, -31.075, -31.025, -30.975, -30.925, -30.875, -30.825, -30.775, -30.725, -30.675, -30.625, -30.575, -30.525, -30.475, -30.425, -30.375, -30.325, -30.275, -30.225, -30.175, -30.125, -30.075, -30.025, -29.975, -29.925, -29.875, -29.825, -29.775, -29.725, -29.675, -29.625, -29.575, -29.525, -29.475, -29.425, -29.375, -29.325, -29.275, -29.225, -29.175, -29.125, -29.075, -29.025, -28.975, -28.925, -28.875, -28.825, -28.775, -28.725, -28.675, -28.625, -28.575, -28.525, -28.475, -28.425, -28.375, -28.325, -28.275, -28.225, -28.175, -28.125, -28.075, -28.025, -27.975, -27.925, -27.875, -27.825, -27.775, -27.725, -27.675, -27.625, -27.575, -27.525, -27.475, -27.425, -27.375, -27.325, -27.275, -27.225, -27.175, -27.125, -27.075, -27.025, -26.975, -26.925, -26.875, -26.825, -26.775, -26.725, -26.675, -26.625, -26.575, -26.525, -26.475, -26.425, -26.375, -26.325, -26.275, -26.225, -26.175, -26.125, -26.075, -26.025, -25.975, -25.925, -25.875, -25.825, -25.775, -25.725, -25.675, -25.625, -25.575, -25.525, -25.475, -25.425, -25.375, -25.325, -25.275, -25.225, -25.175, -25.125, -25.075, -25.025, -24.975, -24.925, -24.875, -24.825, -24.775, -24.725, -24.675, -24.625, -24.575, -24.525, -24.475, -24.425, -24.375, -24.325, -24.275, -24.225, -24.175, -24.125, -24.075, -24.025, -23.975, -23.925, -23.875, -23.825, -23.775, -23.725, -23.675, -23.625, -23.575, -23.525, -23.475, -23.425, -23.375, -23.325, -23.275, -23.225, -23.175, -23.125, -23.075, -23.025, -22.975, -22.925, -22.875, -22.825, -22.775, -22.725, -22.675, -22.625, -22.575, -22.525, -22.475, -22.425, -22.375, -22.325, -22.275, -22.225, -22.175, -22.125, -22.075, -22.025, -21.975, -21.925, -21.875, -21.825, -21.775, -21.725, -21.675, -21.625, -21.575, -21.525, -21.475, -21.425, -21.375, -21.325, -21.275, -21.225, -21.175, -21.125, -21.075, -21.025, -20.975, -20.925, -20.875, -20.825, -20.775, -20.725, -20.675, -20.625, -20.575, -20.525, -20.475, -20.425, -20.375, -20.325, -20.275, -20.225, -20.175, -20.125, -20.075, -20.025, -19.975, -19.925, -19.875, -19.825, -19.775, -19.725, -19.675, -19.625, -19.575, -19.525, -19.475, -19.425, -19.375, -19.325, -19.275, -19.225, -19.175, -19.125, -19.075, -19.025, -18.975, -18.925, -18.875, -18.825, -18.775, -18.725, -18.675, -18.625, -18.575, -18.525, -18.475, -18.425, -18.375, -18.325, -18.275, -18.225, -18.175, -18.125, -18.075, -18.025, -17.975, -17.925, -17.875, -17.825, -17.775, -17.725, -17.675, -17.625, -17.575, -17.525, -17.475, -17.425, -17.375, -17.325, -17.275, -17.225, -17.175, -17.125, -17.075, -17.025, -16.975, -16.925, -16.875, -16.825, -16.775, -16.725, -16.675, -16.625, -16.575, -16.525, -16.475, -16.425, -16.375, -16.325, -16.275, -16.225, -16.175, -16.125, -16.075, -16.025, -15.975, -15.925, -15.875, -15.825, -15.775, -15.725, -15.675, -15.625, -15.575, -15.525, -15.475, -15.425, -15.375, -15.325, -15.275, -15.225, -15.175, -15.125, -15.075, -15.025, -14.975, -14.925, -14.875, -14.825, -14.775, -14.725, -14.675, -14.625, -14.575, -14.525, -14.475, -14.425, -14.375, -14.325, -14.275, -14.225, -14.175, -14.125, -14.075, -14.025, -13.975, -13.925, -13.875, -13.825, -13.775, -13.725, -13.675, -13.625, -13.575, -13.525, -13.475, -13.425, -13.375, -13.325, -13.275, -13.225, -13.175, -13.125, -13.075, -13.025, -12.975, -12.925, -12.875, -12.825, -12.775, -12.725, -12.675, -12.625, -12.575, -12.525, -12.475, -12.425, -12.375, -12.325, -12.275, -12.225, -12.175, -12.125, -12.075, -12.025, -11.975, -11.925, -11.875, -11.825, -11.775, -11.725, -11.675, -11.625, -11.575, -11.525, -11.475, -11.425, -11.375, -11.325, -11.275, -11.225, -11.175, -11.125, -11.075, -11.025, -10.975, -10.925, -10.875, -10.825, -10.775, -10.725, -10.675, -10.625, -10.575, -10.525, -10.475, -10.425, -10.375, -10.325, -10.275, -10.225, -10.175, -10.125, -10.075, -10.025, -9.975, -9.925, -9.875, -9.825, -9.775, -9.725, -9.675, -9.625, -9.575, -9.525, -9.475, -9.425, -9.375, -9.325, -9.275, -9.225, -9.175, -9.125, -9.075, -9.025, -8.975, -8.925, -8.875, -8.825, -8.775, -8.725, -8.675, -8.625, -8.575, -8.525, -8.475, -8.425, -8.375, -8.325, -8.275, -8.225, -8.175, -8.125, -8.075, -8.025, -7.975, -7.925, -7.875, -7.825, -7.775, -7.725, -7.675, -7.625, -7.575, -7.525, -7.475, -7.425, -7.375, -7.325, -7.275, -7.225, -7.175, -7.125, -7.075, -7.025, -6.975, -6.925, -6.875, -6.825, -6.775, -6.725, -6.675, -6.625, -6.575, -6.525, -6.475, -6.425, -6.375, -6.325, -6.275, -6.225, -6.175, -6.125, -6.075, -6.025, -5.975, -5.925, -5.875, -5.825, -5.775, -5.725, -5.675, -5.625, -5.575, -5.525, -5.475, -5.425, -5.375, -5.325, -5.275, -5.225, -5.175, -5.125, -5.075, -5.025, -4.975, -4.925, -4.875, -4.825, -4.775, -4.725, -4.675, -4.625, -4.575, -4.525, -4.475, -4.425, -4.375, -4.325, -4.275, -4.225, -4.175, -4.125, -4.075, -4.025, -3.975, -3.925, -3.875, -3.825, -3.775, -3.725, -3.675, -3.625, -3.575, -3.525, -3.475, -3.425, -3.375, -3.325, -3.275, -3.225, -3.175, -3.125, -3.075, -3.025, -2.975, -2.925, -2.875, -2.825, -2.775, -2.725, -2.675, -2.625, -2.575, -2.525, -2.475, -2.425, -2.375, -2.325, -2.275, -2.225, -2.175, -2.125, -2.075, -2.025, -1.975, -1.925, -1.875, -1.825, -1.775, -1.725, -1.675, -1.625, -1.575, -1.525, -1.475, -1.425, -1.375, -1.325, -1.275, -1.225, -1.175, -1.125, -1.075, -1.025, -0.975, -0.925, -0.875, -0.825, -0.775, -0.725, -0.675, -0.625, -0.575, -0.525, -0.475, -0.425, -0.375, -0.325, -0.275, -0.225, -0.175, -0.125, -0.075, -0.025, 0.025, 0.075, 0.125, 0.175, 0.225, 0.275, 0.325, 0.375, 0.425, 0.475, 0.525, 0.575, 0.625, 0.675, 0.725, 0.775, 0.825, 0.875, 0.925, 0.975, 1.025, 1.075, 1.125, 1.175, 1.225, 1.275, 1.325, 1.375, 1.425, 1.475, 1.525, 1.575, 1.625, 1.675, 1.725, 1.775, 1.825, 1.875, 1.925, 1.975, 2.025, 2.075, 2.125, 2.175, 2.225, 2.275, 2.325, 2.375, 2.425, 2.475, 2.525, 2.575, 2.625, 2.675, 2.725, 2.775, 2.825, 2.875, 2.925, 2.975, 3.025, 3.075, 3.125, 3.175, 3.225, 3.275, 3.325, 3.375, 3.425, 3.475, 3.525, 3.575, 3.625, 3.675, 3.725, 3.775, 3.825, 3.875, 3.925, 3.975, 4.025, 4.075, 4.125, 4.175, 4.225, 4.275, 4.325, 4.375, 4.425, 4.475, 4.525, 4.575, 4.625, 4.675, 4.725, 4.775, 4.825, 4.875, 4.925, 4.975, 5.025, 5.075, 5.125, 5.175, 5.225, 5.275, 5.325, 5.375, 5.425, 5.475, 5.525, 5.575, 5.625, 5.675, 5.725, 5.775, 5.825, 5.875, 5.925, 5.975, 6.025, 6.075, 6.125, 6.175, 6.225, 6.275, 6.325, 6.375, 6.425, 6.475, 6.525, 6.575, 6.625, 6.675, 6.725, 6.775, 6.825, 6.875, 6.925, 6.975, 7.025, 7.075, 7.125, 7.175, 7.225, 7.275, 7.325, 7.375, 7.425, 7.475, 7.525, 7.575, 7.625, 7.675, 7.725, 7.775, 7.825, 7.875, 7.925, 7.975, 8.025, 8.075, 8.125, 8.175, 8.225, 8.275, 8.325, 8.375, 8.425, 8.475, 8.525, 8.575, 8.625, 8.675, 8.725, 8.775, 8.825, 8.875, 8.925, 8.975, 9.025, 9.075, 9.125, 9.175, 9.225, 9.275, 9.325, 9.375, 9.425, 9.475, 9.525, 9.575, 9.625, 9.675, 9.725, 9.775, 9.825, 9.875, 9.925, 9.975, 10.025, 10.075, 10.125, 10.175, 10.225, 10.275, 10.325, 10.375, 10.425, 10.475, 10.525, 10.575, 10.625, 10.675, 10.725, 10.775, 10.825, 10.875, 10.925, 10.975, 11.025, 11.075, 11.125, 11.175, 11.225, 11.275, 11.325, 11.375, 11.425, 11.475, 11.525, 11.575, 11.625, 11.675, 11.725, 11.775, 11.825, 11.875, 11.925, 11.975, 12.025, 12.075, 12.125, 12.175, 12.225, 12.275, 12.325, 12.375, 12.425, 12.475, 12.525, 12.575, 12.625, 12.675, 12.725, 12.775, 12.825, 12.875, 12.925, 12.975, 13.025, 13.075, 13.125, 13.175, 13.225, 13.275, 13.325, 13.375, 13.425, 13.475, 13.525, 13.575, 13.625, 13.675, 13.725, 13.775, 13.825, 13.875, 13.925, 13.975, 14.025, 14.075, 14.125, 14.175, 14.225, 14.275, 14.325, 14.375, 14.425, 14.475, 14.525, 14.575, 14.625, 14.675, 14.725, 14.775, 14.825, 14.875, 14.925, 14.975, 15.025, 15.075, 15.125, 15.175, 15.225, 15.275, 15.325, 15.375, 15.425, 15.475, 15.525, 15.575, 15.625, 15.675, 15.725, 15.775, 15.825, 15.875, 15.925, 15.975, 16.025, 16.075, 16.125, 16.175, 16.225, 16.275, 16.325, 16.375, 16.425, 16.475, 16.525, 16.575, 16.625, 16.675, 16.725, 16.775, 16.825, 16.875, 16.925, 16.975, 17.025, 17.075, 17.125, 17.175, 17.225, 17.275, 17.325, 17.375, 17.425, 17.475, 17.525, 17.575, 17.625, 17.675, 17.725, 17.775, 17.825, 17.875, 17.925, 17.975, 18.025, 18.075, 18.125, 18.175, 18.225, 18.275, 18.325, 18.375, 18.425, 18.475, 18.525, 18.575, 18.625, 18.675, 18.725, 18.775, 18.825, 18.875, 18.925, 18.975, 19.025, 19.075, 19.125, 19.175, 19.225, 19.275, 19.325, 19.375, 19.425, 19.475, 19.525, 19.575, 19.625, 19.675, 19.725, 19.775, 19.825, 19.875, 19.925, 19.975, 20.025, 20.075, 20.125, 20.175, 20.225, 20.275, 20.325, 20.375, 20.425, 20.475, 20.525, 20.575, 20.625, 20.675, 20.725, 20.775, 20.825, 20.875, 20.925, 20.975, 21.025, 21.075, 21.125, 21.175, 21.225, 21.275, 21.325, 21.375, 21.425, 21.475, 21.525, 21.575, 21.625, 21.675, 21.725, 21.775, 21.825, 21.875, 21.925, 21.975, 22.025, 22.075, 22.125, 22.175, 22.225, 22.275, 22.325, 22.375, 22.425, 22.475, 22.525, 22.575, 22.625, 22.675, 22.725, 22.775, 22.825, 22.875, 22.925, 22.975, 23.025, 23.075, 23.125, 23.175, 23.225, 23.275, 23.325, 23.375, 23.425, 23.475, 23.525, 23.575, 23.625, 23.675, 23.725, 23.775, 23.825, 23.875, 23.925, 23.975, 24.025, 24.075, 24.125, 24.175, 24.225, 24.275, 24.325, 24.375, 24.425, 24.475, 24.525, 24.575, 24.625, 24.675, 24.725, 24.775, 24.825, 24.875, 24.925, 24.975, 25.025, 25.075, 25.125, 25.175, 25.225, 25.275, 25.325, 25.375, 25.425, 25.475, 25.525, 25.575, 25.625, 25.675, 25.725, 25.775, 25.825, 25.875, 25.925, 25.975, 26.025, 26.075, 26.125, 26.175, 26.225, 26.275, 26.325, 26.375, 26.425, 26.475, 26.525, 26.575, 26.625, 26.675, 26.725, 26.775, 26.825, 26.875, 26.925, 26.975, 27.025, 27.075, 27.125, 27.175, 27.225, 27.275, 27.325, 27.375, 27.425, 27.475, 27.525, 27.575, 27.625, 27.675, 27.725, 27.775, 27.825, 27.875, 27.925, 27.975, 28.025, 28.075, 28.125, 28.175, 28.225, 28.275, 28.325, 28.375, 28.425, 28.475, 28.525, 28.575, 28.625, 28.675, 28.725, 28.775, 28.825, 28.875, 28.925, 28.975, 29.025, 29.075, 29.125, 29.175, 29.225, 29.275, 29.325, 29.375, 29.425, 29.475, 29.525, 29.575, 29.625, 29.675, 29.725, 29.775, 29.825, 29.875, 29.925, 29.975, 30.025, 30.075, 30.125, 30.175, 30.225, 30.275, 30.325, 30.375, 30.425, 30.475, 30.525, 30.575, 30.625, 30.675, 30.725, 30.775, 30.825, 30.875, 30.925, 30.975, 31.025, 31.075, 31.125, 31.175, 31.225, 31.275, 31.325, 31.375, 31.425, 31.475, 31.525, 31.575, 31.625, 31.675, 31.725, 31.775, 31.825, 31.875, 31.925, 31.975, 32.025, 32.075, 32.125, 32.175, 32.225, 32.275, 32.325, 32.375, 32.425, 32.475, 32.525, 32.575, 32.625, 32.675, 32.725, 32.775, 32.825, 32.875, 32.925, 32.975, 33.025, 33.075, 33.125, 33.175, 33.225, 33.275, 33.325, 33.375, 33.425, 33.475, 33.525, 33.575, 33.625, 33.675, 33.725, 33.775, 33.825, 33.875, 33.925, 33.975, 34.025, 34.075, 34.125, 34.175, 34.225, 34.275, 34.325, 34.375, 34.425, 34.475, 34.525, 34.575, 34.625, 34.675, 34.725, 34.775, 34.825, 34.875, 34.925, 34.975, 35.025, 35.075, 35.125, 35.175, 35.225, 35.275, 35.325, 35.375, 35.425, 35.475, 35.525, 35.575, 35.625, 35.675, 35.725, 35.775, 35.825, 35.875, 35.925, 35.975, 36.025, 36.075, 36.125, 36.175, 36.225, 36.275, 36.325, 36.375, 36.425, 36.475, 36.525, 36.575, 36.625, 36.675, 36.725, 36.775, 36.825, 36.875, 36.925, 36.975, 37.025, 37.075, 37.125, 37.175, 37.225, 37.275, 37.325, 37.375, 37.425, 37.475, 37.525, 37.575, 37.625, 37.675, 37.725, 37.775, 37.825, 37.875, 37.925, 37.975, 38.025, 38.075, 38.125, 38.175, 38.225, 38.275, 38.325, 38.375, 38.425, 38.475, 38.525, 38.575, 38.625, 38.675, 38.725, 38.775, 38.825, 38.875, 38.925, 38.975, 39.025, 39.075, 39.125, 39.175, 39.225, 39.275, 39.325, 39.375, 39.425, 39.475, 39.525, 39.575, 39.625, 39.675, 39.725, 39.775, 39.825, 39.875, 39.925, 39.975, 40.025, 40.075, 40.125, 40.175, 40.225, 40.275, 40.325, 40.375, 40.425, 40.475, 40.525, 40.575, 40.625, 40.675, 40.725, 40.775, 40.825, 40.875, 40.925, 40.975, 41.025, 41.075, 41.125, 41.175, 41.225, 41.275, 41.325, 41.375, 41.425, 41.475, 41.525, 41.575, 41.625, 41.675, 41.725, 41.775, 41.825, 41.875, 41.925, 41.975, 42.025, 42.075, 42.125, 42.175, 42.225, 42.275, 42.325, 42.375, 42.425, 42.475, 42.525, 42.575, 42.625, 42.675, 42.725, 42.775, 42.825, 42.875, 42.925, 42.975, 43.025, 43.075, 43.125, 43.175, 43.225, 43.275, 43.325, 43.375, 43.425, 43.475, 43.525, 43.575, 43.625, 43.675, 43.725, 43.775, 43.825, 43.875, 43.925, 43.975, 44.025, 44.075, 44.125, 44.175, 44.225, 44.275, 44.325, 44.375, 44.425, 44.475, 44.525, 44.575, 44.625, 44.675, 44.725, 44.775, 44.825, 44.875, 44.925, 44.975, 45.025, 45.075, 45.125, 45.175, 45.225, 45.275, 45.325, 45.375, 45.425, 45.475, 45.525, 45.575, 45.625, 45.675, 45.725, 45.775, 45.825, 45.875, 45.925, 45.975, 46.025, 46.075, 46.125, 46.175, 46.225, 46.275, 46.325, 46.375, 46.425, 46.475, 46.525, 46.575, 46.625, 46.675, 46.725, 46.775, 46.825, 46.875, 46.925, 46.975, 47.025, 47.075, 47.125, 47.175, 47.225, 47.275, 47.325, 47.375, 47.425, 47.475, 47.525, 47.575, 47.625, 47.675, 47.725, 47.775, 47.825, 47.875, 47.925, 47.975, 48.025, 48.075, 48.125, 48.175, 48.225, 48.275, 48.325, 48.375, 48.425, 48.475, 48.525, 48.575, 48.625, 48.675, 48.725, 48.775, 48.825, 48.875, 48.925, 48.975, 49.025, 49.075, 49.125, 49.175, 49.225, 49.275, 49.325, 49.375, 49.425, 49.475, 49.525, 49.575, 49.625, 49.675, 49.725, 49.775, 49.825, 49.875, 49.925, 49.975, 50.025, 50.075, 50.125, 50.175, 50.225, 50.275, 50.325, 50.375, 50.425, 50.475, 50.525, 50.575, 50.625, 50.675, 50.725, 50.775, 50.825, 50.875, 50.925, 50.975, 51.025, 51.075, 51.125, 51.175, 51.225, 51.275, 51.325, 51.375, 51.425, 51.475, 51.525, 51.575, 51.625, 51.675, 51.725, 51.775, 51.825, 51.875, 51.925, 51.975, 52.025, 52.075, 52.125, 52.175, 52.225, 52.275, 52.325, 52.375, 52.425, 52.475, 52.525, 52.575, 52.625, 52.675, 52.725, 52.775, 52.825, 52.875, 52.925, 52.975, 53.025, 53.075, 53.125, 53.175, 53.225, 53.275, 53.325, 53.375, 53.425, 53.475, 53.525, 53.575, 53.625, 53.675, 53.725, 53.775, 53.825, 53.875, 53.925, 53.975, 54.025, 54.075, 54.125, 54.175, 54.225, 54.275, 54.325, 54.375, 54.425, 54.475, 54.525, 54.575, 54.625, 54.675, 54.725, 54.775, 54.825, 54.875, 54.925, 54.975, 55.025, 55.075, 55.125, 55.175, 55.225, 55.275, 55.325, 55.375, 55.425, 55.475, 55.525, 55.575, 55.625, 55.675, 55.725, 55.775, 55.825, 55.875, 55.925, 55.975, 56.025, 56.075, 56.125, 56.175, 56.225, 56.275, 56.325, 56.375, 56.425, 56.475, 56.525, 56.575, 56.625, 56.675, 56.725, 56.775, 56.825, 56.875, 56.925, 56.975, 57.025, 57.075, 57.125, 57.175, 57.225, 57.275, 57.325, 57.375, 57.425, 57.475, 57.525, 57.575, 57.625, 57.675, 57.725, 57.775, 57.825, 57.875, 57.925, 57.975, 58.025, 58.075, 58.125, 58.175, 58.225, 58.275, 58.325, 58.375, 58.425, 58.475, 58.525, 58.575, 58.625, 58.675, 58.725, 58.775, 58.825, 58.875, 58.925, 58.975, 59.025, 59.075, 59.125, 59.175, 59.225, 59.275, 59.325, 59.375, 59.425, 59.475, 59.525, 59.575, 59.625, 59.675, 59.725, 59.775, 59.825, 59.875, 59.925, 59.975}; +Float32 lon[lon = 2400] = {-134.975, -134.925, -134.875, -134.825, -134.775, -134.725, -134.675, -134.625, -134.575, -134.525, -134.475, -134.425, -134.375, -134.325, -134.275, -134.225, -134.175, -134.125, -134.075, -134.025, -133.975, -133.925, -133.875, -133.825, -133.775, -133.725, -133.675, -133.625, -133.575, -133.525, -133.475, -133.425, -133.375, -133.325, -133.275, -133.225, -133.175, -133.125, -133.075, -133.025, -132.975, -132.925, -132.875, -132.825, -132.775, -132.725, -132.675, -132.625, -132.575, -132.525, -132.475, -132.425, -132.375, -132.325, -132.275, -132.225, -132.175, -132.125, -132.075, -132.025, -131.975, -131.925, -131.875, -131.825, -131.775, -131.725, -131.675, -131.625, -131.575, -131.525, -131.475, -131.425, -131.375, -131.325, -131.275, -131.225, -131.175, -131.125, -131.075, -131.025, -130.975, -130.925, -130.875, -130.825, -130.775, -130.725, -130.675, -130.625, -130.575, -130.525, -130.475, -130.425, -130.375, -130.325, -130.275, -130.225, -130.175, -130.125, -130.075, -130.025, -129.975, -129.925, -129.875, -129.825, -129.775, -129.725, -129.675, -129.625, -129.575, -129.525, -129.475, -129.425, -129.375, -129.325, -129.275, -129.225, -129.175, -129.125, -129.075, -129.025, -128.975, -128.925, -128.875, -128.825, -128.775, -128.725, -128.675, -128.625, -128.575, -128.525, -128.475, -128.425, -128.375, -128.325, -128.275, -128.225, -128.175, -128.125, -128.075, -128.025, -127.975, -127.925, -127.875, -127.825, -127.775, -127.725, -127.675, -127.625, -127.575, -127.525, -127.475, -127.425, -127.375, -127.325, -127.275, -127.225, -127.175, -127.125, -127.075, -127.025, -126.975, -126.925, -126.875, -126.825, -126.775, -126.725, -126.675, -126.625, -126.575, -126.525, -126.475, -126.425, -126.375, -126.325, -126.275, -126.225, -126.175, -126.125, -126.075, -126.025, -125.975, -125.925, -125.875, -125.825, -125.775, -125.725, -125.675, -125.625, -125.575, -125.525, -125.475, -125.425, -125.375, -125.325, -125.275, -125.225, -125.175, -125.125, -125.075, -125.025, -124.975, -124.925, -124.875, -124.825, -124.775, -124.725, -124.675, -124.625, -124.575, -124.525, -124.475, -124.425, -124.375, -124.325, -124.275, -124.225, -124.175, -124.125, -124.075, -124.025, -123.975, -123.925, -123.875, -123.825, -123.775, -123.725, -123.675, -123.625, -123.575, -123.525, -123.475, -123.425, -123.375, -123.325, -123.275, -123.225, -123.175, -123.125, -123.075, -123.025, -122.975, -122.925, -122.875, -122.825, -122.775, -122.725, -122.675, -122.625, -122.575, -122.525, -122.475, -122.425, -122.375, -122.325, -122.275, -122.225, -122.175, -122.125, -122.075, -122.025, -121.975, -121.925, -121.875, -121.825, -121.775, -121.725, -121.675, -121.625, -121.575, -121.525, -121.475, -121.425, -121.375, -121.325, -121.275, -121.225, -121.175, -121.125, -121.075, -121.025, -120.975, -120.925, -120.875, -120.825, -120.775, -120.725, -120.675, -120.625, -120.575, -120.525, -120.475, -120.425, -120.375, -120.325, -120.275, -120.225, -120.175, -120.125, -120.075, -120.025, -119.975, -119.925, -119.875, -119.825, -119.775, -119.725, -119.675, -119.625, -119.575, -119.525, -119.475, -119.425, -119.375, -119.325, -119.275, -119.225, -119.175, -119.125, -119.075, -119.025, -118.975, -118.925, -118.875, -118.825, -118.775, -118.725, -118.675, -118.625, -118.575, -118.525, -118.475, -118.425, -118.375, -118.325, -118.275, -118.225, -118.175, -118.125, -118.075, -118.025, -117.975, -117.925, -117.875, -117.825, -117.775, -117.725, -117.675, -117.625, -117.575, -117.525, -117.475, -117.425, -117.375, -117.325, -117.275, -117.225, -117.175, -117.125, -117.075, -117.025, -116.975, -116.925, -116.875, -116.825, -116.775, -116.725, -116.675, -116.625, -116.575, -116.525, -116.475, -116.425, -116.375, -116.325, -116.275, -116.225, -116.175, -116.125, -116.075, -116.025, -115.975, -115.925, -115.875, -115.825, -115.775, -115.725, -115.675, -115.625, -115.575, -115.525, -115.475, -115.425, -115.375, -115.325, -115.275, -115.225, -115.175, -115.125, -115.075, -115.025, -114.975, -114.925, -114.875, -114.825, -114.775, -114.725, -114.675, -114.625, -114.575, -114.525, -114.475, -114.425, -114.375, -114.325, -114.275, -114.225, -114.175, -114.125, -114.075, -114.025, -113.975, -113.925, -113.875, -113.825, -113.775, -113.725, -113.675, -113.625, -113.575, -113.525, -113.475, -113.425, -113.375, -113.325, -113.275, -113.225, -113.175, -113.125, -113.075, -113.025, -112.975, -112.925, -112.875, -112.825, -112.775, -112.725, -112.675, -112.625, -112.575, -112.525, -112.475, -112.425, -112.375, -112.325, -112.275, -112.225, -112.175, -112.125, -112.075, -112.025, -111.975, -111.925, -111.875, -111.825, -111.775, -111.725, -111.675, -111.625, -111.575, -111.525, -111.475, -111.425, -111.375, -111.325, -111.275, -111.225, -111.175, -111.125, -111.075, -111.025, -110.975, -110.925, -110.875, -110.825, -110.775, -110.725, -110.675, -110.625, -110.575, -110.525, -110.475, -110.425, -110.375, -110.325, -110.275, -110.225, -110.175, -110.125, -110.075, -110.025, -109.975, -109.925, -109.875, -109.825, -109.775, -109.725, -109.675, -109.625, -109.575, -109.525, -109.475, -109.425, -109.375, -109.325, -109.275, -109.225, -109.175, -109.125, -109.075, -109.025, -108.975, -108.925, -108.875, -108.825, -108.775, -108.725, -108.675, -108.625, -108.575, -108.525, -108.475, -108.425, -108.375, -108.325, -108.275, -108.225, -108.175, -108.125, -108.075, -108.025, -107.975, -107.925, -107.875, -107.825, -107.775, -107.725, -107.675, -107.625, -107.575, -107.525, -107.475, -107.425, -107.375, -107.325, -107.275, -107.225, -107.175, -107.125, -107.075, -107.025, -106.975, -106.925, -106.875, -106.825, -106.775, -106.725, -106.675, -106.625, -106.575, -106.525, -106.475, -106.425, -106.375, -106.325, -106.275, -106.225, -106.175, -106.125, -106.075, -106.025, -105.975, -105.925, -105.875, -105.825, -105.775, -105.725, -105.675, -105.625, -105.575, -105.525, -105.475, -105.425, -105.375, -105.325, -105.275, -105.225, -105.175, -105.125, -105.075, -105.025, -104.975, -104.925, -104.875, -104.825, -104.775, -104.725, -104.675, -104.625, -104.575, -104.525, -104.475, -104.425, -104.375, -104.325, -104.275, -104.225, -104.175, -104.125, -104.075, -104.025, -103.975, -103.925, -103.875, -103.825, -103.775, -103.725, -103.675, -103.625, -103.575, -103.525, -103.475, -103.425, -103.375, -103.325, -103.275, -103.225, -103.175, -103.125, -103.075, -103.025, -102.975, -102.925, -102.875, -102.825, -102.775, -102.725, -102.675, -102.625, -102.575, -102.525, -102.475, -102.425, -102.375, -102.325, -102.275, -102.225, -102.175, -102.125, -102.075, -102.025, -101.975, -101.925, -101.875, -101.825, -101.775, -101.725, -101.675, -101.625, -101.575, -101.525, -101.475, -101.425, -101.375, -101.325, -101.275, -101.225, -101.175, -101.125, -101.075, -101.025, -100.975, -100.925, -100.875, -100.825, -100.775, -100.725, -100.675, -100.625, -100.575, -100.525, -100.475, -100.425, -100.375, -100.325, -100.275, -100.225, -100.175, -100.125, -100.075, -100.025, -99.975, -99.925, -99.875, -99.825, -99.775, -99.725, -99.675, -99.625, -99.575, -99.525, -99.475, -99.425, -99.375, -99.325, -99.275, -99.225, -99.175, -99.125, -99.075, -99.025, -98.975, -98.925, -98.875, -98.825, -98.775, -98.725, -98.675, -98.625, -98.575, -98.525, -98.475, -98.425, -98.375, -98.325, -98.275, -98.225, -98.175, -98.125, -98.075, -98.025, -97.975, -97.925, -97.875, -97.825, -97.775, -97.725, -97.675, -97.625, -97.575, -97.525, -97.475, -97.425, -97.375, -97.325, -97.275, -97.225, -97.175, -97.125, -97.075, -97.025, -96.975, -96.925, -96.875, -96.825, -96.775, -96.725, -96.675, -96.625, -96.575, -96.525, -96.475, -96.425, -96.375, -96.325, -96.275, -96.225, -96.175, -96.125, -96.075, -96.025, -95.975, -95.925, -95.875, -95.825, -95.775, -95.725, -95.675, -95.625, -95.575, -95.525, -95.475, -95.425, -95.375, -95.325, -95.275, -95.225, -95.175, -95.125, -95.075, -95.025, -94.975, -94.925, -94.875, -94.825, -94.775, -94.725, -94.675, -94.625, -94.575, -94.525, -94.475, -94.425, -94.375, -94.325, -94.275, -94.225, -94.175, -94.125, -94.075, -94.025, -93.975, -93.925, -93.875, -93.825, -93.775, -93.725, -93.675, -93.625, -93.575, -93.525, -93.475, -93.425, -93.375, -93.325, -93.275, -93.225, -93.175, -93.125, -93.075, -93.025, -92.975, -92.925, -92.875, -92.825, -92.775, -92.725, -92.675, -92.625, -92.575, -92.525, -92.475, -92.425, -92.375, -92.325, -92.275, -92.225, -92.175, -92.125, -92.075, -92.025, -91.975, -91.925, -91.875, -91.825, -91.775, -91.725, -91.675, -91.625, -91.575, -91.525, -91.475, -91.425, -91.375, -91.325, -91.275, -91.225, -91.175, -91.125, -91.075, -91.025, -90.975, -90.925, -90.875, -90.825, -90.775, -90.725, -90.675, -90.625, -90.575, -90.525, -90.475, -90.425, -90.375, -90.325, -90.275, -90.225, -90.175, -90.125, -90.075, -90.025, -89.975, -89.925, -89.875, -89.825, -89.775, -89.725, -89.675, -89.625, -89.575, -89.525, -89.475, -89.425, -89.375, -89.325, -89.275, -89.225, -89.175, -89.125, -89.075, -89.025, -88.975, -88.925, -88.875, -88.825, -88.775, -88.725, -88.675, -88.625, -88.575, -88.525, -88.475, -88.425, -88.375, -88.325, -88.275, -88.225, -88.175, -88.125, -88.075, -88.025, -87.975, -87.925, -87.875, -87.825, -87.775, -87.725, -87.675, -87.625, -87.575, -87.525, -87.475, -87.425, -87.375, -87.325, -87.275, -87.225, -87.175, -87.125, -87.075, -87.025, -86.975, -86.925, -86.875, -86.825, -86.775, -86.725, -86.675, -86.625, -86.575, -86.525, -86.475, -86.425, -86.375, -86.325, -86.275, -86.225, -86.175, -86.125, -86.075, -86.025, -85.975, -85.925, -85.875, -85.825, -85.775, -85.725, -85.675, -85.625, -85.575, -85.525, -85.475, -85.425, -85.375, -85.325, -85.275, -85.225, -85.175, -85.125, -85.075, -85.025, -84.975, -84.925, -84.875, -84.825, -84.775, -84.725, -84.675, -84.625, -84.575, -84.525, -84.475, -84.425, -84.375, -84.325, -84.275, -84.225, -84.175, -84.125, -84.075, -84.025, -83.975, -83.925, -83.875, -83.825, -83.775, -83.725, -83.675, -83.625, -83.575, -83.525, -83.475, -83.425, -83.375, -83.325, -83.275, -83.225, -83.175, -83.125, -83.075, -83.025, -82.975, -82.925, -82.875, -82.825, -82.775, -82.725, -82.675, -82.625, -82.575, -82.525, -82.475, -82.425, -82.375, -82.325, -82.275, -82.225, -82.175, -82.125, -82.075, -82.025, -81.975, -81.925, -81.875, -81.825, -81.775, -81.725, -81.675, -81.625, -81.575, -81.525, -81.475, -81.425, -81.375, -81.325, -81.275, -81.225, -81.175, -81.125, -81.075, -81.025, -80.975, -80.925, -80.875, -80.825, -80.775, -80.725, -80.675, -80.625, -80.575, -80.525, -80.475, -80.425, -80.375, -80.325, -80.275, -80.225, -80.175, -80.125, -80.075, -80.025, -79.975, -79.925, -79.875, -79.825, -79.775, -79.725, -79.675, -79.625, -79.575, -79.525, -79.475, -79.425, -79.375, -79.325, -79.275, -79.225, -79.175, -79.125, -79.075, -79.025, -78.975, -78.925, -78.875, -78.825, -78.775, -78.725, -78.675, -78.625, -78.575, -78.525, -78.475, -78.425, -78.375, -78.325, -78.275, -78.225, -78.175, -78.125, -78.075, -78.025, -77.975, -77.925, -77.875, -77.825, -77.775, -77.725, -77.675, -77.625, -77.575, -77.525, -77.475, -77.425, -77.375, -77.325, -77.275, -77.225, -77.175, -77.125, -77.075, -77.025, -76.975, -76.925, -76.875, -76.825, -76.775, -76.725, -76.675, -76.625, -76.575, -76.525, -76.475, -76.425, -76.375, -76.325, -76.275, -76.225, -76.175, -76.125, -76.075, -76.025, -75.975, -75.925, -75.875, -75.825, -75.775, -75.725, -75.675, -75.625, -75.575, -75.525, -75.475, -75.425, -75.375, -75.325, -75.275, -75.225, -75.175, -75.125, -75.075, -75.025, -74.975, -74.925, -74.875, -74.825, -74.775, -74.725, -74.675, -74.625, -74.575, -74.525, -74.475, -74.425, -74.375, -74.325, -74.275, -74.225, -74.175, -74.125, -74.075, -74.025, -73.975, -73.925, -73.875, -73.825, -73.775, -73.725, -73.675, -73.625, -73.575, -73.525, -73.475, -73.425, -73.375, -73.325, -73.275, -73.225, -73.175, -73.125, -73.075, -73.025, -72.975, -72.925, -72.875, -72.825, -72.775, -72.725, -72.675, -72.625, -72.575, -72.525, -72.475, -72.425, -72.375, -72.325, -72.275, -72.225, -72.175, -72.125, -72.075, -72.025, -71.975, -71.925, -71.875, -71.825, -71.775, -71.725, -71.675, -71.625, -71.575, -71.525, -71.475, -71.425, -71.375, -71.325, -71.275, -71.225, -71.175, -71.125, -71.075, -71.025, -70.975, -70.925, -70.875, -70.825, -70.775, -70.725, -70.675, -70.625, -70.575, -70.525, -70.475, -70.425, -70.375, -70.325, -70.275, -70.225, -70.175, -70.125, -70.075, -70.025, -69.975, -69.925, -69.875, -69.825, -69.775, -69.725, -69.675, -69.625, -69.575, -69.525, -69.475, -69.425, -69.375, -69.325, -69.275, -69.225, -69.175, -69.125, -69.075, -69.025, -68.975, -68.925, -68.875, -68.825, -68.775, -68.725, -68.675, -68.625, -68.575, -68.525, -68.475, -68.425, -68.375, -68.325, -68.275, -68.225, -68.175, -68.125, -68.075, -68.025, -67.975, -67.925, -67.875, -67.825, -67.775, -67.725, -67.675, -67.625, -67.575, -67.525, -67.475, -67.425, -67.375, -67.325, -67.275, -67.225, -67.175, -67.125, -67.075, -67.025, -66.975, -66.925, -66.875, -66.825, -66.775, -66.725, -66.675, -66.625, -66.575, -66.525, -66.475, -66.425, -66.375, -66.325, -66.275, -66.225, -66.175, -66.125, -66.075, -66.025, -65.975, -65.925, -65.875, -65.825, -65.775, -65.725, -65.675, -65.625, -65.575, -65.525, -65.475, -65.425, -65.375, -65.325, -65.275, -65.225, -65.175, -65.125, -65.075, -65.025, -64.975, -64.925, -64.875, -64.825, -64.775, -64.725, -64.675, -64.625, -64.575, -64.525, -64.475, -64.425, -64.375, -64.325, -64.275, -64.225, -64.175, -64.125, -64.075, -64.025, -63.975, -63.925, -63.875, -63.825, -63.775, -63.725, -63.675, -63.625, -63.575, -63.525, -63.475, -63.425, -63.375, -63.325, -63.275, -63.225, -63.175, -63.125, -63.075, -63.025, -62.975, -62.925, -62.875, -62.825, -62.775, -62.725, -62.675, -62.625, -62.575, -62.525, -62.475, -62.425, -62.375, -62.325, -62.275, -62.225, -62.175, -62.125, -62.075, -62.025, -61.975, -61.925, -61.875, -61.825, -61.775, -61.725, -61.675, -61.625, -61.575, -61.525, -61.475, -61.425, -61.375, -61.325, -61.275, -61.225, -61.175, -61.125, -61.075, -61.025, -60.975, -60.925, -60.875, -60.825, -60.775, -60.725, -60.675, -60.625, -60.575, -60.525, -60.475, -60.425, -60.375, -60.325, -60.275, -60.225, -60.175, -60.125, -60.075, -60.025, -59.975, -59.925, -59.875, -59.825, -59.775, -59.725, -59.675, -59.625, -59.575, -59.525, -59.475, -59.425, -59.375, -59.325, -59.275, -59.225, -59.175, -59.125, -59.075, -59.025, -58.975, -58.925, -58.875, -58.825, -58.775, -58.725, -58.675, -58.625, -58.575, -58.525, -58.475, -58.425, -58.375, -58.325, -58.275, -58.225, -58.175, -58.125, -58.075, -58.025, -57.975, -57.925, -57.875, -57.825, -57.775, -57.725, -57.675, -57.625, -57.575, -57.525, -57.475, -57.425, -57.375, -57.325, -57.275, -57.225, -57.175, -57.125, -57.075, -57.025, -56.975, -56.925, -56.875, -56.825, -56.775, -56.725, -56.675, -56.625, -56.575, -56.525, -56.475, -56.425, -56.375, -56.325, -56.275, -56.225, -56.175, -56.125, -56.075, -56.025, -55.975, -55.925, -55.875, -55.825, -55.775, -55.725, -55.675, -55.625, -55.575, -55.525, -55.475, -55.425, -55.375, -55.325, -55.275, -55.225, -55.175, -55.125, -55.075, -55.025, -54.975, -54.925, -54.875, -54.825, -54.775, -54.725, -54.675, -54.625, -54.575, -54.525, -54.475, -54.425, -54.375, -54.325, -54.275, -54.225, -54.175, -54.125, -54.075, -54.025, -53.975, -53.925, -53.875, -53.825, -53.775, -53.725, -53.675, -53.625, -53.575, -53.525, -53.475, -53.425, -53.375, -53.325, -53.275, -53.225, -53.175, -53.125, -53.075, -53.025, -52.975, -52.925, -52.875, -52.825, -52.775, -52.725, -52.675, -52.625, -52.575, -52.525, -52.475, -52.425, -52.375, -52.325, -52.275, -52.225, -52.175, -52.125, -52.075, -52.025, -51.975, -51.925, -51.875, -51.825, -51.775, -51.725, -51.675, -51.625, -51.575, -51.525, -51.475, -51.425, -51.375, -51.325, -51.275, -51.225, -51.175, -51.125, -51.075, -51.025, -50.975, -50.925, -50.875, -50.825, -50.775, -50.725, -50.675, -50.625, -50.575, -50.525, -50.475, -50.425, -50.375, -50.325, -50.275, -50.225, -50.175, -50.125, -50.075, -50.025, -49.975, -49.925, -49.875, -49.825, -49.775, -49.725, -49.675, -49.625, -49.575, -49.525, -49.475, -49.425, -49.375, -49.325, -49.275, -49.225, -49.175, -49.125, -49.075, -49.025, -48.975, -48.925, -48.875, -48.825, -48.775, -48.725, -48.675, -48.625, -48.575, -48.525, -48.475, -48.425, -48.375, -48.325, -48.275, -48.225, -48.175, -48.125, -48.075, -48.025, -47.975, -47.925, -47.875, -47.825, -47.775, -47.725, -47.675, -47.625, -47.575, -47.525, -47.475, -47.425, -47.375, -47.325, -47.275, -47.225, -47.175, -47.125, -47.075, -47.025, -46.975, -46.925, -46.875, -46.825, -46.775, -46.725, -46.675, -46.625, -46.575, -46.525, -46.475, -46.425, -46.375, -46.325, -46.275, -46.225, -46.175, -46.125, -46.075, -46.025, -45.975, -45.925, -45.875, -45.825, -45.775, -45.725, -45.675, -45.625, -45.575, -45.525, -45.475, -45.425, -45.375, -45.325, -45.275, -45.225, -45.175, -45.125, -45.075, -45.025, -44.975, -44.925, -44.875, -44.825, -44.775, -44.725, -44.675, -44.625, -44.575, -44.525, -44.475, -44.425, -44.375, -44.325, -44.275, -44.225, -44.175, -44.125, -44.075, -44.025, -43.975, -43.925, -43.875, -43.825, -43.775, -43.725, -43.675, -43.625, -43.575, -43.525, -43.475, -43.425, -43.375, -43.325, -43.275, -43.225, -43.175, -43.125, -43.075, -43.025, -42.975, -42.925, -42.875, -42.825, -42.775, -42.725, -42.675, -42.625, -42.575, -42.525, -42.475, -42.425, -42.375, -42.325, -42.275, -42.225, -42.175, -42.125, -42.075, -42.025, -41.975, -41.925, -41.875, -41.825, -41.775, -41.725, -41.675, -41.625, -41.575, -41.525, -41.475, -41.425, -41.375, -41.325, -41.275, -41.225, -41.175, -41.125, -41.075, -41.025, -40.975, -40.925, -40.875, -40.825, -40.775, -40.725, -40.675, -40.625, -40.575, -40.525, -40.475, -40.425, -40.375, -40.325, -40.275, -40.225, -40.175, -40.125, -40.075, -40.025, -39.975, -39.925, -39.875, -39.825, -39.775, -39.725, -39.675, -39.625, -39.575, -39.525, -39.475, -39.425, -39.375, -39.325, -39.275, -39.225, -39.175, -39.125, -39.075, -39.025, -38.975, -38.925, -38.875, -38.825, -38.775, -38.725, -38.675, -38.625, -38.575, -38.525, -38.475, -38.425, -38.375, -38.325, -38.275, -38.225, -38.175, -38.125, -38.075, -38.025, -37.975, -37.925, -37.875, -37.825, -37.775, -37.725, -37.675, -37.625, -37.575, -37.525, -37.475, -37.425, -37.375, -37.325, -37.275, -37.225, -37.175, -37.125, -37.075, -37.025, -36.975, -36.925, -36.875, -36.825, -36.775, -36.725, -36.675, -36.625, -36.575, -36.525, -36.475, -36.425, -36.375, -36.325, -36.275, -36.225, -36.175, -36.125, -36.075, -36.025, -35.975, -35.925, -35.875, -35.825, -35.775, -35.725, -35.675, -35.625, -35.575, -35.525, -35.475, -35.425, -35.375, -35.325, -35.275, -35.225, -35.175, -35.125, -35.075, -35.025, -34.975, -34.925, -34.875, -34.825, -34.775, -34.725, -34.675, -34.625, -34.575, -34.525, -34.475, -34.425, -34.375, -34.325, -34.275, -34.225, -34.175, -34.125, -34.075, -34.025, -33.975, -33.925, -33.875, -33.825, -33.775, -33.725, -33.675, -33.625, -33.575, -33.525, -33.475, -33.425, -33.375, -33.325, -33.275, -33.225, -33.175, -33.125, -33.075, -33.025, -32.975, -32.925, -32.875, -32.825, -32.775, -32.725, -32.675, -32.625, -32.575, -32.525, -32.475, -32.425, -32.375, -32.325, -32.275, -32.225, -32.175, -32.125, -32.075, -32.025, -31.975, -31.925, -31.875, -31.825, -31.775, -31.725, -31.675, -31.625, -31.575, -31.525, -31.475, -31.425, -31.375, -31.325, -31.275, -31.225, -31.175, -31.125, -31.075, -31.025, -30.975, -30.925, -30.875, -30.825, -30.775, -30.725, -30.675, -30.625, -30.575, -30.525, -30.475, -30.425, -30.375, -30.325, -30.275, -30.225, -30.175, -30.125, -30.075, -30.025, -29.975, -29.925, -29.875, -29.825, -29.775, -29.725, -29.675, -29.625, -29.575, -29.525, -29.475, -29.425, -29.375, -29.325, -29.275, -29.225, -29.175, -29.125, -29.075, -29.025, -28.975, -28.925, -28.875, -28.825, -28.775, -28.725, -28.675, -28.625, -28.575, -28.525, -28.475, -28.425, -28.375, -28.325, -28.275, -28.225, -28.175, -28.125, -28.075, -28.025, -27.975, -27.925, -27.875, -27.825, -27.775, -27.725, -27.675, -27.625, -27.575, -27.525, -27.475, -27.425, -27.375, -27.325, -27.275, -27.225, -27.175, -27.125, -27.075, -27.025, -26.975, -26.925, -26.875, -26.825, -26.775, -26.725, -26.675, -26.625, -26.575, -26.525, -26.475, -26.425, -26.375, -26.325, -26.275, -26.225, -26.175, -26.125, -26.075, -26.025, -25.975, -25.925, -25.875, -25.825, -25.775, -25.725, -25.675, -25.625, -25.575, -25.525, -25.475, -25.425, -25.375, -25.325, -25.275, -25.225, -25.175, -25.125, -25.075, -25.025, -24.975, -24.925, -24.875, -24.825, -24.775, -24.725, -24.675, -24.625, -24.575, -24.525, -24.475, -24.425, -24.375, -24.325, -24.275, -24.225, -24.175, -24.125, -24.075, -24.025, -23.975, -23.925, -23.875, -23.825, -23.775, -23.725, -23.675, -23.625, -23.575, -23.525, -23.475, -23.425, -23.375, -23.325, -23.275, -23.225, -23.175, -23.125, -23.075, -23.025, -22.975, -22.925, -22.875, -22.825, -22.775, -22.725, -22.675, -22.625, -22.575, -22.525, -22.475, -22.425, -22.375, -22.325, -22.275, -22.225, -22.175, -22.125, -22.075, -22.025, -21.975, -21.925, -21.875, -21.825, -21.775, -21.725, -21.675, -21.625, -21.575, -21.525, -21.475, -21.425, -21.375, -21.325, -21.275, -21.225, -21.175, -21.125, -21.075, -21.025, -20.975, -20.925, -20.875, -20.825, -20.775, -20.725, -20.675, -20.625, -20.575, -20.525, -20.475, -20.425, -20.375, -20.325, -20.275, -20.225, -20.175, -20.125, -20.075, -20.025, -19.975, -19.925, -19.875, -19.825, -19.775, -19.725, -19.675, -19.625, -19.575, -19.525, -19.475, -19.425, -19.375, -19.325, -19.275, -19.225, -19.175, -19.125, -19.075, -19.025, -18.975, -18.925, -18.875, -18.825, -18.775, -18.725, -18.675, -18.625, -18.575, -18.525, -18.475, -18.425, -18.375, -18.325, -18.275, -18.225, -18.175, -18.125, -18.075, -18.025, -17.975, -17.925, -17.875, -17.825, -17.775, -17.725, -17.675, -17.625, -17.575, -17.525, -17.475, -17.425, -17.375, -17.325, -17.275, -17.225, -17.175, -17.125, -17.075, -17.025, -16.975, -16.925, -16.875, -16.825, -16.775, -16.725, -16.675, -16.625, -16.575, -16.525, -16.475, -16.425, -16.375, -16.325, -16.275, -16.225, -16.175, -16.125, -16.075, -16.025, -15.975, -15.925, -15.875, -15.825, -15.775, -15.725, -15.675, -15.625, -15.575, -15.525, -15.475, -15.425, -15.375, -15.325, -15.275, -15.225, -15.175, -15.125, -15.075, -15.025}; + diff --git a/retired/modules/ngap_module/tests/ngap/20180101000000-OSISAF-L3C_GHRSST-cloudydap.dmr.bescmd b/retired/modules/ngap_module/tests/ngap/20180101000000-OSISAF-L3C_GHRSST-cloudydap.dmr.bescmd new file mode 100644 index 0000000000..0029670eee --- /dev/null +++ b/retired/modules/ngap_module/tests/ngap/20180101000000-OSISAF-L3C_GHRSST-cloudydap.dmr.bescmd @@ -0,0 +1,14 @@ + + + + 300 + no + xml + 0 + + collections/C2036877806-POCLOUD/granules/20180101000000-OSISAF-L3C_GHRSST-SSTsubskin-GOES16-ssteqc_goes16_20180101_000000-v02.0-fv01.0 + + + + + diff --git a/retired/modules/ngap_module/tests/ngap/20180101000000-OSISAF-L3C_GHRSST-cloudydap.dmr.bescmd.baseline b/retired/modules/ngap_module/tests/ngap/20180101000000-OSISAF-L3C_GHRSST-cloudydap.dmr.bescmd.baseline new file mode 100644 index 0000000000..a3f6c6714f --- /dev/null +++ b/retired/modules/ngap_module/tests/ngap/20180101000000-OSISAF-L3C_GHRSST-cloudydap.dmr.bescmd.baseline @@ -0,0 +1,1179 @@ + + + + + + + + + latitude + + + latitude + + + Y + + + degrees_north + + + -90.00000000 + + + 90.00000000 + + + geographical coordinates, WGS84 projection + + + lat + + + /lat + + + + + + longitude + + + longitude + + + X + + + degrees_east + + + -180.0000000 + + + 180.0000000 + + + geographical coordinates, WGS84 projection + + + lon + + + /lon + + + + + + reference time of sst file + + + time + + + T + + + seconds since 1981-01-01 00:00:00 + + + time + + + /time + + + + + + + + -128 + + + 10m wind speed + + + wind_speed + + + m s-1 + + + 10 m + + + 0.0000000000000000 + + + 1.0000000000000000 + + + 0 + + + 127 + + + These wind speeds were created by the ECMWF and represent winds at 10 metres above the sea surface. + + + WSP-ECMWF-Forecast + + + 0.0000000000000000 + + + wind_speed + + + /wind_speed + + + + + + + + + + + -32768 + + + original longitude of the SST value + + + longitude + + + degrees_east + + + 0.0000000000000000 + + + 0.010000000000000000 + + + -18000 + + + 18000 + + + Original longitude of the SST value + + + or_longitude + + + /or_longitude + + + + + + + + + + + -128 + + + SSES standard deviation + + + kelvin + + + 1.0000000000000000 + + + 0.010000000000000000 + + + -127 + + + 127 + + + Standard deviation estimate derived using the techniques described at http://www.ghrsst.org/SSES-Description-of-schemes.html + + + sses_standard_deviation + + + /sses_standard_deviation + + + + + + + + + + + -2147483648 + + + time difference from reference time + + + seconds + + + 0.0000000000000000 + + + 1.0000000000000000 + + + -2147483647 + + + 2147483647 + + + time plus sst_dtime gives seconds after 00:00:00 UTC January 1, 1981 + + + sst_dtime + + + /sst_dtime + + + + + + + + + + + -128 + + + solar zenith angle + + + angular_degree + + + 90.000000000000000 + + + 1.0000000000000000 + + + -90 + + + 90 + + + The solar zenith angle at the time of the SST observations. + + + solar_zenith_angle + + + /solar_zenith_angle + + + + + + + + + + + -128 + + + sea ice fraction + + + sea_ice_area_fraction + + + + + + 0.0000000000000000 + + + 0.010000000000000000 + + + 0 + + + 100 + + + Fractional sea ice cover from OSISAF ice product + + + ICE-OSISAF + + + -36.000000000000000 + + + sea_ice_fraction + + + /sea_ice_fraction + + + + + + + + + + + L2P flags + + + 0 + + + 15 + + + microwave land ice lake + + + 1 + 2 + 4 + 8 + + + These flags are important to properly use the data. + + + l2p_flags + + + /l2p_flags + + + + + + + + + + + -128 + + + sources of aerosol dynamic indicator + + + 0 + + + 2 + + + no_data AOD-NAAPS-ADI SDI-OSISAF-ADI + + + 0 + 1 + 2 + + + This variable provides a pixel by pixel description of where aerosol optical depth were derived from. + + + sources_of_adi + + + /sources_of_adi + + + + + + + + + + + -128 + + + aerosol dynamic indicator + + + + + + 0.0000000000000000 + + + 0.10000000000000001 + + + 0 + + + 127 + + + sources_of_adi + + + aerosol_dynamic_indicator + + + /aerosol_dynamic_indicator + + + + + + + + + + + -32768 + + + sea surface subskin temperature + + + sea_surface_subskin_temperature + + + kelvin + + + 273.14999999999998 + + + 0.010000000000000000 + + + -300 + + + 4500 + + + 1 millimeter + + + GOES_Imager + + + Temperature of the subskin of the ocean + + + sea_surface_temperature + + + /sea_surface_temperature + + + + + + + + + + + -128 + + + quality level of SST pixel + + + 0 + + + 5 + + + no_data bad_data worst_quality low_quality acceptable_quality best_quality + + + 0 + 1 + 2 + 3 + 4 + 5 + + + These are the overall quality indicators and are used for all GHRSST SSTs + + + quality_level + + + /quality_level + + + + + + + + + + + -128 + + + deviation from SST analysis or reference climatology + + + kelvin + + + 0.0000000000000000 + + + 0.10000000000000001 + + + -127 + + + 127 + + + The difference between this SST and the previous day's SST analysis + + + OSTIA + + + dt_analysis + + + /dt_analysis + + + + + + + + + + + -128 + + + satellite zenith angle + + + angular_degree + + + 0.0000000000000000 + + + 1.0000000000000000 + + + -90 + + + 90 + + + The satellite zenith angle at the time of the SST observations. + + + satellite_zenith_angle + + + /satellite_zenith_angle + + + + + + + + + + + -128 + + + time difference of ADI data from sst measurement + + + hour + + + 0.0000000000000000 + + + 0.10000000000000001 + + + -127 + + + 127 + + + Difference in hours between the ADI and SST data + + + adi_dtime_from_sst + + + /adi_dtime_from_sst + + + + + + + + + + + -32768 + + + original latitude of the SST value + + + latitude + + + degrees_north + + + 0.0000000000000000 + + + 0.010000000000000000 + + + -9000 + + + 9000 + + + Original latitude of the SST value + + + or_latitude + + + /or_latitude + + + + + + + + + + + -128 + + + SSES bias estimate + + + kelvin + + + 0.0000000000000000 + + + 0.010000000000000000 + + + -127 + + + 127 + + + Bias estimate derived using the techniques described at http://www.ghrsst.org/SSES-Description-of-schemes.html + + + sses_bias + + + /sses_bias + + + + + + + CF-1.4 + + + Sea Surface Temperature + + + The L3C product derived from GOES16/ABI brightness temperatures. + + + Geostationary Sea Surface Temperature Product User Manual, http://www.osi-saf.org + + + OSISAF + + + METEO-FRANCE/CMS SAFOS processor + + + All intellectual property rights of the Ocean & Sea Ice SAF products belong to EUMETSAT. The use of these products is granted to every user, free of charge. If users wish to use these products, EUMETSAT's copyright credit must be shown by displaying the words 'Copyright EUMETSAT' under each of the products shown. EUMETSAT offers no warranty and accepts no liability in respect of the Ocean & Sea Ice SAF products. EUMETSAT neither commits to nor guarantees the continuity, availability, or quality or suitability for any purpose of, the Ocean & Sea Ice SAF products. + + + GOES16-OSISAF-L3C-v1.0 + + + org.ghrsst + + + 1.0 + + + 2.0 + + + 0.05 degree + + + 60.00000000 + + + -60.00000000 + + + -15.00000000 + + + -135.0000000 + + + GOES_ABI + + + GOES16 + + + GOES_ABI + + + Unidata Dataset Discovery v1.0 + + + N/A + + + Oceans > Ocean Temperature > Sea Surface Temperature + + + NASA Global Change Master Directory (GCMD) Science Keywords + + + NetCDF Climate and Forecast (CF) Metadata Convention + + + degrees_north + + + 0.050000000000000003 + + + degrees_east + + + 0.050000000000000003 + + + In case SAF data (pre-operational or operational) has been used for the study described in a paper the following sentence would be an appropriate reference to the funding coming from EUMETSAT: The data from the EUMETSAT Satellite Application Facility on Ocean & Sea Ice used in this study are accessible through the SAF's homepage http://www.osi-saf.org + + + O&SI SAF + + + osi-saf.helpdesk@meteo.fr + + + http://www.osi-saf.org + + + Group for High Resolution Sea Surface Temperature + + + The GHRSST Project Office + + + http://www.ghrsst.org + + + ghrsst-po@nceo.ac.uk + + + L3C + + + grid + + + 20180101T020918Z + + + 2 + + + 20171231T233000Z + + + 20171231T233000Z + + + 20180101T003000Z + + + 20180101T003000Z + + + D9299038-EE98-11E7-B2C3-0024E836CC1A + + + 4.3.2 + + + + time + + + + + 3.21.0-300 + + + 3.21.0-300 + + + libdap-3.21.0-70 + + + +# TheBESKeys::get_as_config() +AllowedHosts=^https?:\/\/localhost(:8080)?\/.*$ # needed for tests +AllowedHosts+=^https:\/\/(sit\.|uat\.)?urs\.earthdata\.nasa.gov\/.*$ +AllowedHosts+=^https:\/\/cmr.(uat.|sit.)?earthdata.nasa.gov\/.*$ +AllowedHosts+=^https:\/\/goldsmr4\.gesdisc\.eosdis\.nasa\.gov\/.*$ +AllowedHosts+=^file:\/\/\/home\/centos\/hyrax\/build\/share\/hyrax\/.*$ +BES.CancelTimeoutOnSend=true +BES.Catalog.CMR.RootDirectory=UNUSED +BES.Catalog.CMR.TypeMatch=nc:.*\.nc(4)?(\.bz2|\.gz|\.Z)?$; +BES.Catalog.CMR.TypeMatch+=h4:.*\.(hdf|HDF|eos|HDFEOS)(\.bz2|\.gz|\.Z)?$; +BES.Catalog.CMR.TypeMatch+=h5:.*\.(HDF5|h5|he5)(\.bz2|\.gz|\.Z)?$; +BES.Catalog.CMR.TypeMatch+=ncml:.*\.ncml(\.bz2|\.gz|\.Z)?$; +BES.Catalog.Default=catalog +BES.Catalog.RemoteResources.RootDirectory=UNUSED +BES.Catalog.RemoteResources.TypeMatch=unused:unused; +BES.Catalog.catalog.Exclude=(^\..*$)|(^.*\.das$); +BES.Catalog.catalog.FollowSymLinks=No +BES.Catalog.catalog.Include=; +BES.Catalog.catalog.RootDirectory=/usr/share/hyrax +BES.Catalog.catalog.TypeMatch=csv:.*\.csv(\.bz2|\.gz|\.Z)?$; +BES.Catalog.catalog.TypeMatch+=reader:.*\.(dds|dods|data_ddx|dmr|dap)$; +BES.Catalog.catalog.TypeMatch+=dmrpp:.*\.(dmrpp)(\.bz2|\.gz|\.Z)?$; +BES.Catalog.catalog.TypeMatch+=ff:.*\.dat(\.bz2|\.gz|\.Z)?$; +BES.Catalog.catalog.TypeMatch+=gdal:.*\.(tif|TIF)$|.*\.grb\.(bz2|gz|Z)?$|.*\.jp2$|.*/gdal/.*\.jpg$; +BES.Catalog.catalog.TypeMatch+=h4:.*\.(hdf|HDF|eos|HDFEOS)(\.bz2|\.gz|\.Z)?$; +BES.Catalog.catalog.TypeMatch+=h5:.*\.(HDF5|h5|he5|H5)(\.bz2|\.gz|\.Z)?$; +BES.Catalog.catalog.TypeMatch+=nc:.*\.nc(4)?(\.bz2|\.gz|\.Z)?$; +BES.Catalog.catalog.TypeMatch+=ncml:.*\.ncml(\.bz2|\.gz|\.Z)?$; +BES.Catalog.catalog.TypeMatch+=h5:.*\.(HDF5|h5|he5|nc|nc4)(\.bz2|\.gz|\.Z)?$; +BES.Container.Persistence=strict +BES.Data.RootDirectory=/dev/null +BES.FollowSymLinks=No +BES.Group=bes +BES.Help.HTML=/usr/share/bes/bes_help.html +BES.Help.TXT=/usr/share/bes/bes_help.txt +BES.Help.XML=/usr/share/bes/bes_help.xml +BES.Include=modules/.*\.conf$ +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=fonc.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=dap.conf +BES.Include+=site.conf +BES.Info.Buffered=no +BES.Info.Type=xml +BES.LogName=/var/log/bes/bes.log +BES.LogUnixTime=true +BES.LogVerbose=false +BES.MaxResponseSize.bytes=8329006592 +BES.MaxVariableSize.bytes=8589934592 +BES.Memory.GlobalArea.ControlHeap=no +BES.Memory.GlobalArea.EmergencyPoolSize=1 +BES.Memory.GlobalArea.MaximumHeapSize=20 +BES.Memory.GlobalArea.Verbose=no +BES.ProcessManagerMethod=multiple +BES.ServerAdministrator=email:ngap@opendap.org +BES.ServerAdministrator+=organization:OPeNDAP Inc. +BES.ServerAdministrator+=street:165 NW Dean Knauss Dr. +BES.ServerAdministrator+=city:Narragansett +BES.ServerAdministrator+=region:RI +BES.ServerAdministrator+=postalCode:02882 +BES.ServerAdministrator+=country:US +BES.ServerAdministrator+=telephone:+1.401.575.4835 +BES.ServerAdministrator+=website:http://www.opendap.org +BES.ServerPort=10022 +BES.ServerSecure=no +BES.SetSockRecvSize=No +BES.SetSockSendSize=No +BES.SockRecvSize=65535 +BES.SockSendSize=65535 +BES.UncompressCache.dir=/var/cache/bes/hyrax_ux +BES.UncompressCache.prefix=ux_ +BES.UncompressCache.size=500 +BES.User=bes +BES.module.ascii=/usr/lib64/bes/libascii_module.so +BES.module.builddmrpp=/usr/lib64/bes/libbuilddmrpp_module.so +BES.module.cmr=/usr/lib64/bes/libcmr_module.so +BES.module.csv=/usr/lib64/bes/libcsv_module.so +BES.module.dap=/usr/lib64/bes/libdap_module.so +BES.module.dapcmd=/usr/lib64/bes/libdap_xml_module.so +BES.module.dmrpp=/usr/lib64/bes/libdmrpp_module.so +BES.module.ff=/usr/lib64/bes/libff_module.so +BES.module.focovjson=/usr/lib64/bes/libfocovjson_module.so +BES.module.fojson=/usr/lib64/bes/libfojson_module.so +BES.module.fonc=/usr/lib64/bes/libfonc_module.so +BES.module.functions=/usr/lib64/bes/libfunctions_module.so +BES.module.gateway=/usr/lib64/bes/libgateway_module.so +BES.module.gdal=/usr/lib64/bes/libgdal_module.so +BES.module.h4=/usr/lib64/bes/libhdf4_module.so +BES.module.h5=/usr/lib64/bes/libhdf5_module.so +BES.module.httpd=/usr/lib64/bes/libhttpd_catalog_module.so +BES.module.nc=/usr/lib64/bes/libnc_module.so +BES.module.ncml=/usr/lib64/bes/libncml_module.so +BES.module.ngap=/usr/lib64/bes/libngap_module.so +BES.module.reader=/usr/lib64/bes/libdapreader_module.so +BES.module.s3=/usr/lib64/bes/libs3_reader.so +BES.module.sample=/usr/lib64/bes/libsample_module.so +BES.module.ugrid_functions=/usr/lib64/bes/libugrid_functions.so +BES.module.usage=/usr/lib64/bes/libusage_module.so +BES.module.w10n=/usr/lib64/bes/libw10n_handler.so +BES.module.xml_data=/usr/lib64/bes/libxml_data_module.so +BES.modules=dap,dapcmd +BES.modules+=ascii +BES.modules+=builddmrpp +BES.modules+=csv +BES.modules+=reader +BES.modules+=fonc +BES.modules+=dmrpp +BES.modules+=ff +BES.modules+=focovjson +BES.modules+=fojson +BES.modules+=functions +BES.modules+=gateway +BES.modules+=gdal +BES.modules+=h4 +BES.modules+=h5 +BES.modules+=nc +BES.modules+=ncml +BES.modules+=ngap +BES.modules+=s3 +BES.modules+=sample +BES.modules+=ugrid_functions +BES.modules+=usage +BES.modules+=w10n +BES.modules+=xml_data +CMR.Collections=C1276812863-GES_DISC +CMR.Collections+=C1222931489-GHRC_CLOUD +CMR.Collections+=C1222931739-GHRC_CLOUD +CMR.Facets=temporal +CMR.Reference=http://docs.opendap.org/index.php/BES_-_Modules_-_CMR_Catalog +CMR.host.url=https://cmr.earthdata.nasa.gov +DAP.Async.StyleSheet.Ref=/opendap/xsl/asyncResponse.xsl +DAP.FunctionResponseCache.path=/tmp/hyrax_func +DAP.FunctionResponseCache.prefix=func_ +DAP.FunctionResponseCache.size=20000 +DAP.GlobalMetadataStore.ledger=/usr/share/mds/mds_ledger.txt +DAP.GlobalMetadataStore.prefix=mds_ +DAP.GlobalMetadataStore.size=200 +DAP.Help.HTML=/usr/share/bes/dap_help.html +DAP.Help.TXT=/usr/share/bes/dap_help.txt +DAP.Help.XML=/usr/share/bes/dap_help.xml +DAP.StoredResultsCache.prefix=result_ +DAP.StoredResultsCache.size=20000 +DAP.StoredResultsCache.subdir=stored_results +DMRPP.MaxComputeThreads=512 +DMRPP.MaxParallelTransfers=16 +DMRPP.UseComputeThreads=true +DMRPP.UseParallelTransfers=false +DR.UseSeriesValues=false +DR.UseTestTypes=true +FONc.ChunkSize=4096 +FONc.ClassicModel=false +FONc.Reference=http://docs.opendap.org/index.php/BES_-_Modules_-_FileOut_Netcdf +FONc.RequestMaxSizeKB=0 +FONc.Tempdir=/tmp/hyrax_fonc +FONc.UseCompression=true +FONg.GeoTiff.band.type.byte=true +FONg.Reference=http://docs.opendap.org/index.php/BES_-_Modules_-_FileOut_GDAL +FONg.Tempdir=/tmp/hyrax_fong +FONg.default_gcs=WGS84 +FoCovJson.Reference=http://docs.opendap.org/index.php/BES_-_Modules_-_FileOut_CovJSON +FoCovJson.Tempdir=/tmp +FoJson.Reference=http://docs.opendap.org/index.php/BES_-_Modules_-_FileOut_JSON +FoJson.Tempdir=/tmp +Gateway.Cache.dir=/tmp/hyrax_gw +Gateway.Cache.prefix=gw_ +Gateway.Cache.size=500 +Gateway.MimeTypes=nc:application/x-netcdf +Gateway.MimeTypes+=h4:application/x-hdf +Gateway.MimeTypes+=h5:application/x-hdf5 +H4.Cache.metadata.path=/tmp/md +H4.DisableECSMetaDataAll=false +H4.DisableECSMetaDataMin=true +H4.DisableScaleOffsetComp=true +H4.DisableStructMetaAttr=true +H4.DisableSwathDimMap=false +H4.DisableVdataNameclashingCheck=true +H4.EnableCERESMERRAShortName=true +H4.EnableCERESVdata=false +H4.EnableCF=true +H4.EnableCheckMODISGeoFile=false +H4.EnableCheckScaleOffsetType=false +H4.EnableDataCacheFile=false +H4.EnableEOSGeoCacheFile=false +H4.EnableHybridVdata=true +H4.EnableMetaDataCacheFile=false +H4.EnablePassFileID=false +H4.EnableSpecialEOS=true +H4.EnableSwathGridAttr=true +H4.EnableVdataDescAttr=false +H4.EnableVdata_to_Attr=true +H4.EnableVgroupAttr=true +H5.Cache.latlon.path=/tmp/latlon +H5.Cache.latlon.prefix=l +H5.Cache.latlon.size=20000 +H5.CheckIgnoreObj=false +H5.DefaultHandleDimension=true +H5.DisableECSMetaAttr=false +H5.DisableStructMetaAttr=true +H5.DiskCacheComp=false +H5.DiskCacheCompThreshold=2.0 +H5.DiskCacheCompVarSize=100 +H5.DiskCacheDataPath=/tmp +H5.DiskCacheFilePrefix=c +H5.DiskCacheFloatOnlyComp=true +H5.DiskCacheSize=100000 +H5.EnableAddPathAttrs=true +H5.EnableCF=true +H5.EnableCFDMR=true +H5.EnableCheckNameClashing=false +H5.EnableCoorattrAddPath=true +H5.EnableDAP4Coverage=true +H5.EnableDMR64bitInt=true +H5.EnableDiskDataCache=false +H5.EnableDiskMetaDataCache=false +H5.EnableDropLongString=true +H5.EnableEOSGeoCacheFile=false +H5.EnableFillValueCheck=true +H5.EnablePassFileID=false +H5.EscapeUTF8Attr=true +H5.ForceFlattenNDCoorAttr=true +H5.KeepVarLeadingUnderscore=false +H5.LargeDataMemCacheConfig=false +H5.LargeDataMemCacheEntries=0 +H5.MetaDataMemCacheEntries=1000 +H5.NoZeroSizeFullnameAttr=false +H5.RmConventionAttrPath=true +H5.SmallDataMemCacheEntries=0 +HDF4.Cache.latlon.path=/tmp/latlon +HDF4.Cache.latlon.prefix=l +HDF4.Cache.latlon.size=20000 +HDF4.CacheDir=/tmp +Http.Cookies.File=/tmp/hyrax_cookies/cf +Http.MimeTypes=nc:application/x-netcdf +Http.MimeTypes+=h4:application/x-hdf +Http.MimeTypes+=h5:application/x-hdf5 +Http.No.Retry.Regex=^https:\/\/.*\?code\=.*$ +Http.UserAgent=hyrax-prod +Http.cache.effective.urls=true +Http.cache.effective.urls.skip.regex.pattern=^https:\/\/.*s3(\.|-).*\.amazonaws\.com\/.*$ +Http.netrc.file=/etc/bes/ngap_netrc +Httpd_Catalog.Collections=test:http://test.opendap.org/data/ +Httpd_Catalog.Reference=http://docs.opendap.org/index.php/BES_-_Modules_-_Httpd_Catalog +NC.CacheEntries=100 +NC.PromoteByteToShort=true +NC.ShowSharedDimensions=true +NC.UseMDS=false +NCML.DimensionCache.directory=/tmp/hyrax_ncml +NCML.DimensionCache.prefix=ncml_ +NCML.DimensionCache.size=2000 +NGAP.CMRCachePurge=20 +NGAP.CMRCacheSize=100 +NGAP.DMRppCachePurge=20 +NGAP.DMRppCacheSize=100 +NGAP.DMRppFileCacheDir=/tmp/hyrax_ngap_cache +NGAP.DMRppFileCachePurge.MB=2000 +NGAP.DMRppFileCacheSize.MB=10000 +NGAP.UseCMRCache=true +NGAP.UseDMRppCache=true +NGAP.cmr_host_url=https://cmr.earthdata.nasa.gov +NGAP.inject_data_urls=true +Say.LogName=@prefix@/var/say.log +SupportEmail=support@opendap.org +s3.inject_data_urls=true +w10n.Reference=http://docs.opendap.org/index.php/BES_-_Modules_-_w10n_handler +w10n.Tempdir=/tmp + + + + https://opendap.earthdata.nasa.gov/build_dmrpp/collections/C2036877806-POCLOUD/granules/20180101000000-OSISAF-L3C_GHRSST-SSTsubskin-GOES16-ssteqc_goes16_20180101_000000-v02.0-fv01.0 + + + diff --git a/retired/modules/ngap_module/tests/ngap/20180101000000-OSISAF-L3C_GHRSST-pocloud.dap.bescmd b/retired/modules/ngap_module/tests/ngap/20180101000000-OSISAF-L3C_GHRSST-pocloud.dap.bescmd new file mode 100644 index 0000000000..674ae165c4 --- /dev/null +++ b/retired/modules/ngap_module/tests/ngap/20180101000000-OSISAF-L3C_GHRSST-pocloud.dap.bescmd @@ -0,0 +1,18 @@ + + + + 300 + no + xml + 0 + + collections/C2036877806-POCLOUD/granules/20180101000000-OSISAF-L3C_GHRSST-SSTsubskin-GOES16-ssteqc_goes16_20180101_000000-v02.0-fv01.0 + + + + /lat;/lon + + + + + diff --git a/retired/modules/ngap_module/tests/ngap/20180101000000-OSISAF-L3C_GHRSST-pocloud.dap.bescmd.baseline b/retired/modules/ngap_module/tests/ngap/20180101000000-OSISAF-L3C_GHRSST-pocloud.dap.bescmd.baseline new file mode 100644 index 0000000000..d19cac04a6 --- /dev/null +++ b/retired/modules/ngap_module/tests/ngap/20180101000000-OSISAF-L3C_GHRSST-pocloud.dap.bescmd.baseline @@ -0,0 +1,245 @@ + + + + + + + + longitude + + + longitude + + + X + + + degrees_east + + + -180. + + + 180. + + + geographical coordinates, WGS84 projection + + + removed checksum + + + + + + latitude + + + latitude + + + Y + + + degrees_north + + + -90. + + + 90. + + + geographical coordinates, WGS84 projection + + + removed checksum + + + + CF-1.4 + + + Sea Surface Temperature + + + The L3C product derived from GOES16/ABI brightness temperatures. + + + Geostationary Sea Surface Temperature Product User Manual, http://www.osi-saf.org + + + OSISAF + + + METEO-FRANCE/CMS SAFOS processor + + + + + + All intellectual property rights of the Ocean & Sea Ice SAF products belong to EUMETSAT. The use of these products is granted to every user, free of charge. If users wish to use these products, EUMETSAT's copyright credit must be shown by displaying the words 'Copyright EUMETSAT' under each of the products shown. EUMETSAT offers no warranty and accepts no liability in respect of the Ocean & Sea Ice SAF products. EUMETSAT neither commits to nor guarantees the continuity, availability, or quality or suitability for any purpose of, the Ocean & Sea Ice SAF products. + + + GOES16-OSISAF-L3C-v1.0 + + + org.ghrsst + + + 1.0 + + + 2.0 + + + 0.05 degree + + + 60. + + + -60. + + + -15. + + + -135. + + + GOES_ABI + + + GOES16 + + + GOES_ABI + + + Unidata Dataset Discovery v1.0 + + + N/A + + + Oceans > Ocean Temperature > Sea Surface Temperature + + + NASA Global Change Master Directory (GCMD) Science Keywords + + + NetCDF Climate and Forecast (CF) Metadata Convention + + + degrees_north + + + 0.050000000000000003 + + + degrees_east + + + 0.050000000000000003 + + + In case SAF data (pre-operational or operational) has been used for the study described in a paper the following sentence would be an appropriate reference to the funding coming from EUMETSAT: The data from the EUMETSAT Satellite Application Facility on Ocean & Sea Ice used in this study are accessible through the SAF's homepage http://www.osi-saf.org + + + O&SI SAF + + + osi-saf.helpdesk@meteo.fr + + + http://www.osi-saf.org + + + Group for High Resolution Sea Surface Temperature + + + The GHRSST Project Office + + + http://www.ghrsst.org + + + ghrsst-po@nceo.ac.uk + + + L3C + + + grid + + + 20180101T020918Z + + + 2 + + + 20171231T233000Z + + + 20171231T233000Z + + + 20180101T003000Z + + + 20180101T003000Z + + + D9299038-EE98-11E7-B2C3-0024E836CC1A + + + removed-version + + + + removed-version + + + removed-version + + + libdap-removed-version + + + +# TheBESKeys::get_as_config() +AllowedHosts=^https?:\/\/ +BES.Catalog.catalog.FollowSymLinks=Yes +BES.Catalog.catalog.RootDirectory=/tmp/tmpxqbuljki/ +BES.Catalog.catalog.TypeMatch=dmrpp:.*\.(dmrpp)$; +BES.Catalog.catalog.TypeMatch+=h5:.*(\.bz2|\.gz|\.Z)?$; +BES.Data.RootDirectory=/dev/null +BES.LogName=./bes.log +BES.UncompressCache.dir=/tmp/hyrax_ux +BES.UncompressCache.prefix=ux_ +BES.UncompressCache.size=500 +BES.module.cmd=/usr/lib64/bes/libdap_xml_module.so +BES.module.dap=/usr/lib64/bes/libdap_module.so +BES.module.dmrpp=/usr/lib64/bes/libdmrpp_module.so +BES.module.fonc=/usr/lib64/bes/libfonc_module.so +BES.module.h5=/usr/lib64/bes/libhdf5_module.so +BES.module.nc=/usr/lib64/bes/libnc_module.so +BES.modules=dap,cmd,h5,dmrpp,nc,fonc +FONc.ClassicModel=false +FONc.NoGlobalAttrs=true +H5.EnableCF=false +H5.EnableCheckNameClashing=true + + + + build_dmrpp -c /tmp/bes_conf_lvQa -f /tmp/tmpxqbuljki//20180101000000-OSISAF-L3C_GHRSST-SSTsubskin-GOES16-ssteqc_goes16_20180101_000000-v02.0-fv01.0.nc -r /tmp/dmr__mtGDjT -u OPeNDAP_DMRpp_DATA_ACCESS_URL -M + + + + +The data: +Float32 lon[lon = 2400] = {-134.975, -134.925, -134.875, -134.825, -134.775, -134.725, -134.675, -134.625, -134.575, -134.525, -134.475, -134.425, -134.375, -134.325, -134.275, -134.225, -134.175, -134.125, -134.075, -134.025, -133.975, -133.925, -133.875, -133.825, -133.775, -133.725, -133.675, -133.625, -133.575, -133.525, -133.475, -133.425, -133.375, -133.325, -133.275, -133.225, -133.175, -133.125, -133.075, -133.025, -132.975, -132.925, -132.875, -132.825, -132.775, -132.725, -132.675, -132.625, -132.575, -132.525, -132.475, -132.425, -132.375, -132.325, -132.275, -132.225, -132.175, -132.125, -132.075, -132.025, -131.975, -131.925, -131.875, -131.825, -131.775, -131.725, -131.675, -131.625, -131.575, -131.525, -131.475, -131.425, -131.375, -131.325, -131.275, -131.225, -131.175, -131.125, -131.075, -131.025, -130.975, -130.925, -130.875, -130.825, -130.775, -130.725, -130.675, -130.625, -130.575, -130.525, -130.475, -130.425, -130.375, -130.325, -130.275, -130.225, -130.175, -130.125, -130.075, -130.025, -129.975, -129.925, -129.875, -129.825, -129.775, -129.725, -129.675, -129.625, -129.575, -129.525, -129.475, -129.425, -129.375, -129.325, -129.275, -129.225, -129.175, -129.125, -129.075, -129.025, -128.975, -128.925, -128.875, -128.825, -128.775, -128.725, -128.675, -128.625, -128.575, -128.525, -128.475, -128.425, -128.375, -128.325, -128.275, -128.225, -128.175, -128.125, -128.075, -128.025, -127.975, -127.925, -127.875, -127.825, -127.775, -127.725, -127.675, -127.625, -127.575, -127.525, -127.475, -127.425, -127.375, -127.325, -127.275, -127.225, -127.175, -127.125, -127.075, -127.025, -126.975, -126.925, -126.875, -126.825, -126.775, -126.725, -126.675, -126.625, -126.575, -126.525, -126.475, -126.425, -126.375, -126.325, -126.275, -126.225, -126.175, -126.125, -126.075, -126.025, -125.975, -125.925, -125.875, -125.825, -125.775, -125.725, -125.675, -125.625, -125.575, -125.525, -125.475, -125.425, -125.375, -125.325, -125.275, -125.225, -125.175, -125.125, -125.075, -125.025, -124.975, -124.925, -124.875, -124.825, -124.775, -124.725, -124.675, -124.625, -124.575, -124.525, -124.475, -124.425, -124.375, -124.325, -124.275, -124.225, -124.175, -124.125, -124.075, -124.025, -123.975, -123.925, -123.875, -123.825, -123.775, -123.725, -123.675, -123.625, -123.575, -123.525, -123.475, -123.425, -123.375, -123.325, -123.275, -123.225, -123.175, -123.125, -123.075, -123.025, -122.975, -122.925, -122.875, -122.825, -122.775, -122.725, -122.675, -122.625, -122.575, -122.525, -122.475, -122.425, -122.375, -122.325, -122.275, -122.225, -122.175, -122.125, -122.075, -122.025, -121.975, -121.925, -121.875, -121.825, -121.775, -121.725, -121.675, -121.625, -121.575, -121.525, -121.475, -121.425, -121.375, -121.325, -121.275, -121.225, -121.175, -121.125, -121.075, -121.025, -120.975, -120.925, -120.875, -120.825, -120.775, -120.725, -120.675, -120.625, -120.575, -120.525, -120.475, -120.425, -120.375, -120.325, -120.275, -120.225, -120.175, -120.125, -120.075, -120.025, -119.975, -119.925, -119.875, -119.825, -119.775, -119.725, -119.675, -119.625, -119.575, -119.525, -119.475, -119.425, -119.375, -119.325, -119.275, -119.225, -119.175, -119.125, -119.075, -119.025, -118.975, -118.925, -118.875, -118.825, -118.775, -118.725, -118.675, -118.625, -118.575, -118.525, -118.475, -118.425, -118.375, -118.325, -118.275, -118.225, -118.175, -118.125, -118.075, -118.025, -117.975, -117.925, -117.875, -117.825, -117.775, -117.725, -117.675, -117.625, -117.575, -117.525, -117.475, -117.425, -117.375, -117.325, -117.275, -117.225, -117.175, -117.125, -117.075, -117.025, -116.975, -116.925, -116.875, -116.825, -116.775, -116.725, -116.675, -116.625, -116.575, -116.525, -116.475, -116.425, -116.375, -116.325, -116.275, -116.225, -116.175, -116.125, -116.075, -116.025, -115.975, -115.925, -115.875, -115.825, -115.775, -115.725, -115.675, -115.625, -115.575, -115.525, -115.475, -115.425, -115.375, -115.325, -115.275, -115.225, -115.175, -115.125, -115.075, -115.025, -114.975, -114.925, -114.875, -114.825, -114.775, -114.725, -114.675, -114.625, -114.575, -114.525, -114.475, -114.425, -114.375, -114.325, -114.275, -114.225, -114.175, -114.125, -114.075, -114.025, -113.975, -113.925, -113.875, -113.825, -113.775, -113.725, -113.675, -113.625, -113.575, -113.525, -113.475, -113.425, -113.375, -113.325, -113.275, -113.225, -113.175, -113.125, -113.075, -113.025, -112.975, -112.925, -112.875, -112.825, -112.775, -112.725, -112.675, -112.625, -112.575, -112.525, -112.475, -112.425, -112.375, -112.325, -112.275, -112.225, -112.175, -112.125, -112.075, -112.025, -111.975, -111.925, -111.875, -111.825, -111.775, -111.725, -111.675, -111.625, -111.575, -111.525, -111.475, -111.425, -111.375, -111.325, -111.275, -111.225, -111.175, -111.125, -111.075, -111.025, -110.975, -110.925, -110.875, -110.825, -110.775, -110.725, -110.675, -110.625, -110.575, -110.525, -110.475, -110.425, -110.375, -110.325, -110.275, -110.225, -110.175, -110.125, -110.075, -110.025, -109.975, -109.925, -109.875, -109.825, -109.775, -109.725, -109.675, -109.625, -109.575, -109.525, -109.475, -109.425, -109.375, -109.325, -109.275, -109.225, -109.175, -109.125, -109.075, -109.025, -108.975, -108.925, -108.875, -108.825, -108.775, -108.725, -108.675, -108.625, -108.575, -108.525, -108.475, -108.425, -108.375, -108.325, -108.275, -108.225, -108.175, -108.125, -108.075, -108.025, -107.975, -107.925, -107.875, -107.825, -107.775, -107.725, -107.675, -107.625, -107.575, -107.525, -107.475, -107.425, -107.375, -107.325, -107.275, -107.225, -107.175, -107.125, -107.075, -107.025, -106.975, -106.925, -106.875, -106.825, -106.775, -106.725, -106.675, -106.625, -106.575, -106.525, -106.475, -106.425, -106.375, -106.325, -106.275, -106.225, -106.175, -106.125, -106.075, -106.025, -105.975, -105.925, -105.875, -105.825, -105.775, -105.725, -105.675, -105.625, -105.575, -105.525, -105.475, -105.425, -105.375, -105.325, -105.275, -105.225, -105.175, -105.125, -105.075, -105.025, -104.975, -104.925, -104.875, -104.825, -104.775, -104.725, -104.675, -104.625, -104.575, -104.525, -104.475, -104.425, -104.375, -104.325, -104.275, -104.225, -104.175, -104.125, -104.075, -104.025, -103.975, -103.925, -103.875, -103.825, -103.775, -103.725, -103.675, -103.625, -103.575, -103.525, -103.475, -103.425, -103.375, -103.325, -103.275, -103.225, -103.175, -103.125, -103.075, -103.025, -102.975, -102.925, -102.875, -102.825, -102.775, -102.725, -102.675, -102.625, -102.575, -102.525, -102.475, -102.425, -102.375, -102.325, -102.275, -102.225, -102.175, -102.125, -102.075, -102.025, -101.975, -101.925, -101.875, -101.825, -101.775, -101.725, -101.675, -101.625, -101.575, -101.525, -101.475, -101.425, -101.375, -101.325, -101.275, -101.225, -101.175, -101.125, -101.075, -101.025, -100.975, -100.925, -100.875, -100.825, -100.775, -100.725, -100.675, -100.625, -100.575, -100.525, -100.475, -100.425, -100.375, -100.325, -100.275, -100.225, -100.175, -100.125, -100.075, -100.025, -99.975, -99.925, -99.875, -99.825, -99.775, -99.725, -99.675, -99.625, -99.575, -99.525, -99.475, -99.425, -99.375, -99.325, -99.275, -99.225, -99.175, -99.125, -99.075, -99.025, -98.975, -98.925, -98.875, -98.825, -98.775, -98.725, -98.675, -98.625, -98.575, -98.525, -98.475, -98.425, -98.375, -98.325, -98.275, -98.225, -98.175, -98.125, -98.075, -98.025, -97.975, -97.925, -97.875, -97.825, -97.775, -97.725, -97.675, -97.625, -97.575, -97.525, -97.475, -97.425, -97.375, -97.325, -97.275, -97.225, -97.175, -97.125, -97.075, -97.025, -96.975, -96.925, -96.875, -96.825, -96.775, -96.725, -96.675, -96.625, -96.575, -96.525, -96.475, -96.425, -96.375, -96.325, -96.275, -96.225, -96.175, -96.125, -96.075, -96.025, -95.975, -95.925, -95.875, -95.825, -95.775, -95.725, -95.675, -95.625, -95.575, -95.525, -95.475, -95.425, -95.375, -95.325, -95.275, -95.225, -95.175, -95.125, -95.075, -95.025, -94.975, -94.925, -94.875, -94.825, -94.775, -94.725, -94.675, -94.625, -94.575, -94.525, -94.475, -94.425, -94.375, -94.325, -94.275, -94.225, -94.175, -94.125, -94.075, -94.025, -93.975, -93.925, -93.875, -93.825, -93.775, -93.725, -93.675, -93.625, -93.575, -93.525, -93.475, -93.425, -93.375, -93.325, -93.275, -93.225, -93.175, -93.125, -93.075, -93.025, -92.975, -92.925, -92.875, -92.825, -92.775, -92.725, -92.675, -92.625, -92.575, -92.525, -92.475, -92.425, -92.375, -92.325, -92.275, -92.225, -92.175, -92.125, -92.075, -92.025, -91.975, -91.925, -91.875, -91.825, -91.775, -91.725, -91.675, -91.625, -91.575, -91.525, -91.475, -91.425, -91.375, -91.325, -91.275, -91.225, -91.175, -91.125, -91.075, -91.025, -90.975, -90.925, -90.875, -90.825, -90.775, -90.725, -90.675, -90.625, -90.575, -90.525, -90.475, -90.425, -90.375, -90.325, -90.275, -90.225, -90.175, -90.125, -90.075, -90.025, -89.975, -89.925, -89.875, -89.825, -89.775, -89.725, -89.675, -89.625, -89.575, -89.525, -89.475, -89.425, -89.375, -89.325, -89.275, -89.225, -89.175, -89.125, -89.075, -89.025, -88.975, -88.925, -88.875, -88.825, -88.775, -88.725, -88.675, -88.625, -88.575, -88.525, -88.475, -88.425, -88.375, -88.325, -88.275, -88.225, -88.175, -88.125, -88.075, -88.025, -87.975, -87.925, -87.875, -87.825, -87.775, -87.725, -87.675, -87.625, -87.575, -87.525, -87.475, -87.425, -87.375, -87.325, -87.275, -87.225, -87.175, -87.125, -87.075, -87.025, -86.975, -86.925, -86.875, -86.825, -86.775, -86.725, -86.675, -86.625, -86.575, -86.525, -86.475, -86.425, -86.375, -86.325, -86.275, -86.225, -86.175, -86.125, -86.075, -86.025, -85.975, -85.925, -85.875, -85.825, -85.775, -85.725, -85.675, -85.625, -85.575, -85.525, -85.475, -85.425, -85.375, -85.325, -85.275, -85.225, -85.175, -85.125, -85.075, -85.025, -84.975, -84.925, -84.875, -84.825, -84.775, -84.725, -84.675, -84.625, -84.575, -84.525, -84.475, -84.425, -84.375, -84.325, -84.275, -84.225, -84.175, -84.125, -84.075, -84.025, -83.975, -83.925, -83.875, -83.825, -83.775, -83.725, -83.675, -83.625, -83.575, -83.525, -83.475, -83.425, -83.375, -83.325, -83.275, -83.225, -83.175, -83.125, -83.075, -83.025, -82.975, -82.925, -82.875, -82.825, -82.775, -82.725, -82.675, -82.625, -82.575, -82.525, -82.475, -82.425, -82.375, -82.325, -82.275, -82.225, -82.175, -82.125, -82.075, -82.025, -81.975, -81.925, -81.875, -81.825, -81.775, -81.725, -81.675, -81.625, -81.575, -81.525, -81.475, -81.425, -81.375, -81.325, -81.275, -81.225, -81.175, -81.125, -81.075, -81.025, -80.975, -80.925, -80.875, -80.825, -80.775, -80.725, -80.675, -80.625, -80.575, -80.525, -80.475, -80.425, -80.375, -80.325, -80.275, -80.225, -80.175, -80.125, -80.075, -80.025, -79.975, -79.925, -79.875, -79.825, -79.775, -79.725, -79.675, -79.625, -79.575, -79.525, -79.475, -79.425, -79.375, -79.325, -79.275, -79.225, -79.175, -79.125, -79.075, -79.025, -78.975, -78.925, -78.875, -78.825, -78.775, -78.725, -78.675, -78.625, -78.575, -78.525, -78.475, -78.425, -78.375, -78.325, -78.275, -78.225, -78.175, -78.125, -78.075, -78.025, -77.975, -77.925, -77.875, -77.825, -77.775, -77.725, -77.675, -77.625, -77.575, -77.525, -77.475, -77.425, -77.375, -77.325, -77.275, -77.225, -77.175, -77.125, -77.075, -77.025, -76.975, -76.925, -76.875, -76.825, -76.775, -76.725, -76.675, -76.625, -76.575, -76.525, -76.475, -76.425, -76.375, -76.325, -76.275, -76.225, -76.175, -76.125, -76.075, -76.025, -75.975, -75.925, -75.875, -75.825, -75.775, -75.725, -75.675, -75.625, -75.575, -75.525, -75.475, -75.425, -75.375, -75.325, -75.275, -75.225, -75.175, -75.125, -75.075, -75.025, -74.975, -74.925, -74.875, -74.825, -74.775, -74.725, -74.675, -74.625, -74.575, -74.525, -74.475, -74.425, -74.375, -74.325, -74.275, -74.225, -74.175, -74.125, -74.075, -74.025, -73.975, -73.925, -73.875, -73.825, -73.775, -73.725, -73.675, -73.625, -73.575, -73.525, -73.475, -73.425, -73.375, -73.325, -73.275, -73.225, -73.175, -73.125, -73.075, -73.025, -72.975, -72.925, -72.875, -72.825, -72.775, -72.725, -72.675, -72.625, -72.575, -72.525, -72.475, -72.425, -72.375, -72.325, -72.275, -72.225, -72.175, -72.125, -72.075, -72.025, -71.975, -71.925, -71.875, -71.825, -71.775, -71.725, -71.675, -71.625, -71.575, -71.525, -71.475, -71.425, -71.375, -71.325, -71.275, -71.225, -71.175, -71.125, -71.075, -71.025, -70.975, -70.925, -70.875, -70.825, -70.775, -70.725, -70.675, -70.625, -70.575, -70.525, -70.475, -70.425, -70.375, -70.325, -70.275, -70.225, -70.175, -70.125, -70.075, -70.025, -69.975, -69.925, -69.875, -69.825, -69.775, -69.725, -69.675, -69.625, -69.575, -69.525, -69.475, -69.425, -69.375, -69.325, -69.275, -69.225, -69.175, -69.125, -69.075, -69.025, -68.975, -68.925, -68.875, -68.825, -68.775, -68.725, -68.675, -68.625, -68.575, -68.525, -68.475, -68.425, -68.375, -68.325, -68.275, -68.225, -68.175, -68.125, -68.075, -68.025, -67.975, -67.925, -67.875, -67.825, -67.775, -67.725, -67.675, -67.625, -67.575, -67.525, -67.475, -67.425, -67.375, -67.325, -67.275, -67.225, -67.175, -67.125, -67.075, -67.025, -66.975, -66.925, -66.875, -66.825, -66.775, -66.725, -66.675, -66.625, -66.575, -66.525, -66.475, -66.425, -66.375, -66.325, -66.275, -66.225, -66.175, -66.125, -66.075, -66.025, -65.975, -65.925, -65.875, -65.825, -65.775, -65.725, -65.675, -65.625, -65.575, -65.525, -65.475, -65.425, -65.375, -65.325, -65.275, -65.225, -65.175, -65.125, -65.075, -65.025, -64.975, -64.925, -64.875, -64.825, -64.775, -64.725, -64.675, -64.625, -64.575, -64.525, -64.475, -64.425, -64.375, -64.325, -64.275, -64.225, -64.175, -64.125, -64.075, -64.025, -63.975, -63.925, -63.875, -63.825, -63.775, -63.725, -63.675, -63.625, -63.575, -63.525, -63.475, -63.425, -63.375, -63.325, -63.275, -63.225, -63.175, -63.125, -63.075, -63.025, -62.975, -62.925, -62.875, -62.825, -62.775, -62.725, -62.675, -62.625, -62.575, -62.525, -62.475, -62.425, -62.375, -62.325, -62.275, -62.225, -62.175, -62.125, -62.075, -62.025, -61.975, -61.925, -61.875, -61.825, -61.775, -61.725, -61.675, -61.625, -61.575, -61.525, -61.475, -61.425, -61.375, -61.325, -61.275, -61.225, -61.175, -61.125, -61.075, -61.025, -60.975, -60.925, -60.875, -60.825, -60.775, -60.725, -60.675, -60.625, -60.575, -60.525, -60.475, -60.425, -60.375, -60.325, -60.275, -60.225, -60.175, -60.125, -60.075, -60.025, -59.975, -59.925, -59.875, -59.825, -59.775, -59.725, -59.675, -59.625, -59.575, -59.525, -59.475, -59.425, -59.375, -59.325, -59.275, -59.225, -59.175, -59.125, -59.075, -59.025, -58.975, -58.925, -58.875, -58.825, -58.775, -58.725, -58.675, -58.625, -58.575, -58.525, -58.475, -58.425, -58.375, -58.325, -58.275, -58.225, -58.175, -58.125, -58.075, -58.025, -57.975, -57.925, -57.875, -57.825, -57.775, -57.725, -57.675, -57.625, -57.575, -57.525, -57.475, -57.425, -57.375, -57.325, -57.275, -57.225, -57.175, -57.125, -57.075, -57.025, -56.975, -56.925, -56.875, -56.825, -56.775, -56.725, -56.675, -56.625, -56.575, -56.525, -56.475, -56.425, -56.375, -56.325, -56.275, -56.225, -56.175, -56.125, -56.075, -56.025, -55.975, -55.925, -55.875, -55.825, -55.775, -55.725, -55.675, -55.625, -55.575, -55.525, -55.475, -55.425, -55.375, -55.325, -55.275, -55.225, -55.175, -55.125, -55.075, -55.025, -54.975, -54.925, -54.875, -54.825, -54.775, -54.725, -54.675, -54.625, -54.575, -54.525, -54.475, -54.425, -54.375, -54.325, -54.275, -54.225, -54.175, -54.125, -54.075, -54.025, -53.975, -53.925, -53.875, -53.825, -53.775, -53.725, -53.675, -53.625, -53.575, -53.525, -53.475, -53.425, -53.375, -53.325, -53.275, -53.225, -53.175, -53.125, -53.075, -53.025, -52.975, -52.925, -52.875, -52.825, -52.775, -52.725, -52.675, -52.625, -52.575, -52.525, -52.475, -52.425, -52.375, -52.325, -52.275, -52.225, -52.175, -52.125, -52.075, -52.025, -51.975, -51.925, -51.875, -51.825, -51.775, -51.725, -51.675, -51.625, -51.575, -51.525, -51.475, -51.425, -51.375, -51.325, -51.275, -51.225, -51.175, -51.125, -51.075, -51.025, -50.975, -50.925, -50.875, -50.825, -50.775, -50.725, -50.675, -50.625, -50.575, -50.525, -50.475, -50.425, -50.375, -50.325, -50.275, -50.225, -50.175, -50.125, -50.075, -50.025, -49.975, -49.925, -49.875, -49.825, -49.775, -49.725, -49.675, -49.625, -49.575, -49.525, -49.475, -49.425, -49.375, -49.325, -49.275, -49.225, -49.175, -49.125, -49.075, -49.025, -48.975, -48.925, -48.875, -48.825, -48.775, -48.725, -48.675, -48.625, -48.575, -48.525, -48.475, -48.425, -48.375, -48.325, -48.275, -48.225, -48.175, -48.125, -48.075, -48.025, -47.975, -47.925, -47.875, -47.825, -47.775, -47.725, -47.675, -47.625, -47.575, -47.525, -47.475, -47.425, -47.375, -47.325, -47.275, -47.225, -47.175, -47.125, -47.075, -47.025, -46.975, -46.925, -46.875, -46.825, -46.775, -46.725, -46.675, -46.625, -46.575, -46.525, -46.475, -46.425, -46.375, -46.325, -46.275, -46.225, -46.175, -46.125, -46.075, -46.025, -45.975, -45.925, -45.875, -45.825, -45.775, -45.725, -45.675, -45.625, -45.575, -45.525, -45.475, -45.425, -45.375, -45.325, -45.275, -45.225, -45.175, -45.125, -45.075, -45.025, -44.975, -44.925, -44.875, -44.825, -44.775, -44.725, -44.675, -44.625, -44.575, -44.525, -44.475, -44.425, -44.375, -44.325, -44.275, -44.225, -44.175, -44.125, -44.075, -44.025, -43.975, -43.925, -43.875, -43.825, -43.775, -43.725, -43.675, -43.625, -43.575, -43.525, -43.475, -43.425, -43.375, -43.325, -43.275, -43.225, -43.175, -43.125, -43.075, -43.025, -42.975, -42.925, -42.875, -42.825, -42.775, -42.725, -42.675, -42.625, -42.575, -42.525, -42.475, -42.425, -42.375, -42.325, -42.275, -42.225, -42.175, -42.125, -42.075, -42.025, -41.975, -41.925, -41.875, -41.825, -41.775, -41.725, -41.675, -41.625, -41.575, -41.525, -41.475, -41.425, -41.375, -41.325, -41.275, -41.225, -41.175, -41.125, -41.075, -41.025, -40.975, -40.925, -40.875, -40.825, -40.775, -40.725, -40.675, -40.625, -40.575, -40.525, -40.475, -40.425, -40.375, -40.325, -40.275, -40.225, -40.175, -40.125, -40.075, -40.025, -39.975, -39.925, -39.875, -39.825, -39.775, -39.725, -39.675, -39.625, -39.575, -39.525, -39.475, -39.425, -39.375, -39.325, -39.275, -39.225, -39.175, -39.125, -39.075, -39.025, -38.975, -38.925, -38.875, -38.825, -38.775, -38.725, -38.675, -38.625, -38.575, -38.525, -38.475, -38.425, -38.375, -38.325, -38.275, -38.225, -38.175, -38.125, -38.075, -38.025, -37.975, -37.925, -37.875, -37.825, -37.775, -37.725, -37.675, -37.625, -37.575, -37.525, -37.475, -37.425, -37.375, -37.325, -37.275, -37.225, -37.175, -37.125, -37.075, -37.025, -36.975, -36.925, -36.875, -36.825, -36.775, -36.725, -36.675, -36.625, -36.575, -36.525, -36.475, -36.425, -36.375, -36.325, -36.275, -36.225, -36.175, -36.125, -36.075, -36.025, -35.975, -35.925, -35.875, -35.825, -35.775, -35.725, -35.675, -35.625, -35.575, -35.525, -35.475, -35.425, -35.375, -35.325, -35.275, -35.225, -35.175, -35.125, -35.075, -35.025, -34.975, -34.925, -34.875, -34.825, -34.775, -34.725, -34.675, -34.625, -34.575, -34.525, -34.475, -34.425, -34.375, -34.325, -34.275, -34.225, -34.175, -34.125, -34.075, -34.025, -33.975, -33.925, -33.875, -33.825, -33.775, -33.725, -33.675, -33.625, -33.575, -33.525, -33.475, -33.425, -33.375, -33.325, -33.275, -33.225, -33.175, -33.125, -33.075, -33.025, -32.975, -32.925, -32.875, -32.825, -32.775, -32.725, -32.675, -32.625, -32.575, -32.525, -32.475, -32.425, -32.375, -32.325, -32.275, -32.225, -32.175, -32.125, -32.075, -32.025, -31.975, -31.925, -31.875, -31.825, -31.775, -31.725, -31.675, -31.625, -31.575, -31.525, -31.475, -31.425, -31.375, -31.325, -31.275, -31.225, -31.175, -31.125, -31.075, -31.025, -30.975, -30.925, -30.875, -30.825, -30.775, -30.725, -30.675, -30.625, -30.575, -30.525, -30.475, -30.425, -30.375, -30.325, -30.275, -30.225, -30.175, -30.125, -30.075, -30.025, -29.975, -29.925, -29.875, -29.825, -29.775, -29.725, -29.675, -29.625, -29.575, -29.525, -29.475, -29.425, -29.375, -29.325, -29.275, -29.225, -29.175, -29.125, -29.075, -29.025, -28.975, -28.925, -28.875, -28.825, -28.775, -28.725, -28.675, -28.625, -28.575, -28.525, -28.475, -28.425, -28.375, -28.325, -28.275, -28.225, -28.175, -28.125, -28.075, -28.025, -27.975, -27.925, -27.875, -27.825, -27.775, -27.725, -27.675, -27.625, -27.575, -27.525, -27.475, -27.425, -27.375, -27.325, -27.275, -27.225, -27.175, -27.125, -27.075, -27.025, -26.975, -26.925, -26.875, -26.825, -26.775, -26.725, -26.675, -26.625, -26.575, -26.525, -26.475, -26.425, -26.375, -26.325, -26.275, -26.225, -26.175, -26.125, -26.075, -26.025, -25.975, -25.925, -25.875, -25.825, -25.775, -25.725, -25.675, -25.625, -25.575, -25.525, -25.475, -25.425, -25.375, -25.325, -25.275, -25.225, -25.175, -25.125, -25.075, -25.025, -24.975, -24.925, -24.875, -24.825, -24.775, -24.725, -24.675, -24.625, -24.575, -24.525, -24.475, -24.425, -24.375, -24.325, -24.275, -24.225, -24.175, -24.125, -24.075, -24.025, -23.975, -23.925, -23.875, -23.825, -23.775, -23.725, -23.675, -23.625, -23.575, -23.525, -23.475, -23.425, -23.375, -23.325, -23.275, -23.225, -23.175, -23.125, -23.075, -23.025, -22.975, -22.925, -22.875, -22.825, -22.775, -22.725, -22.675, -22.625, -22.575, -22.525, -22.475, -22.425, -22.375, -22.325, -22.275, -22.225, -22.175, -22.125, -22.075, -22.025, -21.975, -21.925, -21.875, -21.825, -21.775, -21.725, -21.675, -21.625, -21.575, -21.525, -21.475, -21.425, -21.375, -21.325, -21.275, -21.225, -21.175, -21.125, -21.075, -21.025, -20.975, -20.925, -20.875, -20.825, -20.775, -20.725, -20.675, -20.625, -20.575, -20.525, -20.475, -20.425, -20.375, -20.325, -20.275, -20.225, -20.175, -20.125, -20.075, -20.025, -19.975, -19.925, -19.875, -19.825, -19.775, -19.725, -19.675, -19.625, -19.575, -19.525, -19.475, -19.425, -19.375, -19.325, -19.275, -19.225, -19.175, -19.125, -19.075, -19.025, -18.975, -18.925, -18.875, -18.825, -18.775, -18.725, -18.675, -18.625, -18.575, -18.525, -18.475, -18.425, -18.375, -18.325, -18.275, -18.225, -18.175, -18.125, -18.075, -18.025, -17.975, -17.925, -17.875, -17.825, -17.775, -17.725, -17.675, -17.625, -17.575, -17.525, -17.475, -17.425, -17.375, -17.325, -17.275, -17.225, -17.175, -17.125, -17.075, -17.025, -16.975, -16.925, -16.875, -16.825, -16.775, -16.725, -16.675, -16.625, -16.575, -16.525, -16.475, -16.425, -16.375, -16.325, -16.275, -16.225, -16.175, -16.125, -16.075, -16.025, -15.975, -15.925, -15.875, -15.825, -15.775, -15.725, -15.675, -15.625, -15.575, -15.525, -15.475, -15.425, -15.375, -15.325, -15.275, -15.225, -15.175, -15.125, -15.075, -15.025}; +Float32 lat[lat = 2400] = {-59.975, -59.925, -59.875, -59.825, -59.775, -59.725, -59.675, -59.625, -59.575, -59.525, -59.475, -59.425, -59.375, -59.325, -59.275, -59.225, -59.175, -59.125, -59.075, -59.025, -58.975, -58.925, -58.875, -58.825, -58.775, -58.725, -58.675, -58.625, -58.575, -58.525, -58.475, -58.425, -58.375, -58.325, -58.275, -58.225, -58.175, -58.125, -58.075, -58.025, -57.975, -57.925, -57.875, -57.825, -57.775, -57.725, -57.675, -57.625, -57.575, -57.525, -57.475, -57.425, -57.375, -57.325, -57.275, -57.225, -57.175, -57.125, -57.075, -57.025, -56.975, -56.925, -56.875, -56.825, -56.775, -56.725, -56.675, -56.625, -56.575, -56.525, -56.475, -56.425, -56.375, -56.325, -56.275, -56.225, -56.175, -56.125, -56.075, -56.025, -55.975, -55.925, -55.875, -55.825, -55.775, -55.725, -55.675, -55.625, -55.575, -55.525, -55.475, -55.425, -55.375, -55.325, -55.275, -55.225, -55.175, -55.125, -55.075, -55.025, -54.975, -54.925, -54.875, -54.825, -54.775, -54.725, -54.675, -54.625, -54.575, -54.525, -54.475, -54.425, -54.375, -54.325, -54.275, -54.225, -54.175, -54.125, -54.075, -54.025, -53.975, -53.925, -53.875, -53.825, -53.775, -53.725, -53.675, -53.625, -53.575, -53.525, -53.475, -53.425, -53.375, -53.325, -53.275, -53.225, -53.175, -53.125, -53.075, -53.025, -52.975, -52.925, -52.875, -52.825, -52.775, -52.725, -52.675, -52.625, -52.575, -52.525, -52.475, -52.425, -52.375, -52.325, -52.275, -52.225, -52.175, -52.125, -52.075, -52.025, -51.975, -51.925, -51.875, -51.825, -51.775, -51.725, -51.675, -51.625, -51.575, -51.525, -51.475, -51.425, -51.375, -51.325, -51.275, -51.225, -51.175, -51.125, -51.075, -51.025, -50.975, -50.925, -50.875, -50.825, -50.775, -50.725, -50.675, -50.625, -50.575, -50.525, -50.475, -50.425, -50.375, -50.325, -50.275, -50.225, -50.175, -50.125, -50.075, -50.025, -49.975, -49.925, -49.875, -49.825, -49.775, -49.725, -49.675, -49.625, -49.575, -49.525, -49.475, -49.425, -49.375, -49.325, -49.275, -49.225, -49.175, -49.125, -49.075, -49.025, -48.975, -48.925, -48.875, -48.825, -48.775, -48.725, -48.675, -48.625, -48.575, -48.525, -48.475, -48.425, -48.375, -48.325, -48.275, -48.225, -48.175, -48.125, -48.075, -48.025, -47.975, -47.925, -47.875, -47.825, -47.775, -47.725, -47.675, -47.625, -47.575, -47.525, -47.475, -47.425, -47.375, -47.325, -47.275, -47.225, -47.175, -47.125, -47.075, -47.025, -46.975, -46.925, -46.875, -46.825, -46.775, -46.725, -46.675, -46.625, -46.575, -46.525, -46.475, -46.425, -46.375, -46.325, -46.275, -46.225, -46.175, -46.125, -46.075, -46.025, -45.975, -45.925, -45.875, -45.825, -45.775, -45.725, -45.675, -45.625, -45.575, -45.525, -45.475, -45.425, -45.375, -45.325, -45.275, -45.225, -45.175, -45.125, -45.075, -45.025, -44.975, -44.925, -44.875, -44.825, -44.775, -44.725, -44.675, -44.625, -44.575, -44.525, -44.475, -44.425, -44.375, -44.325, -44.275, -44.225, -44.175, -44.125, -44.075, -44.025, -43.975, -43.925, -43.875, -43.825, -43.775, -43.725, -43.675, -43.625, -43.575, -43.525, -43.475, -43.425, -43.375, -43.325, -43.275, -43.225, -43.175, -43.125, -43.075, -43.025, -42.975, -42.925, -42.875, -42.825, -42.775, -42.725, -42.675, -42.625, -42.575, -42.525, -42.475, -42.425, -42.375, -42.325, -42.275, -42.225, -42.175, -42.125, -42.075, -42.025, -41.975, -41.925, -41.875, -41.825, -41.775, -41.725, -41.675, -41.625, -41.575, -41.525, -41.475, -41.425, -41.375, -41.325, -41.275, -41.225, -41.175, -41.125, -41.075, -41.025, -40.975, -40.925, -40.875, -40.825, -40.775, -40.725, -40.675, -40.625, -40.575, -40.525, -40.475, -40.425, -40.375, -40.325, -40.275, -40.225, -40.175, -40.125, -40.075, -40.025, -39.975, -39.925, -39.875, -39.825, -39.775, -39.725, -39.675, -39.625, -39.575, -39.525, -39.475, -39.425, -39.375, -39.325, -39.275, -39.225, -39.175, -39.125, -39.075, -39.025, -38.975, -38.925, -38.875, -38.825, -38.775, -38.725, -38.675, -38.625, -38.575, -38.525, -38.475, -38.425, -38.375, -38.325, -38.275, -38.225, -38.175, -38.125, -38.075, -38.025, -37.975, -37.925, -37.875, -37.825, -37.775, -37.725, -37.675, -37.625, -37.575, -37.525, -37.475, -37.425, -37.375, -37.325, -37.275, -37.225, -37.175, -37.125, -37.075, -37.025, -36.975, -36.925, -36.875, -36.825, -36.775, -36.725, -36.675, -36.625, -36.575, -36.525, -36.475, -36.425, -36.375, -36.325, -36.275, -36.225, -36.175, -36.125, -36.075, -36.025, -35.975, -35.925, -35.875, -35.825, -35.775, -35.725, -35.675, -35.625, -35.575, -35.525, -35.475, -35.425, -35.375, -35.325, -35.275, -35.225, -35.175, -35.125, -35.075, -35.025, -34.975, -34.925, -34.875, -34.825, -34.775, -34.725, -34.675, -34.625, -34.575, -34.525, -34.475, -34.425, -34.375, -34.325, -34.275, -34.225, -34.175, -34.125, -34.075, -34.025, -33.975, -33.925, -33.875, -33.825, -33.775, -33.725, -33.675, -33.625, -33.575, -33.525, -33.475, -33.425, -33.375, -33.325, -33.275, -33.225, -33.175, -33.125, -33.075, -33.025, -32.975, -32.925, -32.875, -32.825, -32.775, -32.725, -32.675, -32.625, -32.575, -32.525, -32.475, -32.425, -32.375, -32.325, -32.275, -32.225, -32.175, -32.125, -32.075, -32.025, -31.975, -31.925, -31.875, -31.825, -31.775, -31.725, -31.675, -31.625, -31.575, -31.525, -31.475, -31.425, -31.375, -31.325, -31.275, -31.225, -31.175, -31.125, -31.075, -31.025, -30.975, -30.925, -30.875, -30.825, -30.775, -30.725, -30.675, -30.625, -30.575, -30.525, -30.475, -30.425, -30.375, -30.325, -30.275, -30.225, -30.175, -30.125, -30.075, -30.025, -29.975, -29.925, -29.875, -29.825, -29.775, -29.725, -29.675, -29.625, -29.575, -29.525, -29.475, -29.425, -29.375, -29.325, -29.275, -29.225, -29.175, -29.125, -29.075, -29.025, -28.975, -28.925, -28.875, -28.825, -28.775, -28.725, -28.675, -28.625, -28.575, -28.525, -28.475, -28.425, -28.375, -28.325, -28.275, -28.225, -28.175, -28.125, -28.075, -28.025, -27.975, -27.925, -27.875, -27.825, -27.775, -27.725, -27.675, -27.625, -27.575, -27.525, -27.475, -27.425, -27.375, -27.325, -27.275, -27.225, -27.175, -27.125, -27.075, -27.025, -26.975, -26.925, -26.875, -26.825, -26.775, -26.725, -26.675, -26.625, -26.575, -26.525, -26.475, -26.425, -26.375, -26.325, -26.275, -26.225, -26.175, -26.125, -26.075, -26.025, -25.975, -25.925, -25.875, -25.825, -25.775, -25.725, -25.675, -25.625, -25.575, -25.525, -25.475, -25.425, -25.375, -25.325, -25.275, -25.225, -25.175, -25.125, -25.075, -25.025, -24.975, -24.925, -24.875, -24.825, -24.775, -24.725, -24.675, -24.625, -24.575, -24.525, -24.475, -24.425, -24.375, -24.325, -24.275, -24.225, -24.175, -24.125, -24.075, -24.025, -23.975, -23.925, -23.875, -23.825, -23.775, -23.725, -23.675, -23.625, -23.575, -23.525, -23.475, -23.425, -23.375, -23.325, -23.275, -23.225, -23.175, -23.125, -23.075, -23.025, -22.975, -22.925, -22.875, -22.825, -22.775, -22.725, -22.675, -22.625, -22.575, -22.525, -22.475, -22.425, -22.375, -22.325, -22.275, -22.225, -22.175, -22.125, -22.075, -22.025, -21.975, -21.925, -21.875, -21.825, -21.775, -21.725, -21.675, -21.625, -21.575, -21.525, -21.475, -21.425, -21.375, -21.325, -21.275, -21.225, -21.175, -21.125, -21.075, -21.025, -20.975, -20.925, -20.875, -20.825, -20.775, -20.725, -20.675, -20.625, -20.575, -20.525, -20.475, -20.425, -20.375, -20.325, -20.275, -20.225, -20.175, -20.125, -20.075, -20.025, -19.975, -19.925, -19.875, -19.825, -19.775, -19.725, -19.675, -19.625, -19.575, -19.525, -19.475, -19.425, -19.375, -19.325, -19.275, -19.225, -19.175, -19.125, -19.075, -19.025, -18.975, -18.925, -18.875, -18.825, -18.775, -18.725, -18.675, -18.625, -18.575, -18.525, -18.475, -18.425, -18.375, -18.325, -18.275, -18.225, -18.175, -18.125, -18.075, -18.025, -17.975, -17.925, -17.875, -17.825, -17.775, -17.725, -17.675, -17.625, -17.575, -17.525, -17.475, -17.425, -17.375, -17.325, -17.275, -17.225, -17.175, -17.125, -17.075, -17.025, -16.975, -16.925, -16.875, -16.825, -16.775, -16.725, -16.675, -16.625, -16.575, -16.525, -16.475, -16.425, -16.375, -16.325, -16.275, -16.225, -16.175, -16.125, -16.075, -16.025, -15.975, -15.925, -15.875, -15.825, -15.775, -15.725, -15.675, -15.625, -15.575, -15.525, -15.475, -15.425, -15.375, -15.325, -15.275, -15.225, -15.175, -15.125, -15.075, -15.025, -14.975, -14.925, -14.875, -14.825, -14.775, -14.725, -14.675, -14.625, -14.575, -14.525, -14.475, -14.425, -14.375, -14.325, -14.275, -14.225, -14.175, -14.125, -14.075, -14.025, -13.975, -13.925, -13.875, -13.825, -13.775, -13.725, -13.675, -13.625, -13.575, -13.525, -13.475, -13.425, -13.375, -13.325, -13.275, -13.225, -13.175, -13.125, -13.075, -13.025, -12.975, -12.925, -12.875, -12.825, -12.775, -12.725, -12.675, -12.625, -12.575, -12.525, -12.475, -12.425, -12.375, -12.325, -12.275, -12.225, -12.175, -12.125, -12.075, -12.025, -11.975, -11.925, -11.875, -11.825, -11.775, -11.725, -11.675, -11.625, -11.575, -11.525, -11.475, -11.425, -11.375, -11.325, -11.275, -11.225, -11.175, -11.125, -11.075, -11.025, -10.975, -10.925, -10.875, -10.825, -10.775, -10.725, -10.675, -10.625, -10.575, -10.525, -10.475, -10.425, -10.375, -10.325, -10.275, -10.225, -10.175, -10.125, -10.075, -10.025, -9.975, -9.925, -9.875, -9.825, -9.775, -9.725, -9.675, -9.625, -9.575, -9.525, -9.475, -9.425, -9.375, -9.325, -9.275, -9.225, -9.175, -9.125, -9.075, -9.025, -8.975, -8.925, -8.875, -8.825, -8.775, -8.725, -8.675, -8.625, -8.575, -8.525, -8.475, -8.425, -8.375, -8.325, -8.275, -8.225, -8.175, -8.125, -8.075, -8.025, -7.975, -7.925, -7.875, -7.825, -7.775, -7.725, -7.675, -7.625, -7.575, -7.525, -7.475, -7.425, -7.375, -7.325, -7.275, -7.225, -7.175, -7.125, -7.075, -7.025, -6.975, -6.925, -6.875, -6.825, -6.775, -6.725, -6.675, -6.625, -6.575, -6.525, -6.475, -6.425, -6.375, -6.325, -6.275, -6.225, -6.175, -6.125, -6.075, -6.025, -5.975, -5.925, -5.875, -5.825, -5.775, -5.725, -5.675, -5.625, -5.575, -5.525, -5.475, -5.425, -5.375, -5.325, -5.275, -5.225, -5.175, -5.125, -5.075, -5.025, -4.975, -4.925, -4.875, -4.825, -4.775, -4.725, -4.675, -4.625, -4.575, -4.525, -4.475, -4.425, -4.375, -4.325, -4.275, -4.225, -4.175, -4.125, -4.075, -4.025, -3.975, -3.925, -3.875, -3.825, -3.775, -3.725, -3.675, -3.625, -3.575, -3.525, -3.475, -3.425, -3.375, -3.325, -3.275, -3.225, -3.175, -3.125, -3.075, -3.025, -2.975, -2.925, -2.875, -2.825, -2.775, -2.725, -2.675, -2.625, -2.575, -2.525, -2.475, -2.425, -2.375, -2.325, -2.275, -2.225, -2.175, -2.125, -2.075, -2.025, -1.975, -1.925, -1.875, -1.825, -1.775, -1.725, -1.675, -1.625, -1.575, -1.525, -1.475, -1.425, -1.375, -1.325, -1.275, -1.225, -1.175, -1.125, -1.075, -1.025, -0.975, -0.925, -0.875, -0.825, -0.775, -0.725, -0.675, -0.625, -0.575, -0.525, -0.475, -0.425, -0.375, -0.325, -0.275, -0.225, -0.175, -0.125, -0.075, -0.025, 0.025, 0.075, 0.125, 0.175, 0.225, 0.275, 0.325, 0.375, 0.425, 0.475, 0.525, 0.575, 0.625, 0.675, 0.725, 0.775, 0.825, 0.875, 0.925, 0.975, 1.025, 1.075, 1.125, 1.175, 1.225, 1.275, 1.325, 1.375, 1.425, 1.475, 1.525, 1.575, 1.625, 1.675, 1.725, 1.775, 1.825, 1.875, 1.925, 1.975, 2.025, 2.075, 2.125, 2.175, 2.225, 2.275, 2.325, 2.375, 2.425, 2.475, 2.525, 2.575, 2.625, 2.675, 2.725, 2.775, 2.825, 2.875, 2.925, 2.975, 3.025, 3.075, 3.125, 3.175, 3.225, 3.275, 3.325, 3.375, 3.425, 3.475, 3.525, 3.575, 3.625, 3.675, 3.725, 3.775, 3.825, 3.875, 3.925, 3.975, 4.025, 4.075, 4.125, 4.175, 4.225, 4.275, 4.325, 4.375, 4.425, 4.475, 4.525, 4.575, 4.625, 4.675, 4.725, 4.775, 4.825, 4.875, 4.925, 4.975, 5.025, 5.075, 5.125, 5.175, 5.225, 5.275, 5.325, 5.375, 5.425, 5.475, 5.525, 5.575, 5.625, 5.675, 5.725, 5.775, 5.825, 5.875, 5.925, 5.975, 6.025, 6.075, 6.125, 6.175, 6.225, 6.275, 6.325, 6.375, 6.425, 6.475, 6.525, 6.575, 6.625, 6.675, 6.725, 6.775, 6.825, 6.875, 6.925, 6.975, 7.025, 7.075, 7.125, 7.175, 7.225, 7.275, 7.325, 7.375, 7.425, 7.475, 7.525, 7.575, 7.625, 7.675, 7.725, 7.775, 7.825, 7.875, 7.925, 7.975, 8.025, 8.075, 8.125, 8.175, 8.225, 8.275, 8.325, 8.375, 8.425, 8.475, 8.525, 8.575, 8.625, 8.675, 8.725, 8.775, 8.825, 8.875, 8.925, 8.975, 9.025, 9.075, 9.125, 9.175, 9.225, 9.275, 9.325, 9.375, 9.425, 9.475, 9.525, 9.575, 9.625, 9.675, 9.725, 9.775, 9.825, 9.875, 9.925, 9.975, 10.025, 10.075, 10.125, 10.175, 10.225, 10.275, 10.325, 10.375, 10.425, 10.475, 10.525, 10.575, 10.625, 10.675, 10.725, 10.775, 10.825, 10.875, 10.925, 10.975, 11.025, 11.075, 11.125, 11.175, 11.225, 11.275, 11.325, 11.375, 11.425, 11.475, 11.525, 11.575, 11.625, 11.675, 11.725, 11.775, 11.825, 11.875, 11.925, 11.975, 12.025, 12.075, 12.125, 12.175, 12.225, 12.275, 12.325, 12.375, 12.425, 12.475, 12.525, 12.575, 12.625, 12.675, 12.725, 12.775, 12.825, 12.875, 12.925, 12.975, 13.025, 13.075, 13.125, 13.175, 13.225, 13.275, 13.325, 13.375, 13.425, 13.475, 13.525, 13.575, 13.625, 13.675, 13.725, 13.775, 13.825, 13.875, 13.925, 13.975, 14.025, 14.075, 14.125, 14.175, 14.225, 14.275, 14.325, 14.375, 14.425, 14.475, 14.525, 14.575, 14.625, 14.675, 14.725, 14.775, 14.825, 14.875, 14.925, 14.975, 15.025, 15.075, 15.125, 15.175, 15.225, 15.275, 15.325, 15.375, 15.425, 15.475, 15.525, 15.575, 15.625, 15.675, 15.725, 15.775, 15.825, 15.875, 15.925, 15.975, 16.025, 16.075, 16.125, 16.175, 16.225, 16.275, 16.325, 16.375, 16.425, 16.475, 16.525, 16.575, 16.625, 16.675, 16.725, 16.775, 16.825, 16.875, 16.925, 16.975, 17.025, 17.075, 17.125, 17.175, 17.225, 17.275, 17.325, 17.375, 17.425, 17.475, 17.525, 17.575, 17.625, 17.675, 17.725, 17.775, 17.825, 17.875, 17.925, 17.975, 18.025, 18.075, 18.125, 18.175, 18.225, 18.275, 18.325, 18.375, 18.425, 18.475, 18.525, 18.575, 18.625, 18.675, 18.725, 18.775, 18.825, 18.875, 18.925, 18.975, 19.025, 19.075, 19.125, 19.175, 19.225, 19.275, 19.325, 19.375, 19.425, 19.475, 19.525, 19.575, 19.625, 19.675, 19.725, 19.775, 19.825, 19.875, 19.925, 19.975, 20.025, 20.075, 20.125, 20.175, 20.225, 20.275, 20.325, 20.375, 20.425, 20.475, 20.525, 20.575, 20.625, 20.675, 20.725, 20.775, 20.825, 20.875, 20.925, 20.975, 21.025, 21.075, 21.125, 21.175, 21.225, 21.275, 21.325, 21.375, 21.425, 21.475, 21.525, 21.575, 21.625, 21.675, 21.725, 21.775, 21.825, 21.875, 21.925, 21.975, 22.025, 22.075, 22.125, 22.175, 22.225, 22.275, 22.325, 22.375, 22.425, 22.475, 22.525, 22.575, 22.625, 22.675, 22.725, 22.775, 22.825, 22.875, 22.925, 22.975, 23.025, 23.075, 23.125, 23.175, 23.225, 23.275, 23.325, 23.375, 23.425, 23.475, 23.525, 23.575, 23.625, 23.675, 23.725, 23.775, 23.825, 23.875, 23.925, 23.975, 24.025, 24.075, 24.125, 24.175, 24.225, 24.275, 24.325, 24.375, 24.425, 24.475, 24.525, 24.575, 24.625, 24.675, 24.725, 24.775, 24.825, 24.875, 24.925, 24.975, 25.025, 25.075, 25.125, 25.175, 25.225, 25.275, 25.325, 25.375, 25.425, 25.475, 25.525, 25.575, 25.625, 25.675, 25.725, 25.775, 25.825, 25.875, 25.925, 25.975, 26.025, 26.075, 26.125, 26.175, 26.225, 26.275, 26.325, 26.375, 26.425, 26.475, 26.525, 26.575, 26.625, 26.675, 26.725, 26.775, 26.825, 26.875, 26.925, 26.975, 27.025, 27.075, 27.125, 27.175, 27.225, 27.275, 27.325, 27.375, 27.425, 27.475, 27.525, 27.575, 27.625, 27.675, 27.725, 27.775, 27.825, 27.875, 27.925, 27.975, 28.025, 28.075, 28.125, 28.175, 28.225, 28.275, 28.325, 28.375, 28.425, 28.475, 28.525, 28.575, 28.625, 28.675, 28.725, 28.775, 28.825, 28.875, 28.925, 28.975, 29.025, 29.075, 29.125, 29.175, 29.225, 29.275, 29.325, 29.375, 29.425, 29.475, 29.525, 29.575, 29.625, 29.675, 29.725, 29.775, 29.825, 29.875, 29.925, 29.975, 30.025, 30.075, 30.125, 30.175, 30.225, 30.275, 30.325, 30.375, 30.425, 30.475, 30.525, 30.575, 30.625, 30.675, 30.725, 30.775, 30.825, 30.875, 30.925, 30.975, 31.025, 31.075, 31.125, 31.175, 31.225, 31.275, 31.325, 31.375, 31.425, 31.475, 31.525, 31.575, 31.625, 31.675, 31.725, 31.775, 31.825, 31.875, 31.925, 31.975, 32.025, 32.075, 32.125, 32.175, 32.225, 32.275, 32.325, 32.375, 32.425, 32.475, 32.525, 32.575, 32.625, 32.675, 32.725, 32.775, 32.825, 32.875, 32.925, 32.975, 33.025, 33.075, 33.125, 33.175, 33.225, 33.275, 33.325, 33.375, 33.425, 33.475, 33.525, 33.575, 33.625, 33.675, 33.725, 33.775, 33.825, 33.875, 33.925, 33.975, 34.025, 34.075, 34.125, 34.175, 34.225, 34.275, 34.325, 34.375, 34.425, 34.475, 34.525, 34.575, 34.625, 34.675, 34.725, 34.775, 34.825, 34.875, 34.925, 34.975, 35.025, 35.075, 35.125, 35.175, 35.225, 35.275, 35.325, 35.375, 35.425, 35.475, 35.525, 35.575, 35.625, 35.675, 35.725, 35.775, 35.825, 35.875, 35.925, 35.975, 36.025, 36.075, 36.125, 36.175, 36.225, 36.275, 36.325, 36.375, 36.425, 36.475, 36.525, 36.575, 36.625, 36.675, 36.725, 36.775, 36.825, 36.875, 36.925, 36.975, 37.025, 37.075, 37.125, 37.175, 37.225, 37.275, 37.325, 37.375, 37.425, 37.475, 37.525, 37.575, 37.625, 37.675, 37.725, 37.775, 37.825, 37.875, 37.925, 37.975, 38.025, 38.075, 38.125, 38.175, 38.225, 38.275, 38.325, 38.375, 38.425, 38.475, 38.525, 38.575, 38.625, 38.675, 38.725, 38.775, 38.825, 38.875, 38.925, 38.975, 39.025, 39.075, 39.125, 39.175, 39.225, 39.275, 39.325, 39.375, 39.425, 39.475, 39.525, 39.575, 39.625, 39.675, 39.725, 39.775, 39.825, 39.875, 39.925, 39.975, 40.025, 40.075, 40.125, 40.175, 40.225, 40.275, 40.325, 40.375, 40.425, 40.475, 40.525, 40.575, 40.625, 40.675, 40.725, 40.775, 40.825, 40.875, 40.925, 40.975, 41.025, 41.075, 41.125, 41.175, 41.225, 41.275, 41.325, 41.375, 41.425, 41.475, 41.525, 41.575, 41.625, 41.675, 41.725, 41.775, 41.825, 41.875, 41.925, 41.975, 42.025, 42.075, 42.125, 42.175, 42.225, 42.275, 42.325, 42.375, 42.425, 42.475, 42.525, 42.575, 42.625, 42.675, 42.725, 42.775, 42.825, 42.875, 42.925, 42.975, 43.025, 43.075, 43.125, 43.175, 43.225, 43.275, 43.325, 43.375, 43.425, 43.475, 43.525, 43.575, 43.625, 43.675, 43.725, 43.775, 43.825, 43.875, 43.925, 43.975, 44.025, 44.075, 44.125, 44.175, 44.225, 44.275, 44.325, 44.375, 44.425, 44.475, 44.525, 44.575, 44.625, 44.675, 44.725, 44.775, 44.825, 44.875, 44.925, 44.975, 45.025, 45.075, 45.125, 45.175, 45.225, 45.275, 45.325, 45.375, 45.425, 45.475, 45.525, 45.575, 45.625, 45.675, 45.725, 45.775, 45.825, 45.875, 45.925, 45.975, 46.025, 46.075, 46.125, 46.175, 46.225, 46.275, 46.325, 46.375, 46.425, 46.475, 46.525, 46.575, 46.625, 46.675, 46.725, 46.775, 46.825, 46.875, 46.925, 46.975, 47.025, 47.075, 47.125, 47.175, 47.225, 47.275, 47.325, 47.375, 47.425, 47.475, 47.525, 47.575, 47.625, 47.675, 47.725, 47.775, 47.825, 47.875, 47.925, 47.975, 48.025, 48.075, 48.125, 48.175, 48.225, 48.275, 48.325, 48.375, 48.425, 48.475, 48.525, 48.575, 48.625, 48.675, 48.725, 48.775, 48.825, 48.875, 48.925, 48.975, 49.025, 49.075, 49.125, 49.175, 49.225, 49.275, 49.325, 49.375, 49.425, 49.475, 49.525, 49.575, 49.625, 49.675, 49.725, 49.775, 49.825, 49.875, 49.925, 49.975, 50.025, 50.075, 50.125, 50.175, 50.225, 50.275, 50.325, 50.375, 50.425, 50.475, 50.525, 50.575, 50.625, 50.675, 50.725, 50.775, 50.825, 50.875, 50.925, 50.975, 51.025, 51.075, 51.125, 51.175, 51.225, 51.275, 51.325, 51.375, 51.425, 51.475, 51.525, 51.575, 51.625, 51.675, 51.725, 51.775, 51.825, 51.875, 51.925, 51.975, 52.025, 52.075, 52.125, 52.175, 52.225, 52.275, 52.325, 52.375, 52.425, 52.475, 52.525, 52.575, 52.625, 52.675, 52.725, 52.775, 52.825, 52.875, 52.925, 52.975, 53.025, 53.075, 53.125, 53.175, 53.225, 53.275, 53.325, 53.375, 53.425, 53.475, 53.525, 53.575, 53.625, 53.675, 53.725, 53.775, 53.825, 53.875, 53.925, 53.975, 54.025, 54.075, 54.125, 54.175, 54.225, 54.275, 54.325, 54.375, 54.425, 54.475, 54.525, 54.575, 54.625, 54.675, 54.725, 54.775, 54.825, 54.875, 54.925, 54.975, 55.025, 55.075, 55.125, 55.175, 55.225, 55.275, 55.325, 55.375, 55.425, 55.475, 55.525, 55.575, 55.625, 55.675, 55.725, 55.775, 55.825, 55.875, 55.925, 55.975, 56.025, 56.075, 56.125, 56.175, 56.225, 56.275, 56.325, 56.375, 56.425, 56.475, 56.525, 56.575, 56.625, 56.675, 56.725, 56.775, 56.825, 56.875, 56.925, 56.975, 57.025, 57.075, 57.125, 57.175, 57.225, 57.275, 57.325, 57.375, 57.425, 57.475, 57.525, 57.575, 57.625, 57.675, 57.725, 57.775, 57.825, 57.875, 57.925, 57.975, 58.025, 58.075, 58.125, 58.175, 58.225, 58.275, 58.325, 58.375, 58.425, 58.475, 58.525, 58.575, 58.625, 58.675, 58.725, 58.775, 58.825, 58.875, 58.925, 58.975, 59.025, 59.075, 59.125, 59.175, 59.225, 59.275, 59.325, 59.375, 59.425, 59.475, 59.525, 59.575, 59.625, 59.675, 59.725, 59.775, 59.825, 59.875, 59.925, 59.975}; + diff --git a/retired/modules/ngap_module/tests/ngap/20180101000000-OSISAF-L3C_GHRSST-pocloud.dmr.bescmd b/retired/modules/ngap_module/tests/ngap/20180101000000-OSISAF-L3C_GHRSST-pocloud.dmr.bescmd new file mode 100644 index 0000000000..0029670eee --- /dev/null +++ b/retired/modules/ngap_module/tests/ngap/20180101000000-OSISAF-L3C_GHRSST-pocloud.dmr.bescmd @@ -0,0 +1,14 @@ + + + + 300 + no + xml + 0 + + collections/C2036877806-POCLOUD/granules/20180101000000-OSISAF-L3C_GHRSST-SSTsubskin-GOES16-ssteqc_goes16_20180101_000000-v02.0-fv01.0 + + + + + diff --git a/retired/modules/ngap_module/tests/ngap/20180101000000-OSISAF-L3C_GHRSST-pocloud.dmr.bescmd.baseline b/retired/modules/ngap_module/tests/ngap/20180101000000-OSISAF-L3C_GHRSST-pocloud.dmr.bescmd.baseline new file mode 100644 index 0000000000..017e93d449 --- /dev/null +++ b/retired/modules/ngap_module/tests/ngap/20180101000000-OSISAF-L3C_GHRSST-pocloud.dmr.bescmd.baseline @@ -0,0 +1,802 @@ + + + + + + + + + reference time of sst file + + + time + + + T + + + seconds since 1981-01-01 00:00:00 + + + + + + longitude + + + longitude + + + X + + + degrees_east + + + -180. + + + 180. + + + geographical coordinates, WGS84 projection + + + + + + latitude + + + latitude + + + Y + + + degrees_north + + + -90. + + + 90. + + + geographical coordinates, WGS84 projection + + + + + + + + -128 + + + 10m wind speed + + + wind_speed + + + m s-1 + + + 10 m + + + 0. + + + 1. + + + 0 + + + 127 + + + These wind speeds were created by the ECMWF and represent winds at 10 metres above the sea surface. + + + WSP-ECMWF-Forecast + + + 0. + + + + + + + + + + + -128 + + + SSES standard deviation + + + kelvin + + + 1. + + + 0.01 + + + -127 + + + 127 + + + Standard deviation estimate derived using the techniques described at http://www.ghrsst.org/SSES-Description-of-schemes.html + + + + + + + + + + + -2147483648 + + + time difference from reference time + + + seconds + + + 0. + + + 1. + + + -2147483647 + + + 2147483647 + + + time plus sst_dtime gives seconds after 00:00:00 UTC January 1, 1981 + + + + + + + + + + + -128 + + + solar zenith angle + + + angular_degree + + + 90. + + + 1. + + + -90 + + + 90 + + + The solar zenith angle at the time of the SST observations. + + + + + + + + + + + -128 + + + sea ice fraction + + + sea_ice_area_fraction + + + + + + 0. + + + 0.01 + + + 0 + + + 100 + + + Fractional sea ice cover from OSISAF ice product + + + ICE-OSISAF + + + -36. + + + + + + + + + + + L2P flags + + + 0 + + + 15 + + + microwave land ice lake + + + 1 + 2 + 4 + 8 + + + These flags are important to properly use the data. + + + + + + + + + + + -128 + + + sources of aerosol dynamic indicator + + + 0 + + + 2 + + + no_data AOD-NAAPS-ADI SDI-OSISAF-ADI + + + 0 + 1 + 2 + + + This variable provides a pixel by pixel description of where aerosol optical depth were derived from. + + + + + + + + + + + -128 + + + aerosol dynamic indicator + + + + + + 0. + + + 0.10000000000000001 + + + 0 + + + 127 + + + + + + sources_of_adi + + + + + + + + + + + -32768 + + + sea surface subskin temperature + + + sea_surface_subskin_temperature + + + kelvin + + + 273.14999999999998 + + + 0.01 + + + -300 + + + 4500 + + + 1 millimeter + + + GOES_Imager + + + Temperature of the subskin of the ocean + + + + + + + + + + + -128 + + + quality level of SST pixel + + + 0 + + + 5 + + + no_data bad_data worst_quality low_quality acceptable_quality best_quality + + + 0 + 1 + 2 + 3 + 4 + 5 + + + These are the overall quality indicators and are used for all GHRSST SSTs + + + + + + + + + + + -128 + + + deviation from SST analysis or reference climatology + + + kelvin + + + 0. + + + 0.10000000000000001 + + + -127 + + + 127 + + + The difference between this SST and the previous day's SST analysis + + + OSTIA + + + + + + + + + + + -128 + + + satellite zenith angle + + + angular_degree + + + 0. + + + 1. + + + -90 + + + 90 + + + The satellite zenith angle at the time of the SST observations. + + + + + + + + + + + -32768 + + + original longitude of the SST value + + + longitude + + + degrees_east + + + 0. + + + 0.01 + + + -18000 + + + 18000 + + + Original longitude of the SST value + + + + + + + + + + + -128 + + + time difference of ADI data from sst measurement + + + hour + + + 0. + + + 0.10000000000000001 + + + -127 + + + 127 + + + Difference in hours between the ADI and SST data + + + + + + + + + + + -32768 + + + original latitude of the SST value + + + latitude + + + degrees_north + + + 0. + + + 0.01 + + + -9000 + + + 9000 + + + Original latitude of the SST value + + + + + + + + + + + -128 + + + SSES bias estimate + + + kelvin + + + 0. + + + 0.01 + + + -127 + + + 127 + + + Bias estimate derived using the techniques described at http://www.ghrsst.org/SSES-Description-of-schemes.html + + + + + + + CF-1.4 + + + Sea Surface Temperature + + + The L3C product derived from GOES16/ABI brightness temperatures. + + + Geostationary Sea Surface Temperature Product User Manual, http://www.osi-saf.org + + + OSISAF + + + METEO-FRANCE/CMS SAFOS processor + + + + + + All intellectual property rights of the Ocean & Sea Ice SAF products belong to EUMETSAT. The use of these products is granted to every user, free of charge. If users wish to use these products, EUMETSAT's copyright credit must be shown by displaying the words 'Copyright EUMETSAT' under each of the products shown. EUMETSAT offers no warranty and accepts no liability in respect of the Ocean & Sea Ice SAF products. EUMETSAT neither commits to nor guarantees the continuity, availability, or quality or suitability for any purpose of, the Ocean & Sea Ice SAF products. + + + GOES16-OSISAF-L3C-v1.0 + + + org.ghrsst + + + 1.0 + + + 2.0 + + + 0.05 degree + + + 60. + + + -60. + + + -15. + + + -135. + + + GOES_ABI + + + GOES16 + + + GOES_ABI + + + Unidata Dataset Discovery v1.0 + + + N/A + + + Oceans > Ocean Temperature > Sea Surface Temperature + + + NASA Global Change Master Directory (GCMD) Science Keywords + + + NetCDF Climate and Forecast (CF) Metadata Convention + + + degrees_north + + + 0.050000000000000003 + + + degrees_east + + + 0.050000000000000003 + + + In case SAF data (pre-operational or operational) has been used for the study described in a paper the following sentence would be an appropriate reference to the funding coming from EUMETSAT: The data from the EUMETSAT Satellite Application Facility on Ocean & Sea Ice used in this study are accessible through the SAF's homepage http://www.osi-saf.org + + + O&SI SAF + + + osi-saf.helpdesk@meteo.fr + + + http://www.osi-saf.org + + + Group for High Resolution Sea Surface Temperature + + + The GHRSST Project Office + + + http://www.ghrsst.org + + + ghrsst-po@nceo.ac.uk + + + L3C + + + grid + + + 20180101T020918Z + + + 2 + + + 20171231T233000Z + + + 20171231T233000Z + + + 20180101T003000Z + + + 20180101T003000Z + + + D9299038-EE98-11E7-B2C3-0024E836CC1A + + + 4.3.2 + + + + 3.20.13-664 + + + 3.20.13-664 + + + libdap-3.20.11-198 + + + +# TheBESKeys::get_as_config() +AllowedHosts=^https?:\/\/ +BES.Catalog.catalog.FollowSymLinks=Yes +BES.Catalog.catalog.RootDirectory=/tmp/tmpxqbuljki/ +BES.Catalog.catalog.TypeMatch=dmrpp:.*\.(dmrpp)$; +BES.Catalog.catalog.TypeMatch+=h5:.*(\.bz2|\.gz|\.Z)?$; +BES.Data.RootDirectory=/dev/null +BES.LogName=./bes.log +BES.UncompressCache.dir=/tmp/hyrax_ux +BES.UncompressCache.prefix=ux_ +BES.UncompressCache.size=500 +BES.module.cmd=/usr/lib64/bes/libdap_xml_module.so +BES.module.dap=/usr/lib64/bes/libdap_module.so +BES.module.dmrpp=/usr/lib64/bes/libdmrpp_module.so +BES.module.fonc=/usr/lib64/bes/libfonc_module.so +BES.module.h5=/usr/lib64/bes/libhdf5_module.so +BES.module.nc=/usr/lib64/bes/libnc_module.so +BES.modules=dap,cmd,h5,dmrpp,nc,fonc +FONc.ClassicModel=false +FONc.NoGlobalAttrs=true +H5.EnableCF=false +H5.EnableCheckNameClashing=true + + + + build_dmrpp -c /tmp/bes_conf_lvQa -f /tmp/tmpxqbuljki//20180101000000-OSISAF-L3C_GHRSST-SSTsubskin-GOES16-ssteqc_goes16_20180101_000000-v02.0-fv01.0.nc -r /tmp/dmr__mtGDjT -u OPeNDAP_DMRpp_DATA_ACCESS_URL -M + + + diff --git a/retired/modules/ngap_module/tests/ngap/20240809210000-OSISAF-L3C_GHRSST-pocloud-only.dap.bescmd b/retired/modules/ngap_module/tests/ngap/20240809210000-OSISAF-L3C_GHRSST-pocloud-only.dap.bescmd new file mode 100644 index 0000000000..dd7ad07fc2 --- /dev/null +++ b/retired/modules/ngap_module/tests/ngap/20240809210000-OSISAF-L3C_GHRSST-pocloud-only.dap.bescmd @@ -0,0 +1,20 @@ + + + + 300 + no + xml + 0 + + + collections/C2036877806-POCLOUD/granules/20240809210000-OSISAF-L3C_GHRSST-SSTsubskin-GOES16-ssteqc_goes16_20240809_210000-v02.0-fv01.0 + + + + /lat;/lon + + + + + diff --git a/retired/modules/ngap_module/tests/ngap/20240809210000-OSISAF-L3C_GHRSST-pocloud-only.dap.bescmd.baseline b/retired/modules/ngap_module/tests/ngap/20240809210000-OSISAF-L3C_GHRSST-pocloud-only.dap.bescmd.baseline new file mode 100644 index 0000000000..52e7a8647c --- /dev/null +++ b/retired/modules/ngap_module/tests/ngap/20240809210000-OSISAF-L3C_GHRSST-pocloud-only.dap.bescmd.baseline @@ -0,0 +1,248 @@ + + + + + + + + longitude + + + longitude + + + X + + + degrees_east + + + -180. + + + 180. + + + geographical coordinates, WGS84 projection + + + removed checksum + + + + + + latitude + + + latitude + + + Y + + + degrees_north + + + -90. + + + 90. + + + geographical coordinates, WGS84 projection + + + removed checksum + + + + CF-1.4 + + + Sea Surface Temperature + + + The L3C product derived from GOES16/ABI brightness temperatures. + + + Geostationary Sea Surface Temperature Product User Manual, http://www.osi-saf.org + + + OSISAF + + + + + + All intellectual property rights of the Ocean & Sea Ice SAF products belong to EUMETSAT. The use of these products is granted to every user, free of charge. If users wish to use these products, EUMETSAT's copyright credit must be shown by displaying the words 'Copyright EUMETSAT' under each of the products shown. EUMETSAT offers no warranty and accepts no liability in respect of the Ocean & Sea Ice SAF products. EUMETSAT neither commits to nor guarantees the continuity, availability, or quality or suitability for any purpose of, the Ocean & Sea Ice SAF products. + + + GOES16-OSISAF-L3C-v1.0 + + + OSI-207-b + + + org.ghrsst + + + 1.0 + + + 2.0 + + + 3 + + + 0.05 degree + + + 60. + + + -60. + + + -15. + + + -135. + + + GOES_ABI + + + GOES16 + + + GOES_ABI + + + Unidata Dataset Discovery v1.0 + + + N/A + + + Oceans > Ocean Temperature > Sea Surface Temperature + + + NASA Global Change Master Directory (GCMD) Science Keywords + + + NetCDF Climate and Forecast (CF) Metadata Convention + + + degrees_north + + + 0.050000000000000003 + + + degrees_east + + + 0.050000000000000003 + + + In case SAF data (pre-operational or operational) has been used for the study described in a paper the following sentence would be an appropriate reference to the funding coming from EUMETSAT: The data from the EUMETSAT Satellite Application Facility on Ocean & Sea Ice used in this study are accessible through the SAF's homepage http://www.osi-saf.org + + + O&SI SAF + + + osi-saf.helpdesk@meteo.fr + + + http://www.osi-saf.org + + + Group for High Resolution Sea Surface Temperature + + + The GHRSST Project Office + + + http://www.ghrsst.org + + + ghrsst-po@nceo.ac.uk + + + L3C + + + grid + + + METEO-FRANCE GEOSAFO vremoved-version + + + F63CAD66-5699-11EF-91F2-9440C930FC03 + + + 20240809T215433Z + + + 20240809T204042Z + + + 20240809T204042Z + + + 20240809T211929Z + + + 20240809T211929Z + + + removed-version + + + + removed-version + + + removed-version + + + libdap-removed-version + + + +# TheBESKeys::get_as_config() +AllowedHosts=^https?:\/\/ +BES.Catalog.catalog.FollowSymLinks=Yes +BES.Catalog.catalog.RootDirectory=/tmp/tmphcrbshue/ +BES.Catalog.catalog.TypeMatch=dmrpp:.*\.(dmrpp)$; +BES.Catalog.catalog.TypeMatch+=h5:.*(\.bz2|\.gz|\.Z)?$; +BES.Data.RootDirectory=/dev/null +BES.LogName=./bes.log +BES.UncompressCache.dir=/tmp/hyrax_ux +BES.UncompressCache.prefix=ux_ +BES.UncompressCache.size=500 +BES.module.cmd=/usr/lib64/bes/libdap_xml_module.so +BES.module.dap=/usr/lib64/bes/libdap_module.so +BES.module.dmrpp=/usr/lib64/bes/libdmrpp_module.so +BES.module.fonc=/usr/lib64/bes/libfonc_module.so +BES.module.h5=/usr/lib64/bes/libhdf5_module.so +BES.module.nc=/usr/lib64/bes/libnc_module.so +BES.modules=dap,cmd,h5,dmrpp,nc,fonc +FONc.ClassicModel=false +FONc.NoGlobalAttrs=true +H5.EnableCF=false +H5.EnableCheckNameClashing=true + + + + build_dmrpp -c /tmp/bes_conf_kY1v -f /tmp/tmphcrbshue//20240809210000-OSISAF-L3C_GHRSST-SSTsubskin-GOES16-ssteqc_goes16_20240809_210000-v02.0-fv01.0.nc -r /tmp/dmr__ctTpdz -u OPeNDAP_DMRpp_DATA_ACCESS_URL -M + + + + +The data: +Float32 lon[lon = 2400] = {-134.975, -134.925, -134.875, -134.825, -134.775, -134.725, -134.675, -134.625, -134.575, -134.525, -134.475, -134.425, -134.375, -134.325, -134.275, -134.225, -134.175, -134.125, -134.075, -134.025, -133.975, -133.925, -133.875, -133.825, -133.775, -133.725, -133.675, -133.625, -133.575, -133.525, -133.475, -133.425, -133.375, -133.325, -133.275, -133.225, -133.175, -133.125, -133.075, -133.025, -132.975, -132.925, -132.875, -132.825, -132.775, -132.725, -132.675, -132.625, -132.575, -132.525, -132.475, -132.425, -132.375, -132.325, -132.275, -132.225, -132.175, -132.125, -132.075, -132.025, -131.975, -131.925, -131.875, -131.825, -131.775, -131.725, -131.675, -131.625, -131.575, -131.525, -131.475, -131.425, -131.375, -131.325, -131.275, -131.225, -131.175, -131.125, -131.075, -131.025, -130.975, -130.925, -130.875, -130.825, -130.775, -130.725, -130.675, -130.625, -130.575, -130.525, -130.475, -130.425, -130.375, -130.325, -130.275, -130.225, -130.175, -130.125, -130.075, -130.025, -129.975, -129.925, -129.875, -129.825, -129.775, -129.725, -129.675, -129.625, -129.575, -129.525, -129.475, -129.425, -129.375, -129.325, -129.275, -129.225, -129.175, -129.125, -129.075, -129.025, -128.975, -128.925, -128.875, -128.825, -128.775, -128.725, -128.675, -128.625, -128.575, -128.525, -128.475, -128.425, -128.375, -128.325, -128.275, -128.225, -128.175, -128.125, -128.075, -128.025, -127.975, -127.925, -127.875, -127.825, -127.775, -127.725, -127.675, -127.625, -127.575, -127.525, -127.475, -127.425, -127.375, -127.325, -127.275, -127.225, -127.175, -127.125, -127.075, -127.025, -126.975, -126.925, -126.875, -126.825, -126.775, -126.725, -126.675, -126.625, -126.575, -126.525, -126.475, -126.425, -126.375, -126.325, -126.275, -126.225, -126.175, -126.125, -126.075, -126.025, -125.975, -125.925, -125.875, -125.825, -125.775, -125.725, -125.675, -125.625, -125.575, -125.525, -125.475, -125.425, -125.375, -125.325, -125.275, -125.225, -125.175, -125.125, -125.075, -125.025, -124.975, -124.925, -124.875, -124.825, -124.775, -124.725, -124.675, -124.625, -124.575, -124.525, -124.475, -124.425, -124.375, -124.325, -124.275, -124.225, -124.175, -124.125, -124.075, -124.025, -123.975, -123.925, -123.875, -123.825, -123.775, -123.725, -123.675, -123.625, -123.575, -123.525, -123.475, -123.425, -123.375, -123.325, -123.275, -123.225, -123.175, -123.125, -123.075, -123.025, -122.975, -122.925, -122.875, -122.825, -122.775, -122.725, -122.675, -122.625, -122.575, -122.525, -122.475, -122.425, -122.375, -122.325, -122.275, -122.225, -122.175, -122.125, -122.075, -122.025, -121.975, -121.925, -121.875, -121.825, -121.775, -121.725, -121.675, -121.625, -121.575, -121.525, -121.475, -121.425, -121.375, -121.325, -121.275, -121.225, -121.175, -121.125, -121.075, -121.025, -120.975, -120.925, -120.875, -120.825, -120.775, -120.725, -120.675, -120.625, -120.575, -120.525, -120.475, -120.425, -120.375, -120.325, -120.275, -120.225, -120.175, -120.125, -120.075, -120.025, -119.975, -119.925, -119.875, -119.825, -119.775, -119.725, -119.675, -119.625, -119.575, -119.525, -119.475, -119.425, -119.375, -119.325, -119.275, -119.225, -119.175, -119.125, -119.075, -119.025, -118.975, -118.925, -118.875, -118.825, -118.775, -118.725, -118.675, -118.625, -118.575, -118.525, -118.475, -118.425, -118.375, -118.325, -118.275, -118.225, -118.175, -118.125, -118.075, -118.025, -117.975, -117.925, -117.875, -117.825, -117.775, -117.725, -117.675, -117.625, -117.575, -117.525, -117.475, -117.425, -117.375, -117.325, -117.275, -117.225, -117.175, -117.125, -117.075, -117.025, -116.975, -116.925, -116.875, -116.825, -116.775, -116.725, -116.675, -116.625, -116.575, -116.525, -116.475, -116.425, -116.375, -116.325, -116.275, -116.225, -116.175, -116.125, -116.075, -116.025, -115.975, -115.925, -115.875, -115.825, -115.775, -115.725, -115.675, -115.625, -115.575, -115.525, -115.475, -115.425, -115.375, -115.325, -115.275, -115.225, -115.175, -115.125, -115.075, -115.025, -114.975, -114.925, -114.875, -114.825, -114.775, -114.725, -114.675, -114.625, -114.575, -114.525, -114.475, -114.425, -114.375, -114.325, -114.275, -114.225, -114.175, -114.125, -114.075, -114.025, -113.975, -113.925, -113.875, -113.825, -113.775, -113.725, -113.675, -113.625, -113.575, -113.525, -113.475, -113.425, -113.375, -113.325, -113.275, -113.225, -113.175, -113.125, -113.075, -113.025, -112.975, -112.925, -112.875, -112.825, -112.775, -112.725, -112.675, -112.625, -112.575, -112.525, -112.475, -112.425, -112.375, -112.325, -112.275, -112.225, -112.175, -112.125, -112.075, -112.025, -111.975, -111.925, -111.875, -111.825, -111.775, -111.725, -111.675, -111.625, -111.575, -111.525, -111.475, -111.425, -111.375, -111.325, -111.275, -111.225, -111.175, -111.125, -111.075, -111.025, -110.975, -110.925, -110.875, -110.825, -110.775, -110.725, -110.675, -110.625, -110.575, -110.525, -110.475, -110.425, -110.375, -110.325, -110.275, -110.225, -110.175, -110.125, -110.075, -110.025, -109.975, -109.925, -109.875, -109.825, -109.775, -109.725, -109.675, -109.625, -109.575, -109.525, -109.475, -109.425, -109.375, -109.325, -109.275, -109.225, -109.175, -109.125, -109.075, -109.025, -108.975, -108.925, -108.875, -108.825, -108.775, -108.725, -108.675, -108.625, -108.575, -108.525, -108.475, -108.425, -108.375, -108.325, -108.275, -108.225, -108.175, -108.125, -108.075, -108.025, -107.975, -107.925, -107.875, -107.825, -107.775, -107.725, -107.675, -107.625, -107.575, -107.525, -107.475, -107.425, -107.375, -107.325, -107.275, -107.225, -107.175, -107.125, -107.075, -107.025, -106.975, -106.925, -106.875, -106.825, -106.775, -106.725, -106.675, -106.625, -106.575, -106.525, -106.475, -106.425, -106.375, -106.325, -106.275, -106.225, -106.175, -106.125, -106.075, -106.025, -105.975, -105.925, -105.875, -105.825, -105.775, -105.725, -105.675, -105.625, -105.575, -105.525, -105.475, -105.425, -105.375, -105.325, -105.275, -105.225, -105.175, -105.125, -105.075, -105.025, -104.975, -104.925, -104.875, -104.825, -104.775, -104.725, -104.675, -104.625, -104.575, -104.525, -104.475, -104.425, -104.375, -104.325, -104.275, -104.225, -104.175, -104.125, -104.075, -104.025, -103.975, -103.925, -103.875, -103.825, -103.775, -103.725, -103.675, -103.625, -103.575, -103.525, -103.475, -103.425, -103.375, -103.325, -103.275, -103.225, -103.175, -103.125, -103.075, -103.025, -102.975, -102.925, -102.875, -102.825, -102.775, -102.725, -102.675, -102.625, -102.575, -102.525, -102.475, -102.425, -102.375, -102.325, -102.275, -102.225, -102.175, -102.125, -102.075, -102.025, -101.975, -101.925, -101.875, -101.825, -101.775, -101.725, -101.675, -101.625, -101.575, -101.525, -101.475, -101.425, -101.375, -101.325, -101.275, -101.225, -101.175, -101.125, -101.075, -101.025, -100.975, -100.925, -100.875, -100.825, -100.775, -100.725, -100.675, -100.625, -100.575, -100.525, -100.475, -100.425, -100.375, -100.325, -100.275, -100.225, -100.175, -100.125, -100.075, -100.025, -99.975, -99.925, -99.875, -99.825, -99.775, -99.725, -99.675, -99.625, -99.575, -99.525, -99.475, -99.425, -99.375, -99.325, -99.275, -99.225, -99.175, -99.125, -99.075, -99.025, -98.975, -98.925, -98.875, -98.825, -98.775, -98.725, -98.675, -98.625, -98.575, -98.525, -98.475, -98.425, -98.375, -98.325, -98.275, -98.225, -98.175, -98.125, -98.075, -98.025, -97.975, -97.925, -97.875, -97.825, -97.775, -97.725, -97.675, -97.625, -97.575, -97.525, -97.475, -97.425, -97.375, -97.325, -97.275, -97.225, -97.175, -97.125, -97.075, -97.025, -96.975, -96.925, -96.875, -96.825, -96.775, -96.725, -96.675, -96.625, -96.575, -96.525, -96.475, -96.425, -96.375, -96.325, -96.275, -96.225, -96.175, -96.125, -96.075, -96.025, -95.975, -95.925, -95.875, -95.825, -95.775, -95.725, -95.675, -95.625, -95.575, -95.525, -95.475, -95.425, -95.375, -95.325, -95.275, -95.225, -95.175, -95.125, -95.075, -95.025, -94.975, -94.925, -94.875, -94.825, -94.775, -94.725, -94.675, -94.625, -94.575, -94.525, -94.475, -94.425, -94.375, -94.325, -94.275, -94.225, -94.175, -94.125, -94.075, -94.025, -93.975, -93.925, -93.875, -93.825, -93.775, -93.725, -93.675, -93.625, -93.575, -93.525, -93.475, -93.425, -93.375, -93.325, -93.275, -93.225, -93.175, -93.125, -93.075, -93.025, -92.975, -92.925, -92.875, -92.825, -92.775, -92.725, -92.675, -92.625, -92.575, -92.525, -92.475, -92.425, -92.375, -92.325, -92.275, -92.225, -92.175, -92.125, -92.075, -92.025, -91.975, -91.925, -91.875, -91.825, -91.775, -91.725, -91.675, -91.625, -91.575, -91.525, -91.475, -91.425, -91.375, -91.325, -91.275, -91.225, -91.175, -91.125, -91.075, -91.025, -90.975, -90.925, -90.875, -90.825, -90.775, -90.725, -90.675, -90.625, -90.575, -90.525, -90.475, -90.425, -90.375, -90.325, -90.275, -90.225, -90.175, -90.125, -90.075, -90.025, -89.975, -89.925, -89.875, -89.825, -89.775, -89.725, -89.675, -89.625, -89.575, -89.525, -89.475, -89.425, -89.375, -89.325, -89.275, -89.225, -89.175, -89.125, -89.075, -89.025, -88.975, -88.925, -88.875, -88.825, -88.775, -88.725, -88.675, -88.625, -88.575, -88.525, -88.475, -88.425, -88.375, -88.325, -88.275, -88.225, -88.175, -88.125, -88.075, -88.025, -87.975, -87.925, -87.875, -87.825, -87.775, -87.725, -87.675, -87.625, -87.575, -87.525, -87.475, -87.425, -87.375, -87.325, -87.275, -87.225, -87.175, -87.125, -87.075, -87.025, -86.975, -86.925, -86.875, -86.825, -86.775, -86.725, -86.675, -86.625, -86.575, -86.525, -86.475, -86.425, -86.375, -86.325, -86.275, -86.225, -86.175, -86.125, -86.075, -86.025, -85.975, -85.925, -85.875, -85.825, -85.775, -85.725, -85.675, -85.625, -85.575, -85.525, -85.475, -85.425, -85.375, -85.325, -85.275, -85.225, -85.175, -85.125, -85.075, -85.025, -84.975, -84.925, -84.875, -84.825, -84.775, -84.725, -84.675, -84.625, -84.575, -84.525, -84.475, -84.425, -84.375, -84.325, -84.275, -84.225, -84.175, -84.125, -84.075, -84.025, -83.975, -83.925, -83.875, -83.825, -83.775, -83.725, -83.675, -83.625, -83.575, -83.525, -83.475, -83.425, -83.375, -83.325, -83.275, -83.225, -83.175, -83.125, -83.075, -83.025, -82.975, -82.925, -82.875, -82.825, -82.775, -82.725, -82.675, -82.625, -82.575, -82.525, -82.475, -82.425, -82.375, -82.325, -82.275, -82.225, -82.175, -82.125, -82.075, -82.025, -81.975, -81.925, -81.875, -81.825, -81.775, -81.725, -81.675, -81.625, -81.575, -81.525, -81.475, -81.425, -81.375, -81.325, -81.275, -81.225, -81.175, -81.125, -81.075, -81.025, -80.975, -80.925, -80.875, -80.825, -80.775, -80.725, -80.675, -80.625, -80.575, -80.525, -80.475, -80.425, -80.375, -80.325, -80.275, -80.225, -80.175, -80.125, -80.075, -80.025, -79.975, -79.925, -79.875, -79.825, -79.775, -79.725, -79.675, -79.625, -79.575, -79.525, -79.475, -79.425, -79.375, -79.325, -79.275, -79.225, -79.175, -79.125, -79.075, -79.025, -78.975, -78.925, -78.875, -78.825, -78.775, -78.725, -78.675, -78.625, -78.575, -78.525, -78.475, -78.425, -78.375, -78.325, -78.275, -78.225, -78.175, -78.125, -78.075, -78.025, -77.975, -77.925, -77.875, -77.825, -77.775, -77.725, -77.675, -77.625, -77.575, -77.525, -77.475, -77.425, -77.375, -77.325, -77.275, -77.225, -77.175, -77.125, -77.075, -77.025, -76.975, -76.925, -76.875, -76.825, -76.775, -76.725, -76.675, -76.625, -76.575, -76.525, -76.475, -76.425, -76.375, -76.325, -76.275, -76.225, -76.175, -76.125, -76.075, -76.025, -75.975, -75.925, -75.875, -75.825, -75.775, -75.725, -75.675, -75.625, -75.575, -75.525, -75.475, -75.425, -75.375, -75.325, -75.275, -75.225, -75.175, -75.125, -75.075, -75.025, -74.975, -74.925, -74.875, -74.825, -74.775, -74.725, -74.675, -74.625, -74.575, -74.525, -74.475, -74.425, -74.375, -74.325, -74.275, -74.225, -74.175, -74.125, -74.075, -74.025, -73.975, -73.925, -73.875, -73.825, -73.775, -73.725, -73.675, -73.625, -73.575, -73.525, -73.475, -73.425, -73.375, -73.325, -73.275, -73.225, -73.175, -73.125, -73.075, -73.025, -72.975, -72.925, -72.875, -72.825, -72.775, -72.725, -72.675, -72.625, -72.575, -72.525, -72.475, -72.425, -72.375, -72.325, -72.275, -72.225, -72.175, -72.125, -72.075, -72.025, -71.975, -71.925, -71.875, -71.825, -71.775, -71.725, -71.675, -71.625, -71.575, -71.525, -71.475, -71.425, -71.375, -71.325, -71.275, -71.225, -71.175, -71.125, -71.075, -71.025, -70.975, -70.925, -70.875, -70.825, -70.775, -70.725, -70.675, -70.625, -70.575, -70.525, -70.475, -70.425, -70.375, -70.325, -70.275, -70.225, -70.175, -70.125, -70.075, -70.025, -69.975, -69.925, -69.875, -69.825, -69.775, -69.725, -69.675, -69.625, -69.575, -69.525, -69.475, -69.425, -69.375, -69.325, -69.275, -69.225, -69.175, -69.125, -69.075, -69.025, -68.975, -68.925, -68.875, -68.825, -68.775, -68.725, -68.675, -68.625, -68.575, -68.525, -68.475, -68.425, -68.375, -68.325, -68.275, -68.225, -68.175, -68.125, -68.075, -68.025, -67.975, -67.925, -67.875, -67.825, -67.775, -67.725, -67.675, -67.625, -67.575, -67.525, -67.475, -67.425, -67.375, -67.325, -67.275, -67.225, -67.175, -67.125, -67.075, -67.025, -66.975, -66.925, -66.875, -66.825, -66.775, -66.725, -66.675, -66.625, -66.575, -66.525, -66.475, -66.425, -66.375, -66.325, -66.275, -66.225, -66.175, -66.125, -66.075, -66.025, -65.975, -65.925, -65.875, -65.825, -65.775, -65.725, -65.675, -65.625, -65.575, -65.525, -65.475, -65.425, -65.375, -65.325, -65.275, -65.225, -65.175, -65.125, -65.075, -65.025, -64.975, -64.925, -64.875, -64.825, -64.775, -64.725, -64.675, -64.625, -64.575, -64.525, -64.475, -64.425, -64.375, -64.325, -64.275, -64.225, -64.175, -64.125, -64.075, -64.025, -63.975, -63.925, -63.875, -63.825, -63.775, -63.725, -63.675, -63.625, -63.575, -63.525, -63.475, -63.425, -63.375, -63.325, -63.275, -63.225, -63.175, -63.125, -63.075, -63.025, -62.975, -62.925, -62.875, -62.825, -62.775, -62.725, -62.675, -62.625, -62.575, -62.525, -62.475, -62.425, -62.375, -62.325, -62.275, -62.225, -62.175, -62.125, -62.075, -62.025, -61.975, -61.925, -61.875, -61.825, -61.775, -61.725, -61.675, -61.625, -61.575, -61.525, -61.475, -61.425, -61.375, -61.325, -61.275, -61.225, -61.175, -61.125, -61.075, -61.025, -60.975, -60.925, -60.875, -60.825, -60.775, -60.725, -60.675, -60.625, -60.575, -60.525, -60.475, -60.425, -60.375, -60.325, -60.275, -60.225, -60.175, -60.125, -60.075, -60.025, -59.975, -59.925, -59.875, -59.825, -59.775, -59.725, -59.675, -59.625, -59.575, -59.525, -59.475, -59.425, -59.375, -59.325, -59.275, -59.225, -59.175, -59.125, -59.075, -59.025, -58.975, -58.925, -58.875, -58.825, -58.775, -58.725, -58.675, -58.625, -58.575, -58.525, -58.475, -58.425, -58.375, -58.325, -58.275, -58.225, -58.175, -58.125, -58.075, -58.025, -57.975, -57.925, -57.875, -57.825, -57.775, -57.725, -57.675, -57.625, -57.575, -57.525, -57.475, -57.425, -57.375, -57.325, -57.275, -57.225, -57.175, -57.125, -57.075, -57.025, -56.975, -56.925, -56.875, -56.825, -56.775, -56.725, -56.675, -56.625, -56.575, -56.525, -56.475, -56.425, -56.375, -56.325, -56.275, -56.225, -56.175, -56.125, -56.075, -56.025, -55.975, -55.925, -55.875, -55.825, -55.775, -55.725, -55.675, -55.625, -55.575, -55.525, -55.475, -55.425, -55.375, -55.325, -55.275, -55.225, -55.175, -55.125, -55.075, -55.025, -54.975, -54.925, -54.875, -54.825, -54.775, -54.725, -54.675, -54.625, -54.575, -54.525, -54.475, -54.425, -54.375, -54.325, -54.275, -54.225, -54.175, -54.125, -54.075, -54.025, -53.975, -53.925, -53.875, -53.825, -53.775, -53.725, -53.675, -53.625, -53.575, -53.525, -53.475, -53.425, -53.375, -53.325, -53.275, -53.225, -53.175, -53.125, -53.075, -53.025, -52.975, -52.925, -52.875, -52.825, -52.775, -52.725, -52.675, -52.625, -52.575, -52.525, -52.475, -52.425, -52.375, -52.325, -52.275, -52.225, -52.175, -52.125, -52.075, -52.025, -51.975, -51.925, -51.875, -51.825, -51.775, -51.725, -51.675, -51.625, -51.575, -51.525, -51.475, -51.425, -51.375, -51.325, -51.275, -51.225, -51.175, -51.125, -51.075, -51.025, -50.975, -50.925, -50.875, -50.825, -50.775, -50.725, -50.675, -50.625, -50.575, -50.525, -50.475, -50.425, -50.375, -50.325, -50.275, -50.225, -50.175, -50.125, -50.075, -50.025, -49.975, -49.925, -49.875, -49.825, -49.775, -49.725, -49.675, -49.625, -49.575, -49.525, -49.475, -49.425, -49.375, -49.325, -49.275, -49.225, -49.175, -49.125, -49.075, -49.025, -48.975, -48.925, -48.875, -48.825, -48.775, -48.725, -48.675, -48.625, -48.575, -48.525, -48.475, -48.425, -48.375, -48.325, -48.275, -48.225, -48.175, -48.125, -48.075, -48.025, -47.975, -47.925, -47.875, -47.825, -47.775, -47.725, -47.675, -47.625, -47.575, -47.525, -47.475, -47.425, -47.375, -47.325, -47.275, -47.225, -47.175, -47.125, -47.075, -47.025, -46.975, -46.925, -46.875, -46.825, -46.775, -46.725, -46.675, -46.625, -46.575, -46.525, -46.475, -46.425, -46.375, -46.325, -46.275, -46.225, -46.175, -46.125, -46.075, -46.025, -45.975, -45.925, -45.875, -45.825, -45.775, -45.725, -45.675, -45.625, -45.575, -45.525, -45.475, -45.425, -45.375, -45.325, -45.275, -45.225, -45.175, -45.125, -45.075, -45.025, -44.975, -44.925, -44.875, -44.825, -44.775, -44.725, -44.675, -44.625, -44.575, -44.525, -44.475, -44.425, -44.375, -44.325, -44.275, -44.225, -44.175, -44.125, -44.075, -44.025, -43.975, -43.925, -43.875, -43.825, -43.775, -43.725, -43.675, -43.625, -43.575, -43.525, -43.475, -43.425, -43.375, -43.325, -43.275, -43.225, -43.175, -43.125, -43.075, -43.025, -42.975, -42.925, -42.875, -42.825, -42.775, -42.725, -42.675, -42.625, -42.575, -42.525, -42.475, -42.425, -42.375, -42.325, -42.275, -42.225, -42.175, -42.125, -42.075, -42.025, -41.975, -41.925, -41.875, -41.825, -41.775, -41.725, -41.675, -41.625, -41.575, -41.525, -41.475, -41.425, -41.375, -41.325, -41.275, -41.225, -41.175, -41.125, -41.075, -41.025, -40.975, -40.925, -40.875, -40.825, -40.775, -40.725, -40.675, -40.625, -40.575, -40.525, -40.475, -40.425, -40.375, -40.325, -40.275, -40.225, -40.175, -40.125, -40.075, -40.025, -39.975, -39.925, -39.875, -39.825, -39.775, -39.725, -39.675, -39.625, -39.575, -39.525, -39.475, -39.425, -39.375, -39.325, -39.275, -39.225, -39.175, -39.125, -39.075, -39.025, -38.975, -38.925, -38.875, -38.825, -38.775, -38.725, -38.675, -38.625, -38.575, -38.525, -38.475, -38.425, -38.375, -38.325, -38.275, -38.225, -38.175, -38.125, -38.075, -38.025, -37.975, -37.925, -37.875, -37.825, -37.775, -37.725, -37.675, -37.625, -37.575, -37.525, -37.475, -37.425, -37.375, -37.325, -37.275, -37.225, -37.175, -37.125, -37.075, -37.025, -36.975, -36.925, -36.875, -36.825, -36.775, -36.725, -36.675, -36.625, -36.575, -36.525, -36.475, -36.425, -36.375, -36.325, -36.275, -36.225, -36.175, -36.125, -36.075, -36.025, -35.975, -35.925, -35.875, -35.825, -35.775, -35.725, -35.675, -35.625, -35.575, -35.525, -35.475, -35.425, -35.375, -35.325, -35.275, -35.225, -35.175, -35.125, -35.075, -35.025, -34.975, -34.925, -34.875, -34.825, -34.775, -34.725, -34.675, -34.625, -34.575, -34.525, -34.475, -34.425, -34.375, -34.325, -34.275, -34.225, -34.175, -34.125, -34.075, -34.025, -33.975, -33.925, -33.875, -33.825, -33.775, -33.725, -33.675, -33.625, -33.575, -33.525, -33.475, -33.425, -33.375, -33.325, -33.275, -33.225, -33.175, -33.125, -33.075, -33.025, -32.975, -32.925, -32.875, -32.825, -32.775, -32.725, -32.675, -32.625, -32.575, -32.525, -32.475, -32.425, -32.375, -32.325, -32.275, -32.225, -32.175, -32.125, -32.075, -32.025, -31.975, -31.925, -31.875, -31.825, -31.775, -31.725, -31.675, -31.625, -31.575, -31.525, -31.475, -31.425, -31.375, -31.325, -31.275, -31.225, -31.175, -31.125, -31.075, -31.025, -30.975, -30.925, -30.875, -30.825, -30.775, -30.725, -30.675, -30.625, -30.575, -30.525, -30.475, -30.425, -30.375, -30.325, -30.275, -30.225, -30.175, -30.125, -30.075, -30.025, -29.975, -29.925, -29.875, -29.825, -29.775, -29.725, -29.675, -29.625, -29.575, -29.525, -29.475, -29.425, -29.375, -29.325, -29.275, -29.225, -29.175, -29.125, -29.075, -29.025, -28.975, -28.925, -28.875, -28.825, -28.775, -28.725, -28.675, -28.625, -28.575, -28.525, -28.475, -28.425, -28.375, -28.325, -28.275, -28.225, -28.175, -28.125, -28.075, -28.025, -27.975, -27.925, -27.875, -27.825, -27.775, -27.725, -27.675, -27.625, -27.575, -27.525, -27.475, -27.425, -27.375, -27.325, -27.275, -27.225, -27.175, -27.125, -27.075, -27.025, -26.975, -26.925, -26.875, -26.825, -26.775, -26.725, -26.675, -26.625, -26.575, -26.525, -26.475, -26.425, -26.375, -26.325, -26.275, -26.225, -26.175, -26.125, -26.075, -26.025, -25.975, -25.925, -25.875, -25.825, -25.775, -25.725, -25.675, -25.625, -25.575, -25.525, -25.475, -25.425, -25.375, -25.325, -25.275, -25.225, -25.175, -25.125, -25.075, -25.025, -24.975, -24.925, -24.875, -24.825, -24.775, -24.725, -24.675, -24.625, -24.575, -24.525, -24.475, -24.425, -24.375, -24.325, -24.275, -24.225, -24.175, -24.125, -24.075, -24.025, -23.975, -23.925, -23.875, -23.825, -23.775, -23.725, -23.675, -23.625, -23.575, -23.525, -23.475, -23.425, -23.375, -23.325, -23.275, -23.225, -23.175, -23.125, -23.075, -23.025, -22.975, -22.925, -22.875, -22.825, -22.775, -22.725, -22.675, -22.625, -22.575, -22.525, -22.475, -22.425, -22.375, -22.325, -22.275, -22.225, -22.175, -22.125, -22.075, -22.025, -21.975, -21.925, -21.875, -21.825, -21.775, -21.725, -21.675, -21.625, -21.575, -21.525, -21.475, -21.425, -21.375, -21.325, -21.275, -21.225, -21.175, -21.125, -21.075, -21.025, -20.975, -20.925, -20.875, -20.825, -20.775, -20.725, -20.675, -20.625, -20.575, -20.525, -20.475, -20.425, -20.375, -20.325, -20.275, -20.225, -20.175, -20.125, -20.075, -20.025, -19.975, -19.925, -19.875, -19.825, -19.775, -19.725, -19.675, -19.625, -19.575, -19.525, -19.475, -19.425, -19.375, -19.325, -19.275, -19.225, -19.175, -19.125, -19.075, -19.025, -18.975, -18.925, -18.875, -18.825, -18.775, -18.725, -18.675, -18.625, -18.575, -18.525, -18.475, -18.425, -18.375, -18.325, -18.275, -18.225, -18.175, -18.125, -18.075, -18.025, -17.975, -17.925, -17.875, -17.825, -17.775, -17.725, -17.675, -17.625, -17.575, -17.525, -17.475, -17.425, -17.375, -17.325, -17.275, -17.225, -17.175, -17.125, -17.075, -17.025, -16.975, -16.925, -16.875, -16.825, -16.775, -16.725, -16.675, -16.625, -16.575, -16.525, -16.475, -16.425, -16.375, -16.325, -16.275, -16.225, -16.175, -16.125, -16.075, -16.025, -15.975, -15.925, -15.875, -15.825, -15.775, -15.725, -15.675, -15.625, -15.575, -15.525, -15.475, -15.425, -15.375, -15.325, -15.275, -15.225, -15.175, -15.125, -15.075, -15.025}; +Float32 lat[lat = 2400] = {-59.975, -59.925, -59.875, -59.825, -59.775, -59.725, -59.675, -59.625, -59.575, -59.525, -59.475, -59.425, -59.375, -59.325, -59.275, -59.225, -59.175, -59.125, -59.075, -59.025, -58.975, -58.925, -58.875, -58.825, -58.775, -58.725, -58.675, -58.625, -58.575, -58.525, -58.475, -58.425, -58.375, -58.325, -58.275, -58.225, -58.175, -58.125, -58.075, -58.025, -57.975, -57.925, -57.875, -57.825, -57.775, -57.725, -57.675, -57.625, -57.575, -57.525, -57.475, -57.425, -57.375, -57.325, -57.275, -57.225, -57.175, -57.125, -57.075, -57.025, -56.975, -56.925, -56.875, -56.825, -56.775, -56.725, -56.675, -56.625, -56.575, -56.525, -56.475, -56.425, -56.375, -56.325, -56.275, -56.225, -56.175, -56.125, -56.075, -56.025, -55.975, -55.925, -55.875, -55.825, -55.775, -55.725, -55.675, -55.625, -55.575, -55.525, -55.475, -55.425, -55.375, -55.325, -55.275, -55.225, -55.175, -55.125, -55.075, -55.025, -54.975, -54.925, -54.875, -54.825, -54.775, -54.725, -54.675, -54.625, -54.575, -54.525, -54.475, -54.425, -54.375, -54.325, -54.275, -54.225, -54.175, -54.125, -54.075, -54.025, -53.975, -53.925, -53.875, -53.825, -53.775, -53.725, -53.675, -53.625, -53.575, -53.525, -53.475, -53.425, -53.375, -53.325, -53.275, -53.225, -53.175, -53.125, -53.075, -53.025, -52.975, -52.925, -52.875, -52.825, -52.775, -52.725, -52.675, -52.625, -52.575, -52.525, -52.475, -52.425, -52.375, -52.325, -52.275, -52.225, -52.175, -52.125, -52.075, -52.025, -51.975, -51.925, -51.875, -51.825, -51.775, -51.725, -51.675, -51.625, -51.575, -51.525, -51.475, -51.425, -51.375, -51.325, -51.275, -51.225, -51.175, -51.125, -51.075, -51.025, -50.975, -50.925, -50.875, -50.825, -50.775, -50.725, -50.675, -50.625, -50.575, -50.525, -50.475, -50.425, -50.375, -50.325, -50.275, -50.225, -50.175, -50.125, -50.075, -50.025, -49.975, -49.925, -49.875, -49.825, -49.775, -49.725, -49.675, -49.625, -49.575, -49.525, -49.475, -49.425, -49.375, -49.325, -49.275, -49.225, -49.175, -49.125, -49.075, -49.025, -48.975, -48.925, -48.875, -48.825, -48.775, -48.725, -48.675, -48.625, -48.575, -48.525, -48.475, -48.425, -48.375, -48.325, -48.275, -48.225, -48.175, -48.125, -48.075, -48.025, -47.975, -47.925, -47.875, -47.825, -47.775, -47.725, -47.675, -47.625, -47.575, -47.525, -47.475, -47.425, -47.375, -47.325, -47.275, -47.225, -47.175, -47.125, -47.075, -47.025, -46.975, -46.925, -46.875, -46.825, -46.775, -46.725, -46.675, -46.625, -46.575, -46.525, -46.475, -46.425, -46.375, -46.325, -46.275, -46.225, -46.175, -46.125, -46.075, -46.025, -45.975, -45.925, -45.875, -45.825, -45.775, -45.725, -45.675, -45.625, -45.575, -45.525, -45.475, -45.425, -45.375, -45.325, -45.275, -45.225, -45.175, -45.125, -45.075, -45.025, -44.975, -44.925, -44.875, -44.825, -44.775, -44.725, -44.675, -44.625, -44.575, -44.525, -44.475, -44.425, -44.375, -44.325, -44.275, -44.225, -44.175, -44.125, -44.075, -44.025, -43.975, -43.925, -43.875, -43.825, -43.775, -43.725, -43.675, -43.625, -43.575, -43.525, -43.475, -43.425, -43.375, -43.325, -43.275, -43.225, -43.175, -43.125, -43.075, -43.025, -42.975, -42.925, -42.875, -42.825, -42.775, -42.725, -42.675, -42.625, -42.575, -42.525, -42.475, -42.425, -42.375, -42.325, -42.275, -42.225, -42.175, -42.125, -42.075, -42.025, -41.975, -41.925, -41.875, -41.825, -41.775, -41.725, -41.675, -41.625, -41.575, -41.525, -41.475, -41.425, -41.375, -41.325, -41.275, -41.225, -41.175, -41.125, -41.075, -41.025, -40.975, -40.925, -40.875, -40.825, -40.775, -40.725, -40.675, -40.625, -40.575, -40.525, -40.475, -40.425, -40.375, -40.325, -40.275, -40.225, -40.175, -40.125, -40.075, -40.025, -39.975, -39.925, -39.875, -39.825, -39.775, -39.725, -39.675, -39.625, -39.575, -39.525, -39.475, -39.425, -39.375, -39.325, -39.275, -39.225, -39.175, -39.125, -39.075, -39.025, -38.975, -38.925, -38.875, -38.825, -38.775, -38.725, -38.675, -38.625, -38.575, -38.525, -38.475, -38.425, -38.375, -38.325, -38.275, -38.225, -38.175, -38.125, -38.075, -38.025, -37.975, -37.925, -37.875, -37.825, -37.775, -37.725, -37.675, -37.625, -37.575, -37.525, -37.475, -37.425, -37.375, -37.325, -37.275, -37.225, -37.175, -37.125, -37.075, -37.025, -36.975, -36.925, -36.875, -36.825, -36.775, -36.725, -36.675, -36.625, -36.575, -36.525, -36.475, -36.425, -36.375, -36.325, -36.275, -36.225, -36.175, -36.125, -36.075, -36.025, -35.975, -35.925, -35.875, -35.825, -35.775, -35.725, -35.675, -35.625, -35.575, -35.525, -35.475, -35.425, -35.375, -35.325, -35.275, -35.225, -35.175, -35.125, -35.075, -35.025, -34.975, -34.925, -34.875, -34.825, -34.775, -34.725, -34.675, -34.625, -34.575, -34.525, -34.475, -34.425, -34.375, -34.325, -34.275, -34.225, -34.175, -34.125, -34.075, -34.025, -33.975, -33.925, -33.875, -33.825, -33.775, -33.725, -33.675, -33.625, -33.575, -33.525, -33.475, -33.425, -33.375, -33.325, -33.275, -33.225, -33.175, -33.125, -33.075, -33.025, -32.975, -32.925, -32.875, -32.825, -32.775, -32.725, -32.675, -32.625, -32.575, -32.525, -32.475, -32.425, -32.375, -32.325, -32.275, -32.225, -32.175, -32.125, -32.075, -32.025, -31.975, -31.925, -31.875, -31.825, -31.775, -31.725, -31.675, -31.625, -31.575, -31.525, -31.475, -31.425, -31.375, -31.325, -31.275, -31.225, -31.175, -31.125, -31.075, -31.025, -30.975, -30.925, -30.875, -30.825, -30.775, -30.725, -30.675, -30.625, -30.575, -30.525, -30.475, -30.425, -30.375, -30.325, -30.275, -30.225, -30.175, -30.125, -30.075, -30.025, -29.975, -29.925, -29.875, -29.825, -29.775, -29.725, -29.675, -29.625, -29.575, -29.525, -29.475, -29.425, -29.375, -29.325, -29.275, -29.225, -29.175, -29.125, -29.075, -29.025, -28.975, -28.925, -28.875, -28.825, -28.775, -28.725, -28.675, -28.625, -28.575, -28.525, -28.475, -28.425, -28.375, -28.325, -28.275, -28.225, -28.175, -28.125, -28.075, -28.025, -27.975, -27.925, -27.875, -27.825, -27.775, -27.725, -27.675, -27.625, -27.575, -27.525, -27.475, -27.425, -27.375, -27.325, -27.275, -27.225, -27.175, -27.125, -27.075, -27.025, -26.975, -26.925, -26.875, -26.825, -26.775, -26.725, -26.675, -26.625, -26.575, -26.525, -26.475, -26.425, -26.375, -26.325, -26.275, -26.225, -26.175, -26.125, -26.075, -26.025, -25.975, -25.925, -25.875, -25.825, -25.775, -25.725, -25.675, -25.625, -25.575, -25.525, -25.475, -25.425, -25.375, -25.325, -25.275, -25.225, -25.175, -25.125, -25.075, -25.025, -24.975, -24.925, -24.875, -24.825, -24.775, -24.725, -24.675, -24.625, -24.575, -24.525, -24.475, -24.425, -24.375, -24.325, -24.275, -24.225, -24.175, -24.125, -24.075, -24.025, -23.975, -23.925, -23.875, -23.825, -23.775, -23.725, -23.675, -23.625, -23.575, -23.525, -23.475, -23.425, -23.375, -23.325, -23.275, -23.225, -23.175, -23.125, -23.075, -23.025, -22.975, -22.925, -22.875, -22.825, -22.775, -22.725, -22.675, -22.625, -22.575, -22.525, -22.475, -22.425, -22.375, -22.325, -22.275, -22.225, -22.175, -22.125, -22.075, -22.025, -21.975, -21.925, -21.875, -21.825, -21.775, -21.725, -21.675, -21.625, -21.575, -21.525, -21.475, -21.425, -21.375, -21.325, -21.275, -21.225, -21.175, -21.125, -21.075, -21.025, -20.975, -20.925, -20.875, -20.825, -20.775, -20.725, -20.675, -20.625, -20.575, -20.525, -20.475, -20.425, -20.375, -20.325, -20.275, -20.225, -20.175, -20.125, -20.075, -20.025, -19.975, -19.925, -19.875, -19.825, -19.775, -19.725, -19.675, -19.625, -19.575, -19.525, -19.475, -19.425, -19.375, -19.325, -19.275, -19.225, -19.175, -19.125, -19.075, -19.025, -18.975, -18.925, -18.875, -18.825, -18.775, -18.725, -18.675, -18.625, -18.575, -18.525, -18.475, -18.425, -18.375, -18.325, -18.275, -18.225, -18.175, -18.125, -18.075, -18.025, -17.975, -17.925, -17.875, -17.825, -17.775, -17.725, -17.675, -17.625, -17.575, -17.525, -17.475, -17.425, -17.375, -17.325, -17.275, -17.225, -17.175, -17.125, -17.075, -17.025, -16.975, -16.925, -16.875, -16.825, -16.775, -16.725, -16.675, -16.625, -16.575, -16.525, -16.475, -16.425, -16.375, -16.325, -16.275, -16.225, -16.175, -16.125, -16.075, -16.025, -15.975, -15.925, -15.875, -15.825, -15.775, -15.725, -15.675, -15.625, -15.575, -15.525, -15.475, -15.425, -15.375, -15.325, -15.275, -15.225, -15.175, -15.125, -15.075, -15.025, -14.975, -14.925, -14.875, -14.825, -14.775, -14.725, -14.675, -14.625, -14.575, -14.525, -14.475, -14.425, -14.375, -14.325, -14.275, -14.225, -14.175, -14.125, -14.075, -14.025, -13.975, -13.925, -13.875, -13.825, -13.775, -13.725, -13.675, -13.625, -13.575, -13.525, -13.475, -13.425, -13.375, -13.325, -13.275, -13.225, -13.175, -13.125, -13.075, -13.025, -12.975, -12.925, -12.875, -12.825, -12.775, -12.725, -12.675, -12.625, -12.575, -12.525, -12.475, -12.425, -12.375, -12.325, -12.275, -12.225, -12.175, -12.125, -12.075, -12.025, -11.975, -11.925, -11.875, -11.825, -11.775, -11.725, -11.675, -11.625, -11.575, -11.525, -11.475, -11.425, -11.375, -11.325, -11.275, -11.225, -11.175, -11.125, -11.075, -11.025, -10.975, -10.925, -10.875, -10.825, -10.775, -10.725, -10.675, -10.625, -10.575, -10.525, -10.475, -10.425, -10.375, -10.325, -10.275, -10.225, -10.175, -10.125, -10.075, -10.025, -9.975, -9.925, -9.875, -9.825, -9.775, -9.725, -9.675, -9.625, -9.575, -9.525, -9.475, -9.425, -9.375, -9.325, -9.275, -9.225, -9.175, -9.125, -9.075, -9.025, -8.975, -8.925, -8.875, -8.825, -8.775, -8.725, -8.675, -8.625, -8.575, -8.525, -8.475, -8.425, -8.375, -8.325, -8.275, -8.225, -8.175, -8.125, -8.075, -8.025, -7.975, -7.925, -7.875, -7.825, -7.775, -7.725, -7.675, -7.625, -7.575, -7.525, -7.475, -7.425, -7.375, -7.325, -7.275, -7.225, -7.175, -7.125, -7.075, -7.025, -6.975, -6.925, -6.875, -6.825, -6.775, -6.725, -6.675, -6.625, -6.575, -6.525, -6.475, -6.425, -6.375, -6.325, -6.275, -6.225, -6.175, -6.125, -6.075, -6.025, -5.975, -5.925, -5.875, -5.825, -5.775, -5.725, -5.675, -5.625, -5.575, -5.525, -5.475, -5.425, -5.375, -5.325, -5.275, -5.225, -5.175, -5.125, -5.075, -5.025, -4.975, -4.925, -4.875, -4.825, -4.775, -4.725, -4.675, -4.625, -4.575, -4.525, -4.475, -4.425, -4.375, -4.325, -4.275, -4.225, -4.175, -4.125, -4.075, -4.025, -3.975, -3.925, -3.875, -3.825, -3.775, -3.725, -3.675, -3.625, -3.575, -3.525, -3.475, -3.425, -3.375, -3.325, -3.275, -3.225, -3.175, -3.125, -3.075, -3.025, -2.975, -2.925, -2.875, -2.825, -2.775, -2.725, -2.675, -2.625, -2.575, -2.525, -2.475, -2.425, -2.375, -2.325, -2.275, -2.225, -2.175, -2.125, -2.075, -2.025, -1.975, -1.925, -1.875, -1.825, -1.775, -1.725, -1.675, -1.625, -1.575, -1.525, -1.475, -1.425, -1.375, -1.325, -1.275, -1.225, -1.175, -1.125, -1.075, -1.025, -0.975, -0.925, -0.875, -0.825, -0.775, -0.725, -0.675, -0.625, -0.575, -0.525, -0.475, -0.425, -0.375, -0.325, -0.275, -0.225, -0.175, -0.125, -0.075, -0.025, 0.025, 0.075, 0.125, 0.175, 0.225, 0.275, 0.325, 0.375, 0.425, 0.475, 0.525, 0.575, 0.625, 0.675, 0.725, 0.775, 0.825, 0.875, 0.925, 0.975, 1.025, 1.075, 1.125, 1.175, 1.225, 1.275, 1.325, 1.375, 1.425, 1.475, 1.525, 1.575, 1.625, 1.675, 1.725, 1.775, 1.825, 1.875, 1.925, 1.975, 2.025, 2.075, 2.125, 2.175, 2.225, 2.275, 2.325, 2.375, 2.425, 2.475, 2.525, 2.575, 2.625, 2.675, 2.725, 2.775, 2.825, 2.875, 2.925, 2.975, 3.025, 3.075, 3.125, 3.175, 3.225, 3.275, 3.325, 3.375, 3.425, 3.475, 3.525, 3.575, 3.625, 3.675, 3.725, 3.775, 3.825, 3.875, 3.925, 3.975, 4.025, 4.075, 4.125, 4.175, 4.225, 4.275, 4.325, 4.375, 4.425, 4.475, 4.525, 4.575, 4.625, 4.675, 4.725, 4.775, 4.825, 4.875, 4.925, 4.975, 5.025, 5.075, 5.125, 5.175, 5.225, 5.275, 5.325, 5.375, 5.425, 5.475, 5.525, 5.575, 5.625, 5.675, 5.725, 5.775, 5.825, 5.875, 5.925, 5.975, 6.025, 6.075, 6.125, 6.175, 6.225, 6.275, 6.325, 6.375, 6.425, 6.475, 6.525, 6.575, 6.625, 6.675, 6.725, 6.775, 6.825, 6.875, 6.925, 6.975, 7.025, 7.075, 7.125, 7.175, 7.225, 7.275, 7.325, 7.375, 7.425, 7.475, 7.525, 7.575, 7.625, 7.675, 7.725, 7.775, 7.825, 7.875, 7.925, 7.975, 8.025, 8.075, 8.125, 8.175, 8.225, 8.275, 8.325, 8.375, 8.425, 8.475, 8.525, 8.575, 8.625, 8.675, 8.725, 8.775, 8.825, 8.875, 8.925, 8.975, 9.025, 9.075, 9.125, 9.175, 9.225, 9.275, 9.325, 9.375, 9.425, 9.475, 9.525, 9.575, 9.625, 9.675, 9.725, 9.775, 9.825, 9.875, 9.925, 9.975, 10.025, 10.075, 10.125, 10.175, 10.225, 10.275, 10.325, 10.375, 10.425, 10.475, 10.525, 10.575, 10.625, 10.675, 10.725, 10.775, 10.825, 10.875, 10.925, 10.975, 11.025, 11.075, 11.125, 11.175, 11.225, 11.275, 11.325, 11.375, 11.425, 11.475, 11.525, 11.575, 11.625, 11.675, 11.725, 11.775, 11.825, 11.875, 11.925, 11.975, 12.025, 12.075, 12.125, 12.175, 12.225, 12.275, 12.325, 12.375, 12.425, 12.475, 12.525, 12.575, 12.625, 12.675, 12.725, 12.775, 12.825, 12.875, 12.925, 12.975, 13.025, 13.075, 13.125, 13.175, 13.225, 13.275, 13.325, 13.375, 13.425, 13.475, 13.525, 13.575, 13.625, 13.675, 13.725, 13.775, 13.825, 13.875, 13.925, 13.975, 14.025, 14.075, 14.125, 14.175, 14.225, 14.275, 14.325, 14.375, 14.425, 14.475, 14.525, 14.575, 14.625, 14.675, 14.725, 14.775, 14.825, 14.875, 14.925, 14.975, 15.025, 15.075, 15.125, 15.175, 15.225, 15.275, 15.325, 15.375, 15.425, 15.475, 15.525, 15.575, 15.625, 15.675, 15.725, 15.775, 15.825, 15.875, 15.925, 15.975, 16.025, 16.075, 16.125, 16.175, 16.225, 16.275, 16.325, 16.375, 16.425, 16.475, 16.525, 16.575, 16.625, 16.675, 16.725, 16.775, 16.825, 16.875, 16.925, 16.975, 17.025, 17.075, 17.125, 17.175, 17.225, 17.275, 17.325, 17.375, 17.425, 17.475, 17.525, 17.575, 17.625, 17.675, 17.725, 17.775, 17.825, 17.875, 17.925, 17.975, 18.025, 18.075, 18.125, 18.175, 18.225, 18.275, 18.325, 18.375, 18.425, 18.475, 18.525, 18.575, 18.625, 18.675, 18.725, 18.775, 18.825, 18.875, 18.925, 18.975, 19.025, 19.075, 19.125, 19.175, 19.225, 19.275, 19.325, 19.375, 19.425, 19.475, 19.525, 19.575, 19.625, 19.675, 19.725, 19.775, 19.825, 19.875, 19.925, 19.975, 20.025, 20.075, 20.125, 20.175, 20.225, 20.275, 20.325, 20.375, 20.425, 20.475, 20.525, 20.575, 20.625, 20.675, 20.725, 20.775, 20.825, 20.875, 20.925, 20.975, 21.025, 21.075, 21.125, 21.175, 21.225, 21.275, 21.325, 21.375, 21.425, 21.475, 21.525, 21.575, 21.625, 21.675, 21.725, 21.775, 21.825, 21.875, 21.925, 21.975, 22.025, 22.075, 22.125, 22.175, 22.225, 22.275, 22.325, 22.375, 22.425, 22.475, 22.525, 22.575, 22.625, 22.675, 22.725, 22.775, 22.825, 22.875, 22.925, 22.975, 23.025, 23.075, 23.125, 23.175, 23.225, 23.275, 23.325, 23.375, 23.425, 23.475, 23.525, 23.575, 23.625, 23.675, 23.725, 23.775, 23.825, 23.875, 23.925, 23.975, 24.025, 24.075, 24.125, 24.175, 24.225, 24.275, 24.325, 24.375, 24.425, 24.475, 24.525, 24.575, 24.625, 24.675, 24.725, 24.775, 24.825, 24.875, 24.925, 24.975, 25.025, 25.075, 25.125, 25.175, 25.225, 25.275, 25.325, 25.375, 25.425, 25.475, 25.525, 25.575, 25.625, 25.675, 25.725, 25.775, 25.825, 25.875, 25.925, 25.975, 26.025, 26.075, 26.125, 26.175, 26.225, 26.275, 26.325, 26.375, 26.425, 26.475, 26.525, 26.575, 26.625, 26.675, 26.725, 26.775, 26.825, 26.875, 26.925, 26.975, 27.025, 27.075, 27.125, 27.175, 27.225, 27.275, 27.325, 27.375, 27.425, 27.475, 27.525, 27.575, 27.625, 27.675, 27.725, 27.775, 27.825, 27.875, 27.925, 27.975, 28.025, 28.075, 28.125, 28.175, 28.225, 28.275, 28.325, 28.375, 28.425, 28.475, 28.525, 28.575, 28.625, 28.675, 28.725, 28.775, 28.825, 28.875, 28.925, 28.975, 29.025, 29.075, 29.125, 29.175, 29.225, 29.275, 29.325, 29.375, 29.425, 29.475, 29.525, 29.575, 29.625, 29.675, 29.725, 29.775, 29.825, 29.875, 29.925, 29.975, 30.025, 30.075, 30.125, 30.175, 30.225, 30.275, 30.325, 30.375, 30.425, 30.475, 30.525, 30.575, 30.625, 30.675, 30.725, 30.775, 30.825, 30.875, 30.925, 30.975, 31.025, 31.075, 31.125, 31.175, 31.225, 31.275, 31.325, 31.375, 31.425, 31.475, 31.525, 31.575, 31.625, 31.675, 31.725, 31.775, 31.825, 31.875, 31.925, 31.975, 32.025, 32.075, 32.125, 32.175, 32.225, 32.275, 32.325, 32.375, 32.425, 32.475, 32.525, 32.575, 32.625, 32.675, 32.725, 32.775, 32.825, 32.875, 32.925, 32.975, 33.025, 33.075, 33.125, 33.175, 33.225, 33.275, 33.325, 33.375, 33.425, 33.475, 33.525, 33.575, 33.625, 33.675, 33.725, 33.775, 33.825, 33.875, 33.925, 33.975, 34.025, 34.075, 34.125, 34.175, 34.225, 34.275, 34.325, 34.375, 34.425, 34.475, 34.525, 34.575, 34.625, 34.675, 34.725, 34.775, 34.825, 34.875, 34.925, 34.975, 35.025, 35.075, 35.125, 35.175, 35.225, 35.275, 35.325, 35.375, 35.425, 35.475, 35.525, 35.575, 35.625, 35.675, 35.725, 35.775, 35.825, 35.875, 35.925, 35.975, 36.025, 36.075, 36.125, 36.175, 36.225, 36.275, 36.325, 36.375, 36.425, 36.475, 36.525, 36.575, 36.625, 36.675, 36.725, 36.775, 36.825, 36.875, 36.925, 36.975, 37.025, 37.075, 37.125, 37.175, 37.225, 37.275, 37.325, 37.375, 37.425, 37.475, 37.525, 37.575, 37.625, 37.675, 37.725, 37.775, 37.825, 37.875, 37.925, 37.975, 38.025, 38.075, 38.125, 38.175, 38.225, 38.275, 38.325, 38.375, 38.425, 38.475, 38.525, 38.575, 38.625, 38.675, 38.725, 38.775, 38.825, 38.875, 38.925, 38.975, 39.025, 39.075, 39.125, 39.175, 39.225, 39.275, 39.325, 39.375, 39.425, 39.475, 39.525, 39.575, 39.625, 39.675, 39.725, 39.775, 39.825, 39.875, 39.925, 39.975, 40.025, 40.075, 40.125, 40.175, 40.225, 40.275, 40.325, 40.375, 40.425, 40.475, 40.525, 40.575, 40.625, 40.675, 40.725, 40.775, 40.825, 40.875, 40.925, 40.975, 41.025, 41.075, 41.125, 41.175, 41.225, 41.275, 41.325, 41.375, 41.425, 41.475, 41.525, 41.575, 41.625, 41.675, 41.725, 41.775, 41.825, 41.875, 41.925, 41.975, 42.025, 42.075, 42.125, 42.175, 42.225, 42.275, 42.325, 42.375, 42.425, 42.475, 42.525, 42.575, 42.625, 42.675, 42.725, 42.775, 42.825, 42.875, 42.925, 42.975, 43.025, 43.075, 43.125, 43.175, 43.225, 43.275, 43.325, 43.375, 43.425, 43.475, 43.525, 43.575, 43.625, 43.675, 43.725, 43.775, 43.825, 43.875, 43.925, 43.975, 44.025, 44.075, 44.125, 44.175, 44.225, 44.275, 44.325, 44.375, 44.425, 44.475, 44.525, 44.575, 44.625, 44.675, 44.725, 44.775, 44.825, 44.875, 44.925, 44.975, 45.025, 45.075, 45.125, 45.175, 45.225, 45.275, 45.325, 45.375, 45.425, 45.475, 45.525, 45.575, 45.625, 45.675, 45.725, 45.775, 45.825, 45.875, 45.925, 45.975, 46.025, 46.075, 46.125, 46.175, 46.225, 46.275, 46.325, 46.375, 46.425, 46.475, 46.525, 46.575, 46.625, 46.675, 46.725, 46.775, 46.825, 46.875, 46.925, 46.975, 47.025, 47.075, 47.125, 47.175, 47.225, 47.275, 47.325, 47.375, 47.425, 47.475, 47.525, 47.575, 47.625, 47.675, 47.725, 47.775, 47.825, 47.875, 47.925, 47.975, 48.025, 48.075, 48.125, 48.175, 48.225, 48.275, 48.325, 48.375, 48.425, 48.475, 48.525, 48.575, 48.625, 48.675, 48.725, 48.775, 48.825, 48.875, 48.925, 48.975, 49.025, 49.075, 49.125, 49.175, 49.225, 49.275, 49.325, 49.375, 49.425, 49.475, 49.525, 49.575, 49.625, 49.675, 49.725, 49.775, 49.825, 49.875, 49.925, 49.975, 50.025, 50.075, 50.125, 50.175, 50.225, 50.275, 50.325, 50.375, 50.425, 50.475, 50.525, 50.575, 50.625, 50.675, 50.725, 50.775, 50.825, 50.875, 50.925, 50.975, 51.025, 51.075, 51.125, 51.175, 51.225, 51.275, 51.325, 51.375, 51.425, 51.475, 51.525, 51.575, 51.625, 51.675, 51.725, 51.775, 51.825, 51.875, 51.925, 51.975, 52.025, 52.075, 52.125, 52.175, 52.225, 52.275, 52.325, 52.375, 52.425, 52.475, 52.525, 52.575, 52.625, 52.675, 52.725, 52.775, 52.825, 52.875, 52.925, 52.975, 53.025, 53.075, 53.125, 53.175, 53.225, 53.275, 53.325, 53.375, 53.425, 53.475, 53.525, 53.575, 53.625, 53.675, 53.725, 53.775, 53.825, 53.875, 53.925, 53.975, 54.025, 54.075, 54.125, 54.175, 54.225, 54.275, 54.325, 54.375, 54.425, 54.475, 54.525, 54.575, 54.625, 54.675, 54.725, 54.775, 54.825, 54.875, 54.925, 54.975, 55.025, 55.075, 55.125, 55.175, 55.225, 55.275, 55.325, 55.375, 55.425, 55.475, 55.525, 55.575, 55.625, 55.675, 55.725, 55.775, 55.825, 55.875, 55.925, 55.975, 56.025, 56.075, 56.125, 56.175, 56.225, 56.275, 56.325, 56.375, 56.425, 56.475, 56.525, 56.575, 56.625, 56.675, 56.725, 56.775, 56.825, 56.875, 56.925, 56.975, 57.025, 57.075, 57.125, 57.175, 57.225, 57.275, 57.325, 57.375, 57.425, 57.475, 57.525, 57.575, 57.625, 57.675, 57.725, 57.775, 57.825, 57.875, 57.925, 57.975, 58.025, 58.075, 58.125, 58.175, 58.225, 58.275, 58.325, 58.375, 58.425, 58.475, 58.525, 58.575, 58.625, 58.675, 58.725, 58.775, 58.825, 58.875, 58.925, 58.975, 59.025, 59.075, 59.125, 59.175, 59.225, 59.275, 59.325, 59.375, 59.425, 59.475, 59.525, 59.575, 59.625, 59.675, 59.725, 59.775, 59.825, 59.875, 59.925, 59.975}; + diff --git a/retired/modules/ngap_module/tests/ngap/20240809210000-OSISAF-L3C_GHRSST-pocloud-only.dmr.bescmd b/retired/modules/ngap_module/tests/ngap/20240809210000-OSISAF-L3C_GHRSST-pocloud-only.dmr.bescmd new file mode 100644 index 0000000000..cdb65b04b3 --- /dev/null +++ b/retired/modules/ngap_module/tests/ngap/20240809210000-OSISAF-L3C_GHRSST-pocloud-only.dmr.bescmd @@ -0,0 +1,18 @@ + + + + 300 + no + xml + 0 + + + collections/C2036877806-POCLOUD/granules/20240809210000-OSISAF-L3C_GHRSST-SSTsubskin-GOES16-ssteqc_goes16_20240809_210000-v02.0-fv01.0 + + + + + + + diff --git a/retired/modules/ngap_module/tests/ngap/20240809210000-OSISAF-L3C_GHRSST-pocloud-only.dmr.bescmd.baseline b/retired/modules/ngap_module/tests/ngap/20240809210000-OSISAF-L3C_GHRSST-pocloud-only.dmr.bescmd.baseline new file mode 100644 index 0000000000..941bbc971f --- /dev/null +++ b/retired/modules/ngap_module/tests/ngap/20240809210000-OSISAF-L3C_GHRSST-pocloud-only.dmr.bescmd.baseline @@ -0,0 +1,805 @@ + + + + + + + + + reference time of sst file + + + time + + + T + + + seconds since 1981-01-01 00:00:00 + + + + + + longitude + + + longitude + + + X + + + degrees_east + + + -180. + + + 180. + + + geographical coordinates, WGS84 projection + + + + + + latitude + + + latitude + + + Y + + + degrees_north + + + -90. + + + 90. + + + geographical coordinates, WGS84 projection + + + + + + + + -128 + + + 10m wind speed + + + wind_speed + + + m s-1 + + + 10 m + + + 0. + + + 1. + + + 0 + + + 127 + + + 0. + + + WSP-ECMWF-Forecast + + + These wind speeds were created by the ECMWF and represent winds at 10 metres above the sea surface. + + + + + + + + + + + -128 + + + SSES standard deviation + + + kelvin + + + 1. + + + 0.01 + + + -127 + + + 127 + + + Standard deviation estimate derived using the techniques described at http://www.ghrsst.org/SSES-Description-of-schemes.html + + + + + + + + + + + -2147483648 + + + time difference from reference time + + + seconds + + + 0. + + + 1. + + + -2147483647 + + + 2147483647 + + + time plus sst_dtime gives seconds after 00:00:00 UTC January 1, 1981 + + + + + + + + + + + -128 + + + solar zenith angle + + + angular_degree + + + 90. + + + 1. + + + -90 + + + 90 + + + The solar zenith angle at the time of the SST observations. + + + + + + + + + + + -128 + + + sea ice fraction + + + sea_ice_area_fraction + + + + + + 0. + + + 0.01 + + + 0 + + + 100 + + + 0. + + + ICE-OSISAF + + + Fractional sea ice cover from OSISAF ice product + + + + + + + + + + + L2P flags + + + 0 + + + 15 + + + microwave land ice lake + + + 1 + 2 + 4 + 8 + + + These flags are important to properly use the data. + + + + + + + + + + + -128 + + + sources of aerosol dynamic indicator + + + 0 + + + 2 + + + no_data AOD-NAAPS-ADI SDI-OSISAF-ADI + + + 0 + 1 + 2 + + + This variable provides a pixel by pixel description of where aerosol optical depth were derived from. + + + + + + + + + + + -128 + + + aerosol dynamic indicator + + + + + + 0. + + + 0.10000000000000001 + + + 0 + + + 127 + + + sources_of_adi + + + + + + + + + + + + + + -32768 + + + sea surface subskin temperature + + + sea_surface_subskin_temperature + + + kelvin + + + 273.14999999999998 + + + 0.01 + + + -300 + + + 4500 + + + 1 millimeter + + + GOES_Imager + + + Temperature of the subskin of the ocean + + + + + + + + + + + -128 + + + quality level of SST pixel + + + 0 + + + 5 + + + no_data bad_data worst_quality low_quality acceptable_quality best_quality + + + 0 + 1 + 2 + 3 + 4 + 5 + + + These are the overall quality indicators and are used for all GHRSST SSTs + + + + + + + + + + + -128 + + + deviation from SST analysis or reference climatology + + + kelvin + + + 0. + + + 0.10000000000000001 + + + -127 + + + 127 + + + OSTIA + + + The difference between this SST and the previous day's SST analysis + + + + + + + + + + + -128 + + + satellite zenith angle + + + angular_degree + + + 0. + + + 1. + + + -90 + + + 90 + + + The satellite zenith angle at the time of the SST observations. + + + + + + + + + + + -32768 + + + original longitude of the SST value + + + longitude + + + degrees_east + + + 0. + + + 0.01 + + + -18000 + + + 18000 + + + Original longitude of the SST value + + + + + + + + + + + -128 + + + time difference of ADI data from sst measurement + + + hour + + + 0. + + + 0.10000000000000001 + + + -127 + + + 127 + + + Difference in hours between the ADI and SST data + + + + + + + + + + + -32768 + + + original latitude of the SST value + + + latitude + + + degrees_north + + + 0. + + + 0.01 + + + -9000 + + + 9000 + + + Original latitude of the SST value + + + + + + + + + + + -128 + + + SSES bias estimate + + + kelvin + + + 0. + + + 0.01 + + + -127 + + + 127 + + + Bias estimate derived using the techniques described at http://www.ghrsst.org/SSES-Description-of-schemes.html + + + + + + + CF-1.4 + + + Sea Surface Temperature + + + The L3C product derived from GOES16/ABI brightness temperatures. + + + Geostationary Sea Surface Temperature Product User Manual, http://www.osi-saf.org + + + OSISAF + + + + + + All intellectual property rights of the Ocean & Sea Ice SAF products belong to EUMETSAT. The use of these products is granted to every user, free of charge. If users wish to use these products, EUMETSAT's copyright credit must be shown by displaying the words 'Copyright EUMETSAT' under each of the products shown. EUMETSAT offers no warranty and accepts no liability in respect of the Ocean & Sea Ice SAF products. EUMETSAT neither commits to nor guarantees the continuity, availability, or quality or suitability for any purpose of, the Ocean & Sea Ice SAF products. + + + GOES16-OSISAF-L3C-v1.0 + + + OSI-207-b + + + org.ghrsst + + + 1.0 + + + 2.0 + + + 3 + + + 0.05 degree + + + 60. + + + -60. + + + -15. + + + -135. + + + GOES_ABI + + + GOES16 + + + GOES_ABI + + + Unidata Dataset Discovery v1.0 + + + N/A + + + Oceans > Ocean Temperature > Sea Surface Temperature + + + NASA Global Change Master Directory (GCMD) Science Keywords + + + NetCDF Climate and Forecast (CF) Metadata Convention + + + degrees_north + + + 0.050000000000000003 + + + degrees_east + + + 0.050000000000000003 + + + In case SAF data (pre-operational or operational) has been used for the study described in a paper the following sentence would be an appropriate reference to the funding coming from EUMETSAT: The data from the EUMETSAT Satellite Application Facility on Ocean & Sea Ice used in this study are accessible through the SAF's homepage http://www.osi-saf.org + + + O&SI SAF + + + osi-saf.helpdesk@meteo.fr + + + http://www.osi-saf.org + + + Group for High Resolution Sea Surface Temperature + + + The GHRSST Project Office + + + http://www.ghrsst.org + + + ghrsst-po@nceo.ac.uk + + + L3C + + + grid + + + METEO-FRANCE GEOSAFO v1.3.3 + + + F63CAD66-5699-11EF-91F2-9440C930FC03 + + + 20240809T215433Z + + + 20240809T204042Z + + + 20240809T204042Z + + + 20240809T211929Z + + + 20240809T211929Z + + + 4.6.3 + + + + 3.21.0-46 + + + 3.21.0-46 + + + libdap-3.21.0-27 + + + +# TheBESKeys::get_as_config() +AllowedHosts=^https?:\/\/ +BES.Catalog.catalog.FollowSymLinks=Yes +BES.Catalog.catalog.RootDirectory=/tmp/tmphcrbshue/ +BES.Catalog.catalog.TypeMatch=dmrpp:.*\.(dmrpp)$; +BES.Catalog.catalog.TypeMatch+=h5:.*(\.bz2|\.gz|\.Z)?$; +BES.Data.RootDirectory=/dev/null +BES.LogName=./bes.log +BES.UncompressCache.dir=/tmp/hyrax_ux +BES.UncompressCache.prefix=ux_ +BES.UncompressCache.size=500 +BES.module.cmd=/usr/lib64/bes/libdap_xml_module.so +BES.module.dap=/usr/lib64/bes/libdap_module.so +BES.module.dmrpp=/usr/lib64/bes/libdmrpp_module.so +BES.module.fonc=/usr/lib64/bes/libfonc_module.so +BES.module.h5=/usr/lib64/bes/libhdf5_module.so +BES.module.nc=/usr/lib64/bes/libnc_module.so +BES.modules=dap,cmd,h5,dmrpp,nc,fonc +FONc.ClassicModel=false +FONc.NoGlobalAttrs=true +H5.EnableCF=false +H5.EnableCheckNameClashing=true + + + + build_dmrpp -c /tmp/bes_conf_kY1v -f /tmp/tmphcrbshue//20240809210000-OSISAF-L3C_GHRSST-SSTsubskin-GOES16-ssteqc_goes16_20240809_210000-v02.0-fv01.0.nc -r /tmp/dmr__ctTpdz -u OPeNDAP_DMRpp_DATA_ACCESS_URL -M + + + diff --git a/retired/modules/ngap_module/tests/ngap/README b/retired/modules/ngap_module/tests/ngap/README new file mode 100644 index 0000000000..567202d24e --- /dev/null +++ b/retired/modules/ngap_module/tests/ngap/README @@ -0,0 +1,13 @@ + +These tests work three scenarios: +1. The DMR++ is in the OPeNDAP S3 bucket and it should be used (because the bes.conf option says so). +2. The DMR++ is in the OPeNDAP S3 bucket but it should not be used (because the bes.conf option says so). + In that case, the DMR++ is found by going to the DAAC bucket +3. The DMR++ is not in the OPeNDAP S3 bucket and but it is in the DAAC bucket and that should be used. + +I used two testsuite.at files, but we might want to combine them into one by adding the bes.conf +file to some of the test macros (or adding a new macro or two). + +These tests require the the CM.config file (not in GitHub) is set with credentials for both the +OPeNDAP S3 bucket and NGAP. The latter uses an EDL token that is only used when the code is built +in developer mode. diff --git a/retired/modules/ngap_module/tests/test.bescmd b/retired/modules/ngap_module/tests/test.bescmd new file mode 100644 index 0000000000..681834714e --- /dev/null +++ b/retired/modules/ngap_module/tests/test.bescmd @@ -0,0 +1,13 @@ + + + no + xml + 0 + providers/GHRC_CLOUD/collections/Lightning Imaging Sensor (LIS) on TRMM Backgrounds V4/granules/TRMM_LIS_BG.04.3_2015.091.98991.nc + + + bg_data_summary_address + + + + diff --git a/retired/modules/ngap_module/tests/testsuite.at b/retired/modules/ngap_module/tests/testsuite.at new file mode 100644 index 0000000000..5c58e04ba3 --- /dev/null +++ b/retired/modules/ngap_module/tests/testsuite.at @@ -0,0 +1,19 @@ +# Process with autom4te to create an -*- Autotest -*- test suite. + +AT_INIT([bes/modules/ngap_module/tests testsuite]) + +m4_include([../../common/handler_tests_macros.m4]) + +# This granule (20180101000000-OSISAF-L3C_GHRSST) is available from both pocloud and the +# cloudydap S3 bucket (cloudydap is in us-east-1). +AT_BESCMD_BESCONF_RESPONSE_TEST([ngap/20180101000000-OSISAF-L3C_GHRSST-cloudydap.dmr.bescmd], [bes.conf]) +AT_BESCMD_BESCONF_BINARY_DAP4_RESPONSE_TEST([ngap/20180101000000-OSISAF-L3C_GHRSST-cloudydap.dap.bescmd], [bes.conf]) + +# This granule (20240809210000-OSISAF-L3C_GHRSST) is only available from pocloud. +AT_BESCMD_BESCONF_RESPONSE_TEST([ngap/20240809210000-OSISAF-L3C_GHRSST-pocloud-only.dmr.bescmd], [bes.conf]) +AT_BESCMD_BESCONF_BINARY_DAP4_RESPONSE_TEST([ngap/20240809210000-OSISAF-L3C_GHRSST-pocloud-only.dap.bescmd], [bes.conf]) + +# Must use a different bes.conf for these - This tests the case where the server only looks +# in the DAAC bucket. +AT_BESCMD_BESCONF_RESPONSE_TEST([ngap/20180101000000-OSISAF-L3C_GHRSST-pocloud.dmr.bescmd], [bes-daac.conf]) +AT_BESCMD_BESCONF_BINARY_DAP4_RESPONSE_TEST([ngap/20180101000000-OSISAF-L3C_GHRSST-pocloud.dap.bescmd], [bes-daac.conf]) diff --git a/retired/modules/ngap_module/unit-tests/.gitignore b/retired/modules/ngap_module/unit-tests/.gitignore new file mode 100644 index 0000000000..0ba6eb105d --- /dev/null +++ b/retired/modules/ngap_module/unit-tests/.gitignore @@ -0,0 +1,3 @@ +static-cache +bes.conf +test_config.h diff --git a/retired/modules/ngap_module/unit-tests/Makefile.am b/retired/modules/ngap_module/unit-tests/Makefile.am new file mode 100644 index 0000000000..b7ccd0599e --- /dev/null +++ b/retired/modules/ngap_module/unit-tests/Makefile.am @@ -0,0 +1,113 @@ +# Tests + +AUTOMAKE_OPTIONS = foreign + +AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/modules/common -I$(top_srcdir)/modules/ngap_module \ + -I$(top_srcdir)/dispatch -I$(top_srcdir)/dap -I$(top_srcdir)/http $(DAP_CFLAGS) + +LIBADD = -L$(top_builddir)/modules/common -lmodules_common $(BES_DISPATCH_LIB) \ + $(top_builddir)/dap/.libs/libdap_module.a $(BES_HTTP_LIB) $(DAP_SERVER_LIBS) $(DAP_CLIENT_LIBS) + +# $(BES_DAP_LIB) Replace with static library explicitly referenced. jhrg 4/29/24 + +if CPPUNIT +AM_CPPFLAGS += $(CPPUNIT_CFLAGS) +LIBADD += $(CPPUNIT_LIBS) +endif + +# These are not used by automake but are often useful for certain types of +# debugging. Set CXXFLAGS to this in the nightly build using export ... +CXXFLAGS_DEBUG = -g3 -O0 -Wall -W -Wcast-align -Werror + +AM_CXXFLAGS= +AM_LDFLAGS = +include $(top_srcdir)/coverage.mk + +DISTCLEANFILES = test_config.h *.Po + +CLEANFILES = bes.conf bes.cache.conf *.dbg *.log + +EXTRA_DIST = test_config.h.in bes.conf.in bes.cache.conf.in cmr_json_responses data + +check_PROGRAMS = $(UNIT_TESTS) + +TESTS = $(UNIT_TESTS) + +noinst_DATA = bes.conf bes.cache.conf +# See target below. jhrg +# $(abs_builddir)/static-cache + +BUILT_SOURCES = test_config.h + +noinst_HEADERS = test_config.h + +# This way of building the header ensures it's in the build dir and that there +# are no '../' sequences in the paths. The BES will reject paths with 'dot dot' +# in them in certain circumstances. jhrg 1/21/18 +test_config.h: $(srcdir)/test_config.h.in Makefile + @mod_abs_srcdir=`${PYTHON} -c "import os.path; print(os.path.abspath('${abs_srcdir}'))"`; \ + mod_abs_builddir=`${PYTHON} -c "import os.path; print(os.path.abspath('${abs_builddir}'))"`; \ + mod_abs_top_srcdir=`${PYTHON} -c "import os.path; print(os.path.abspath('${abs_top_srcdir}'))"`; \ + sed -e "s%[@]abs_srcdir[@]%$${mod_abs_srcdir}%" \ + -e "s%[@]abs_builddir[@]%$${mod_abs_builddir}%" \ + -e "s%[@]abs_top_srcdir[@]%$${mod_abs_top_srcdir}%" $< > test_config.h + +bes.conf: $(top_srcdir)/configure.ac +bes.cache.conf: $(top_srcdir)/configure.ac + +%.conf: %.conf.in + @clean_abs_top_srcdir=`${PYTHON} -c "import os.path; print(os.path.abspath('${abs_top_srcdir}'))"`; \ + sed -e "s%[@]abs_top_srcdir[@]%$$clean_abs_top_srcdir%" \ + -e "s%[@]abs_top_builddir[@]%${abs_top_builddir}%" $< > $@ + +# This may be useful at some point, but the NGAP module does not use +# it currently. jhrg 3/11/20 +$(abs_builddir)/static-cache: + @echo "# abs_top_srcdir: $(abs_top_srcdir)" + @echo "# top_srcdir: $(top_srcdir)" + @echo "# srcdir: $(srcdir)" + @echo "# abs_top_builddir: $(abs_top_builddir)" + @echo "# abs_builddir: $(abs_builddir)" + @echo "# builddir: $(builddir)" + @echo "# Copying preloaded NGAP cache from: '$(top_srcdir)/modules/ngap_module/data/ngap_cache_for_tests' to '$(builddir)/static-cache'" + cp -r $(top_srcdir)/modules/ngap_module/data/ngap_cache_for_tests $(builddir)/static-cache + chmod -R ug+w $(builddir)/static-cache + +############################################################################ +# Unit Tests +# + +# NgapContainerTest + +if CPPUNIT +UNIT_TESTS = MemoryCacheTest NgapApiTest NgapRequestHandlerTest NgapOwnedContainerTest +else +UNIT_TESTS = + +check-local: + @echo "" + @echo "**********************************************************" + @echo "You must have cppunit 1.12.x or greater installed to run *" + @echo "check target in unit-tests directory *" + @echo "**********************************************************" + @echo "" +endif + +clean-local: + test ! -d $(builddir)/owned-cache || rm -rf $(builddir)/owned-cache + +NgapApiTest_SOURCES = NgapApiTest.cc +NgapApiTest_LDADD = $(top_builddir)/modules/ngap_module/.libs/libngap_module.a $(LIBADD) + +NgapRequestHandlerTest_SOURCES = NgapRequestHandlerTest.cc +NgapRequestHandlerTest_LDADD = $(top_builddir)/modules/ngap_module/.libs/libngap_module.a $(LIBADD) + +# NgapContainerTest_SOURCES = NgapContainerTest.cc +# NgapContainerTest_LDADD = $(top_builddir)/modules/ngap_module/.libs/libngap_module.a $(LIBADD) + +MemoryCacheTest_SOURCES = MemoryCacheTest.cc +MemoryCacheTest_LDADD = $(top_builddir)/modules/ngap_module/.libs/libngap_module.a $(LIBADD) + +NgapOwnedContainerTest_SOURCES = NgapOwnedContainerTest.cc +NgapOwnedContainerTest_LDADD = $(top_builddir)/modules/ngap_module/.libs/libngap_module.a $(LIBADD) + diff --git a/retired/modules/ngap_module/unit-tests/MemoryCacheTest b/retired/modules/ngap_module/unit-tests/MemoryCacheTest new file mode 100755 index 0000000000..c1fbcc3aa1 --- /dev/null +++ b/retired/modules/ngap_module/unit-tests/MemoryCacheTest @@ -0,0 +1,210 @@ +#! /bin/sh + +# MemoryCacheTest - temporary wrapper script for .libs/MemoryCacheTest +# Generated by libtool (GNU libtool) 2.5.4 +# +# The MemoryCacheTest program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s|\([`"$\\]\)|\\\1|g' + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command="" + +# This environment variable determines our operation mode. +if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then + # install mode needs the following variables: + generated_by_libtool_version='2.5.4' + notinst_deplibs=' /Users/jimg/src/opendap/hyrax/bes/dispatch/libbes_dispatch.la' +else + # When we are sourced in execute mode, $file and $ECHO are already set. + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + file="$0" + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + ECHO="printf %s\\n" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ that is used only on +# windows platforms, and (c) all begin with the string --lt- +# (application programs are unlikely to have options that match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's ../../../libtool value, followed by no. +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=$0 + shift + for lt_opt + do + case "$lt_opt" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%/[^/]*$%%'` + test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=. + lt_dump_F=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%^.*/%%'` + cat "$lt_dump_D/$lt_dump_F" + exit 0 + ;; + --lt-*) + $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n "$lt_option_debug"; then + echo "MemoryCacheTest:MemoryCacheTest:$LINENO: libtool wrapper (GNU libtool) 2.5.4" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + $ECHO "MemoryCacheTest:MemoryCacheTest:$LINENO: newargv[$lt_dump_args_N]: $lt_arg" + lt_dump_args_N=`expr $lt_dump_args_N + 1` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ + + if test -n "$lt_option_debug"; then + $ECHO "MemoryCacheTest:MemoryCacheTest:$LINENO: newargv[0]: $progdir/$program" 1>&2 + func_lt_dump_args ${1+"$@"} 1>&2 + fi + exec "$progdir/$program" ${1+"$@"} + + $ECHO "$0: cannot exec $program $*" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from $@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case " $* " in + *\ --lt-*) + for lt_wr_arg + do + case $lt_wr_arg in + --lt-*) ;; + *) set x "$@" "$lt_wr_arg"; shift;; + esac + shift + done ;; + esac + func_exec_program_core ${1+"$@"} +} + + # Parse options + func_parse_lt_options "$0" ${1+"$@"} + + # Find the directory that this script lives in. + thisdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'` + test "x$thisdir" = "x$file" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=`ls -ld "$file" | /usr/bin/sed -n 's/.*-> //p'` + while test -n "$file"; do + destdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'` + + # If there was a directory component, then change thisdir. + if test "x$destdir" != "x$file"; then + case "$destdir" in + [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;; + *) thisdir="$thisdir/$destdir" ;; + esac + fi + + file=`$ECHO "$file" | /usr/bin/sed 's%^.*/%%'` + file=`ls -ld "$thisdir/$file" | /usr/bin/sed -n 's/.*-> //p'` + done + + # Usually 'no', except on cygwin/mingw/windows when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no + if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then + # special case for '.' + if test "$thisdir" = "."; then + thisdir=`pwd` + fi + # remove .libs from thisdir + case "$thisdir" in + *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /usr/bin/sed 's%[\\/][^\\/]*$%%'` ;; + .libs ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=`cd "$thisdir" && pwd` + test -n "$absdir" && thisdir="$absdir" + + program='MemoryCacheTest' + progdir="$thisdir/.libs" + + + if test -f "$progdir/$program"; then + # Add our own library path to DYLD_LIBRARY_PATH + DYLD_LIBRARY_PATH="/Users/jimg/src/opendap/hyrax/bes/dispatch/.libs:$DYLD_LIBRARY_PATH" + + # Some systems cannot cope with colon-terminated DYLD_LIBRARY_PATH + # The second colon is a workaround for a bug in BeOS R4 sed + DYLD_LIBRARY_PATH=`$ECHO "$DYLD_LIBRARY_PATH" | /usr/bin/sed 's/::*$//'` + + export DYLD_LIBRARY_PATH + + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + # Run the actual program with our arguments. + func_exec_program ${1+"$@"} + fi + else + # The program doesn't exist. + $ECHO "$0: error: '$progdir/$program' does not exist" 1>&2 + $ECHO "This script is just a wrapper for $program." 1>&2 + $ECHO "See the libtool documentation for more information." 1>&2 + exit 1 + fi +fi diff --git a/retired/modules/ngap_module/unit-tests/MemoryCacheTest.cc b/retired/modules/ngap_module/unit-tests/MemoryCacheTest.cc new file mode 100644 index 0000000000..b171a5f413 --- /dev/null +++ b/retired/modules/ngap_module/unit-tests/MemoryCacheTest.cc @@ -0,0 +1,223 @@ +// -*- mode: c++; c-basic-offset:4 -*- + +// This file is part of the BES component of the Hyrax Data Server. + +// Copyright (c) 2023 OPeNDAP, Inc. +// Author: James Gallagher +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. + +#include "config.h" + +#include +#include + +#include "BESDebug.h" +#include "MemoryCache.h" + +#include "test_config.h" +#include "run_tests_cppunit.h" + +using namespace std; + +#define prolog string("MemoryCacheTest::").append(__func__).append("() - ") + +namespace ngap { + +class MemoryCacheTest: public CppUnit::TestFixture { + MemoryCache string_cache; + +public: + // Called once before everything gets tested + MemoryCacheTest() = default; + ~MemoryCacheTest() override = default; + MemoryCacheTest(const MemoryCacheTest &src) = delete; + const MemoryCacheTest &operator=(const MemoryCacheTest & rhs) = delete; + + // setUp; Called before each test; not used. + void setUp() override { + string_cache.initialize(5, 2); // holds five things; purge removes two + string_cache.put("one", "one_1"); + string_cache.put("two", "two_2"); + string_cache.put("three", "three_3"); + string_cache.put("four", "four_4"); + string_cache.put("five", "five_5"); + } + + // tearDown; Called after each test; not used. + void tearDown() override { + string_cache.clear(); + } + + void test_zero_items() { + MemoryCache broken_cache; + bool status = broken_cache.initialize(0, 2); + + CPPUNIT_ASSERT_MESSAGE("The cache should not initialize with size of zero", status == false); + CPPUNIT_ASSERT_MESSAGE("The cache invariant should be true", broken_cache.invariant()); + } + + void test_zero_purge() { + MemoryCache broken_cache; + bool status = broken_cache.initialize(5, 0); + + CPPUNIT_ASSERT_MESSAGE("The cache should not initialize with purge size of zero", status == false); + CPPUNIT_ASSERT_MESSAGE("The cache invariant should be true", broken_cache.invariant()); + } + + void test_negative_items() { + MemoryCache broken_cache; + bool status = broken_cache.initialize(-5, 2); + + CPPUNIT_ASSERT_MESSAGE("The cache should not initialize with a negative size", status == false); + CPPUNIT_ASSERT_MESSAGE("The cache invariant should be true", broken_cache.invariant()); + } + + void test_negative_purge_size() { + MemoryCache broken_cache; + bool status = broken_cache.initialize(5, -2); + + CPPUNIT_ASSERT_MESSAGE("The cache should not initialize with a negative purge size", status == false); + CPPUNIT_ASSERT_MESSAGE("The cache invariant should be true", broken_cache.invariant()); + } + + void test_put_one_item() { + MemoryCache local_cache; + local_cache.put("one", "one"); + CPPUNIT_ASSERT_MESSAGE("The cache should have one item", local_cache.size() == 1); + CPPUNIT_ASSERT_MESSAGE("The cache invariant should be true", local_cache.invariant()); + } + + void test_put_five_items() { + CPPUNIT_ASSERT_MESSAGE("The cache should have five items", string_cache.size() == 5); + CPPUNIT_ASSERT_MESSAGE("The cache invariant should be true", string_cache.invariant()); + } + + void test_put_six_items_should_purge() { + string_cache.put("six", "six_6"); + + // After adding the sixth item, the cache should have purged two items, leaving four. + CPPUNIT_ASSERT_MESSAGE("The cache should have four items", string_cache.size() == 4); + CPPUNIT_ASSERT_MESSAGE("The cache invariant should be true", string_cache.invariant()); + CPPUNIT_ASSERT_MESSAGE("The oldest entry in the fifo of keys should be 'two'", + *string_cache.d_fifo_keys.begin() == "three"); + } + + void test_put_three_items_one_purge() { + MemoryCache small_cache; + small_cache.initialize(3, 1); // holds three things; purge removes one + small_cache.put("one", "one_1"); + small_cache.put("two", "two_2"); + small_cache.put("three", "three_3"); + small_cache.put("four", "four_4"); + small_cache.put("five", "five_5"); + small_cache.put("six", "six_6"); + + // After adding the sixth item, the cache should have purged two items, leaving four. + CPPUNIT_ASSERT_MESSAGE("The cache should have three items", small_cache.size() == 3); + CPPUNIT_ASSERT_MESSAGE("The cache invariant should be true", small_cache.invariant()); + CPPUNIT_ASSERT_MESSAGE("The oldest entry in the fifo of keys should be 'four'", + *small_cache.d_fifo_keys.begin() == "four"); + } + + void test_get_one_item() { + CPPUNIT_ASSERT_MESSAGE("The cache should have five items", string_cache.size() == 5); + CPPUNIT_ASSERT_MESSAGE("The cache invariant should be true", string_cache.invariant()); + + string value; + bool status = string_cache.get("three", value); + CPPUNIT_ASSERT_MESSAGE("The cache should have returned true", status == true); + CPPUNIT_ASSERT_MESSAGE("The cache should have returned 'three_3'", value == "three_3"); + } + + void test_get_one_item_not_in_cache() { + CPPUNIT_ASSERT_MESSAGE("The cache should have five items", string_cache.size() == 5); + CPPUNIT_ASSERT_MESSAGE("The cache invariant should be true", string_cache.invariant()); + + string value; + bool status = string_cache.get("17", value); + CPPUNIT_ASSERT_MESSAGE("The cache should have returned false - the item is not in the cache", status == false); + CPPUNIT_ASSERT_MESSAGE("The cache should have returned the empty string", value == ""); + } + + void test_get_one_item_purged() { + string_cache.put("six", "six_6"); // This triggers a purge of two items + + CPPUNIT_ASSERT_MESSAGE("The cache should have five items", string_cache.size() == 4); + CPPUNIT_ASSERT_MESSAGE("The cache invariant should be true", string_cache.invariant()); + + string value; + bool status = string_cache.get("one", value); + CPPUNIT_ASSERT_MESSAGE("The cache should have returned false - the item is not in the cache", status == false); + CPPUNIT_ASSERT_MESSAGE("The cache should have returned the empty string", value == ""); + + status = string_cache.get("two", value); + CPPUNIT_ASSERT_MESSAGE("The cache should have returned false - the item is not in the cache", status == false); + CPPUNIT_ASSERT_MESSAGE("The cache should have returned the empty string", value == ""); + + status = string_cache.get("three", value); + CPPUNIT_ASSERT_MESSAGE("The cache should have returned true - the item is in the cache", status == true); + CPPUNIT_ASSERT_MESSAGE("The cache should have returned 'three_3'", value == "three_3"); + + status = string_cache.get("six", value); + CPPUNIT_ASSERT_MESSAGE("The cache should have returned true - the item is in the cache", status == true); + CPPUNIT_ASSERT_MESSAGE("The cache should have returned 'six_6'", value == "six_6"); + } + + void test_no_initialize() { + MemoryCache local_cache; + string value; + bool status = local_cache.get("one", value); + CPPUNIT_ASSERT_MESSAGE("The cache should have returned false - the item is not in the cache", status == false); + CPPUNIT_ASSERT_MESSAGE("The cache should have returned the empty string", value == ""); + + local_cache.put("one", "one"); + CPPUNIT_ASSERT_MESSAGE("The cache should have one item", local_cache.size() == 1); + CPPUNIT_ASSERT_MESSAGE("The cache invariant should be true", local_cache.invariant()); + } + + CPPUNIT_TEST_SUITE( MemoryCacheTest ); + + CPPUNIT_TEST(test_zero_items); + CPPUNIT_TEST(test_zero_purge); + CPPUNIT_TEST(test_negative_items); + CPPUNIT_TEST(test_negative_purge_size); + + CPPUNIT_TEST(test_put_one_item); + CPPUNIT_TEST(test_put_five_items); + CPPUNIT_TEST(test_put_six_items_should_purge); + CPPUNIT_TEST(test_put_three_items_one_purge); + + CPPUNIT_TEST(test_get_one_item); + CPPUNIT_TEST(test_get_one_item_not_in_cache); + CPPUNIT_TEST(test_get_one_item_purged); + + CPPUNIT_TEST(test_no_initialize); + + CPPUNIT_TEST_SUITE_END(); +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(MemoryCacheTest); + +} // namespace ngap + +int main(int argc, char*argv[]) +{ + bool status = bes_run_tests(argc, argv, "cerr,cache"); + + return status ? 0 : 1; +} diff --git a/retired/modules/ngap_module/unit-tests/NgapApiTest b/retired/modules/ngap_module/unit-tests/NgapApiTest new file mode 100755 index 0000000000..fc79cc78ec --- /dev/null +++ b/retired/modules/ngap_module/unit-tests/NgapApiTest @@ -0,0 +1,210 @@ +#! /bin/sh + +# NgapApiTest - temporary wrapper script for .libs/NgapApiTest +# Generated by libtool (GNU libtool) 2.5.4 +# +# The NgapApiTest program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s|\([`"$\\]\)|\\\1|g' + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command="" + +# This environment variable determines our operation mode. +if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then + # install mode needs the following variables: + generated_by_libtool_version='2.5.4' + notinst_deplibs=' /Users/jimg/src/opendap/hyrax/bes/dispatch/libbes_dispatch.la' +else + # When we are sourced in execute mode, $file and $ECHO are already set. + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + file="$0" + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + ECHO="printf %s\\n" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ that is used only on +# windows platforms, and (c) all begin with the string --lt- +# (application programs are unlikely to have options that match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's ../../../libtool value, followed by no. +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=$0 + shift + for lt_opt + do + case "$lt_opt" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%/[^/]*$%%'` + test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=. + lt_dump_F=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%^.*/%%'` + cat "$lt_dump_D/$lt_dump_F" + exit 0 + ;; + --lt-*) + $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n "$lt_option_debug"; then + echo "NgapApiTest:NgapApiTest:$LINENO: libtool wrapper (GNU libtool) 2.5.4" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + $ECHO "NgapApiTest:NgapApiTest:$LINENO: newargv[$lt_dump_args_N]: $lt_arg" + lt_dump_args_N=`expr $lt_dump_args_N + 1` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ + + if test -n "$lt_option_debug"; then + $ECHO "NgapApiTest:NgapApiTest:$LINENO: newargv[0]: $progdir/$program" 1>&2 + func_lt_dump_args ${1+"$@"} 1>&2 + fi + exec "$progdir/$program" ${1+"$@"} + + $ECHO "$0: cannot exec $program $*" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from $@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case " $* " in + *\ --lt-*) + for lt_wr_arg + do + case $lt_wr_arg in + --lt-*) ;; + *) set x "$@" "$lt_wr_arg"; shift;; + esac + shift + done ;; + esac + func_exec_program_core ${1+"$@"} +} + + # Parse options + func_parse_lt_options "$0" ${1+"$@"} + + # Find the directory that this script lives in. + thisdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'` + test "x$thisdir" = "x$file" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=`ls -ld "$file" | /usr/bin/sed -n 's/.*-> //p'` + while test -n "$file"; do + destdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'` + + # If there was a directory component, then change thisdir. + if test "x$destdir" != "x$file"; then + case "$destdir" in + [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;; + *) thisdir="$thisdir/$destdir" ;; + esac + fi + + file=`$ECHO "$file" | /usr/bin/sed 's%^.*/%%'` + file=`ls -ld "$thisdir/$file" | /usr/bin/sed -n 's/.*-> //p'` + done + + # Usually 'no', except on cygwin/mingw/windows when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no + if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then + # special case for '.' + if test "$thisdir" = "."; then + thisdir=`pwd` + fi + # remove .libs from thisdir + case "$thisdir" in + *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /usr/bin/sed 's%[\\/][^\\/]*$%%'` ;; + .libs ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=`cd "$thisdir" && pwd` + test -n "$absdir" && thisdir="$absdir" + + program='NgapApiTest' + progdir="$thisdir/.libs" + + + if test -f "$progdir/$program"; then + # Add our own library path to DYLD_LIBRARY_PATH + DYLD_LIBRARY_PATH="/Users/jimg/src/opendap/hyrax/bes/dispatch/.libs:$DYLD_LIBRARY_PATH" + + # Some systems cannot cope with colon-terminated DYLD_LIBRARY_PATH + # The second colon is a workaround for a bug in BeOS R4 sed + DYLD_LIBRARY_PATH=`$ECHO "$DYLD_LIBRARY_PATH" | /usr/bin/sed 's/::*$//'` + + export DYLD_LIBRARY_PATH + + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + # Run the actual program with our arguments. + func_exec_program ${1+"$@"} + fi + else + # The program doesn't exist. + $ECHO "$0: error: '$progdir/$program' does not exist" 1>&2 + $ECHO "This script is just a wrapper for $program." 1>&2 + $ECHO "See the libtool documentation for more information." 1>&2 + exit 1 + fi +fi diff --git a/retired/modules/ngap_module/unit-tests/NgapApiTest.cc b/retired/modules/ngap_module/unit-tests/NgapApiTest.cc new file mode 100644 index 0000000000..98c97cd2df --- /dev/null +++ b/retired/modules/ngap_module/unit-tests/NgapApiTest.cc @@ -0,0 +1,358 @@ +// -*- mode: c++; c-basic-offset:4 -*- + +// This file is part of the BES component of the Hyrax Data Server. + +// Copyright (c) 2018 OPeNDAP, Inc. +// Author: Nathan Potter +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. + +#include "config.h" + +#include +#include +#include +#include + +#include +#include "libdap/util.h" + +#include "rapidjson/document.h" +#include "rapidjson/writer.h" +#include "rapidjson/prettywriter.h" +#include "rapidjson/stringbuffer.h" +#include "rapidjson/filereadstream.h" + +#include "BESError.h" +#include "BESDebug.h" +#include "BESUtil.h" +#include "BESCatalogList.h" +#include "TheBESKeys.h" +#include "HttpUtils.h" +#include "HttpNames.h" +#include "url_impl.h" +#include "RemoteResource.h" + +#include "NgapApi.h" +#include "NgapNames.h" + +#include "test_config.h" +#include "run_tests_cppunit.h" +#include "read_test_baseline.h" + +using namespace std; +using namespace rapidjson; + +#define prolog std::string("NgapApiTest::").append(__func__).append("() - ") + +namespace ngap { + +class NgapApiTest: public CppUnit::TestFixture { +private: + void show_file(string filename) + { + ifstream t(filename.c_str()); + + if (t.is_open()) { + string file_content((istreambuf_iterator(t)), istreambuf_iterator()); + t.close(); + cout << endl << "##################################################################" << endl; + cout << "file: " << filename << endl; + cout << ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . " << endl; + cout << file_content << endl; + cout << ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . " << endl; + } + } + +public: + // Called once before everything gets tested + NgapApiTest() = default; + + // Called at the end of the test + ~NgapApiTest() = default; + + // Called before each test + void setUp() override + { + DBG(cerr << endl); + DBG2(cerr << "setUp() - BEGIN" << endl); + string bes_conf = BESUtil::assemblePath(TEST_BUILD_DIR,"bes.conf"); + DBG2(cerr << "setUp() - Using BES configuration: " << bes_conf << endl); + + TheBESKeys::ConfigFile = bes_conf; + + if (debug2) show_file(bes_conf); + + DBG2(cerr << "setUp() - END" << endl); + } + + void show_vector(vector v){ + cerr << "show_vector(): Found " << v.size() << " elements." << endl; + // vector::iterator it = v.begin(); + for(size_t i=0; i < v.size(); i++){ + cerr << "show_vector: v["<< i << "]: " << v[i] << endl; + } + } + + void compare_results(const string &granule_name, const string &data_access_url, const string &expected_data_access_url){ + if (debug) cerr << prolog << "TEST: Is the URL longer than the granule name? " << endl; + CPPUNIT_ASSERT (data_access_url.size() > granule_name.size() ); + + if (debug) cerr << prolog << "TEST: Does the URL end with the granule name? " << endl; + bool endsWithGranuleName = data_access_url.substr(data_access_url.size()-granule_name.size(), granule_name.size()) == granule_name; + CPPUNIT_ASSERT( endsWithGranuleName == true ); + + if (debug) cerr << prolog << "TEST: Does the returned URL match the expected URL? " << endl; + if (debug) cerr << prolog << "CMR returned DataAccessURL: " << data_access_url << endl; + if (debug) cerr << prolog << "The expected DataAccessURL: " << expected_data_access_url << endl; + CPPUNIT_ASSERT (expected_data_access_url == data_access_url); + + } + + /** + * This test exercises the legacy 3 component restified path model + * /providers//collections//granules/ + */ + void resty_path_to_cmr_query_test_01() { + DBG(cerr << prolog << "BEGIN" << endl); + + string resty_path("providers/POCLOUD" + "/collections/Sentinel-6A MF/Jason-CS L2 Advanced Microwave Radiometer (AMR-C) NRT Geophysical Parameters" + "/granules/S6A_MW_2__AMR_____NR_001_227_20201130T133814_20201130T153340_F00"); + DBG(cerr << prolog << "resty_path: " << resty_path << endl); + + string expected_cmr_url( + "https://cmr.earthdata.nasa.gov/search/granules.umm_json_v1_4" + "?" CMR_PROVIDER "=POCLOUD" + "&" CMR_ENTRY_TITLE "=Sentinel-6A%20MF%2FJason-CS%20L2%20Advanced%20Microwave%20Radiometer%20%28AMR-C%29%20NRT%20Geophysical%20Parameters" + "&" CMR_GRANULE_UR "=S6A_MW_2__AMR_____NR_001_227_20201130T133814_20201130T153340_F00" + ); + try { + string cmr_query_url; + cmr_query_url = NgapApi::build_cmr_query_url(resty_path); + DBG(cerr << prolog << "expected_cmr_url: " << expected_cmr_url << endl); + DBG(cerr << prolog << " cmr_query_url: " << cmr_query_url << endl); + CPPUNIT_ASSERT( cmr_query_url == expected_cmr_url ); + } + catch(BESError e){ + stringstream msg; + msg << prolog << "Caught BESError! Message: " << e.get_verbose_message() << endl; + CPPUNIT_FAIL(msg.str()); + } + DBG(cerr << prolog << "END" << endl); + } + + /** + * This test exercises the new (12/2020) 2 component restified path model + * /collections//granules/ + * Example: + * https://opendap.earthdata.nasa.gov/collections/C1443727145-LAADS/granules/MOD08_D3.A2020308.061.2020309092644.hdf.nc + */ + void resty_path_to_cmr_query_test_02() { + DBG(cerr << prolog << "BEGIN" << endl); + + string resty_path("/collections/C1443727145-LAADS/MOD08_D3.v6.1/granules/MOD08_D3.A2020308.061.2020309092644.hdf.nc"); + DBG(cerr << prolog << "resty_path: " << resty_path << endl); + + string expected_cmr_url( + "https://cmr.earthdata.nasa.gov/search/granules.umm_json_v1_4?" + CMR_COLLECTION_CONCEPT_ID "=C1443727145-LAADS&" + CMR_GRANULE_UR "=MOD08_D3.A2020308.061.2020309092644.hdf.nc" + ); + try { + string cmr_query_url; + cmr_query_url = NgapApi::build_cmr_query_url(resty_path); + DBG(cerr << prolog << "expected_cmr_url: " << expected_cmr_url << endl); + DBG(cerr << prolog << " cmr_query_url: " << cmr_query_url << endl); + CPPUNIT_ASSERT( cmr_query_url == expected_cmr_url ); + } + catch(BESError e){ + stringstream msg; + msg << prolog << "Caught BESError! Message: " << e.get_verbose_message() << endl; + CPPUNIT_FAIL(msg.str()); + } + } + + /** + * This test exercises the new (12/2020) 2 component restified path model with the optional shortname and version + * /collections/[/short_name.version]/granules/ + * Example: + * https://opendap.earthdata.nasa.gov/collections/C1443727145-LAADS/MOD08_D3.v6.1/granules/MOD08_D3.A2020308.061.2020309092644.hdf.nc + */ + void resty_path_to_cmr_query_test_03() { + DBG(cerr << prolog << "BEGIN" << endl); + + string resty_path("/collections/C1443727145-LAADS/MOD08_D3.v6.1/granules/MOD08_D3.A2020308.061.2020309092644.hdf.nc"); + DBG(cerr << prolog << "resty_path: " << resty_path << endl); + + string expected_cmr_url( + "https://cmr.earthdata.nasa.gov/search/granules.umm_json_v1_4?" + CMR_COLLECTION_CONCEPT_ID "=C1443727145-LAADS&" + CMR_GRANULE_UR "=MOD08_D3.A2020308.061.2020309092644.hdf.nc" + ); + try { + string cmr_query_url; + cmr_query_url = NgapApi::build_cmr_query_url(resty_path); + DBG(cerr << prolog << "expected_cmr_url: " << expected_cmr_url << endl); + DBG(cerr << prolog << " cmr_query_url: " << cmr_query_url << endl); + CPPUNIT_ASSERT( cmr_query_url == expected_cmr_url ); + } + catch(BESError e){ + stringstream msg; + msg << prolog << "Caught BESError! Message: " << e.get_verbose_message() << endl; + CPPUNIT_FAIL(msg.str()); + } + } + +#if 0 + void cmr_access_entry_title_test() { + DBG(cerr << prolog << "BEGIN" << endl); + string provider_name; + string collection_name; + string granule_name; + string data_access_url; + + provider_name = "GHRC_DAAC"; + collection_name ="ADVANCED MICROWAVE SOUNDING UNIT-A (AMSU-A) SWATH FROM NOAA-15 V1"; + granule_name = "amsua15_2020.028_12915_1139_1324_WI.nc"; + + string resty_path = "providers/"+provider_name+"/collections/"+collection_name+"/granules/"+granule_name; + if (debug) cerr << prolog << "RestifiedPath: " << resty_path << endl; + + try { + data_access_url = NgapApi::convert_ngap_resty_path_to_data_access_url(resty_path); + if (debug) cerr << prolog << "Found data_access_url: " << data_access_url << endl; + } + catch(BESError &e){ + cerr << "Caught BESError: " << e.get_message() << " File: " << e.get_file() << " Line: " << e.get_line() << endl; + CPPUNIT_ASSERT(false); + } + string expected; + expected = "https://data.ghrc.earthdata.nasa.gov/ghrcw-protected/amsua15sp__1/amsu-a/noaa-15/data/nc/2020/0128/amsua15_2020.028_12915_1139_1324_WI.nc"; + compare_results(granule_name, data_access_url, expected); + DBG(cerr << prolog << "END" << endl); + } + + void cmr_access_collection_concept_id_test() { + DBG(cerr << prolog << "BEGIN" << endl); + string provider_name; + string collection_concept_id; + string granule_name; + string data_access_url; + + provider_name = "GHRC_DAAC"; + collection_concept_id ="C1996541017-GHRC_DAAC"; + granule_name = "amsua15_2020.028_12915_1139_1324_WI.nc"; + + string resty_path; + resty_path = "providers/" + provider_name + "/concepts/" + collection_concept_id + "/granules/" + granule_name; + if (debug) cerr << prolog << "RestifiedPath: " << resty_path << endl; + try { + data_access_url = NgapApi::convert_ngap_resty_path_to_data_access_url(resty_path); + if (debug) cerr << prolog << "Found data_access_url: " << data_access_url << endl; + } + catch(BESError &e){ + cerr << "Caught BESError: " << e.get_message() << " File: " << e.get_file() << " Line: " << e.get_line() << endl; + CPPUNIT_ASSERT(false); + } + string expected = "https://data.ghrc.earthdata.nasa.gov/ghrcw-protected/amsua15sp__1/amsu-a/noaa-15/data/nc/2020/0128/amsua15_2020.028_12915_1139_1324_WI.nc"; + compare_results(granule_name, data_access_url, expected); + DBG(cerr << prolog << "END" << endl); + } +#endif + + void signed_url_is_expired_test(){ + DBG(cerr << prolog << "BEGIN" << endl); + string signed_url_str; + std::map url_info; + bool is_expired; + + signed_url_str = "https://ghrcw-protected.s3.us-west-2.amazonaws.com/rss_demo/rssmif16d__7/f16_ssmis_20200512v7.nc?" + "A-userid=hyrax" + "&X-Amz-Algorithm=AWS4-HMAC-SHA256" + "&X-Amz-Credential=SomeBigMessyAwfulEncodedEscapeBunchOfCryptoPhaffing" + "&X-Amz-Date=20200621T161744Z" + "&X-Amz-Expires=86400" + "&X-Amz-Security-Token=FwoGZXIvYXdzENL%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaDKmu" + "SomeBigMessyAwfulEncodedEscapeBunchOfCryptoPhaffingSomeBigMessyAwfulEncodedEscapeBunchOfCryptoPhaffing" + "SomeBigMessyAwfulEncodedEscapeBunchOfCryptoPhaffingSomeBigMessyAwfulEncodedEscapeBunchOfCryptoPhaffing" + "SomeBigMessyAwfulEncodedEscapeBunchOfCryptoPhaffingSomeBigMessyAwfulEncodedEscapeBunchOfCryptoPhaffing" + "SomeBigMessyAwfulEncodedEscapeBunchOfCryptoPhaffingSomeBigMessyAwfulEncodedEscapeBunchOfCryptoPhaffing" + "&X-Amz-SignedHeaders=host" + "&X-Amz-Signature=SomeBigMessyAwfulEncodedEscapeBunchOfCryptoPhaffing"; + + http::url signed_url(signed_url_str); + + time_t now; + time(&now); + stringstream ingest_time; + time_t then = now - 82810; // 23 hours and 10 seconds ago. + + signed_url.set_ingest_time(then); + is_expired = NgapApi::signed_url_is_expired(signed_url); + CPPUNIT_ASSERT(is_expired == true); + DBG(cerr << prolog << "END" << endl); + + } + + void test_find_get_data_url_in_granules_umm_json_v1_4_lpdaac() { + // not a test baseline, but a canned response from LPDAAC + string cmr_canned_response_lpdaac = bes::read_test_baseline(string(TEST_SRC_DIR) + "/cmr_json_responses/ECOv002_L1B_GEO_22172_008_20220604T024955_0700_01.json"); + rapidjson::Document cmr_response; + cmr_response.Parse(cmr_canned_response_lpdaac.c_str()); + + string data_url = NgapApi::find_get_data_url_in_granules_umm_json_v1_4("placeholder_for_restified_url", cmr_response); + + DBG(cerr << prolog << "data_url: " << data_url << endl); + CPPUNIT_ASSERT_MESSAGE("data_url should not be empty", !data_url.empty()); + string expected = "https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/ECO_L1B_GEO.002/ECOv002_L1B_GEO_22172_008_20220604T024955_0700_01/ECOv002_L1B_GEO_22172_008_20220604T024955_0700_01.h5"; + CPPUNIT_ASSERT_MESSAGE("data_url should be '" + expected + " but was '" + data_url, data_url == expected); + } + + // C2251464384-POCLOUD, cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.json. jhrg 5/22/24 + void test_find_get_data_url_in_granules_umm_json_v1_4_podaac() { + string cmr_canned_response_podaac = bes::read_test_baseline(string(TEST_SRC_DIR) + "/cmr_json_responses/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.json"); + rapidjson::Document cmr_response; + cmr_response.Parse(cmr_canned_response_podaac.c_str()); + + string data_url = NgapApi::find_get_data_url_in_granules_umm_json_v1_4("placeholder_for_restified_url", cmr_response); + + DBG(cerr << prolog << "data_url: " << data_url << endl); + CPPUNIT_ASSERT_MESSAGE("data_url should not be empty", !data_url.empty()); + string expected = "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-protected/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.nc"; + CPPUNIT_ASSERT_MESSAGE("data_url should be '" + expected + " but was '" + data_url, data_url == expected); + } + + CPPUNIT_TEST_SUITE( NgapApiTest ); + + CPPUNIT_TEST(resty_path_to_cmr_query_test_01); + CPPUNIT_TEST(resty_path_to_cmr_query_test_02); + CPPUNIT_TEST(resty_path_to_cmr_query_test_03); + CPPUNIT_TEST(signed_url_is_expired_test); + CPPUNIT_TEST(test_find_get_data_url_in_granules_umm_json_v1_4_lpdaac); + CPPUNIT_TEST(test_find_get_data_url_in_granules_umm_json_v1_4_podaac); + + CPPUNIT_TEST_SUITE_END(); +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(NgapApiTest); + +} // namespace dmrpp + +int main(int argc, char*argv[]) { + return bes_run_tests(argc, argv, "cerr,ngap,http") ? 0 : 1; +} diff --git a/retired/modules/ngap_module/unit-tests/NgapContainerTest.cc b/retired/modules/ngap_module/unit-tests/NgapContainerTest.cc new file mode 100644 index 0000000000..86274978ce --- /dev/null +++ b/retired/modules/ngap_module/unit-tests/NgapContainerTest.cc @@ -0,0 +1,463 @@ +// -*- mode: c++; c-basic-offset:4 -*- + +// This file is part of the BES component of the Hyrax Data Server. + +// Copyright (c) 2023 OPeNDAP, Inc. +// Author: James Gallagher +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. + +#include "config.h" + +#include + +#include "BESUtil.h" +#include "TheBESKeys.h" +#include "BESContextManager.h" +#include "BESInternalError.h" + +#include "NgapNames.h" +#include "NgapContainer.h" +#include "NgapRequestHandler.h" + +#include "run_tests_cppunit.h" +#include "test_config.h" + +using namespace std; + +#define prolog string("NgapContainerTest::").append(__func__).append("() - ") + +namespace ngap { + +class NgapContainerTest: public CppUnit::TestFixture { + string d_cache_dir = string(TEST_BUILD_DIR) + "/cache"; + +public: + // Called once before everything gets tested + NgapContainerTest() = default; + ~NgapContainerTest() override = default; + NgapContainerTest(const NgapContainerTest &src) = delete; + const NgapContainerTest &operator=(const NgapContainerTest & rhs) = delete; + + void set_bes_keys() const { + TheBESKeys::TheKeys()->set_key("BES.LogName", "./bes.log"); + TheBESKeys::TheKeys()->set_key("BES.Catalog.catalog.RootDirectory", "/tmp"); // any dir that exists will do + TheBESKeys::TheKeys()->set_key("BES.Catalog.catalog.TypeMatch", "any-value:will-do"); + TheBESKeys::TheKeys()->set_key("AllowedHosts", ".*"); + } + + void configure_ngap_handler() const { + NgapRequestHandler::d_use_dmrpp_cache = true; + NgapRequestHandler::d_dmrpp_file_cache_dir = d_cache_dir; + NgapRequestHandler::d_dmrpp_file_cache_size_mb = 100 * MEGABYTE; // MB + NgapRequestHandler::d_dmrpp_file_cache_purge_size_mb = 20 * MEGABYTE; // MB + NgapRequestHandler::d_dmrpp_file_cache.initialize(NgapRequestHandler::d_dmrpp_file_cache_dir, + NgapRequestHandler::d_dmrpp_file_cache_size_mb, + NgapRequestHandler::d_dmrpp_file_cache_purge_size_mb); + } + + // Delete the cache dir after each test; really only needed for the + // tests toward the end of the suite that test the FileCache. + void tearDown() override { + struct stat sb; + if (stat(d_cache_dir.c_str(), &sb) == 0) { + if (S_ISDIR(sb.st_mode)) { + // remove the cache dir + string cmd = "rm -rf " + d_cache_dir; + int ret = system(cmd.c_str()); + if (ret != 0) { + CPPUNIT_FAIL("Failed to remove cache dir: " + d_cache_dir + '\n'); + } + } + } + } + + void test_inject_data_url_default() { + NgapContainer container; + CPPUNIT_ASSERT_MESSAGE("The default value should be false", !container.inject_data_url()); + } + + void test_inject_data_url_set() { + TheBESKeys::TheKeys()->set_key(NGAP_INJECT_DATA_URL_KEY, "true"); + NgapContainer container; + CPPUNIT_ASSERT_MESSAGE("The default value should be true", container.inject_data_url()); + } + + void test_get_content_filters_default() { + TheBESKeys::TheKeys()->set_key(NGAP_INJECT_DATA_URL_KEY, "false"); // clear this to the default + NgapContainer container; + map> content_filters; + bool do_content_filtering = container.get_daac_content_filters(content_filters); + CPPUNIT_ASSERT_MESSAGE("The without setting the key, 'do_content_filtering' should be false", !do_content_filtering); + CPPUNIT_ASSERT_MESSAGE("The content_filters v/r parameter should be empty (unaltered)", content_filters.empty()); + } + + void test_get_content_filters_set() { + TheBESKeys::TheKeys()->set_key(NGAP_INJECT_DATA_URL_KEY, "true"); // clear this to the default + map> content_filters; + NgapContainer container; + container.set_real_name("https://foo/bar.h5"); + + bool do_content_filtering = container.get_daac_content_filters(content_filters); + CPPUNIT_ASSERT_MESSAGE("The key is set, 'do_content_filtering' should be tru", do_content_filtering); + CPPUNIT_ASSERT_MESSAGE("The content_filters v/r parameter should have the filter values", !content_filters.empty()); + + if (debug) + for (auto const &p: content_filters) { cerr << "{" << p.first << ": " << p.second << "}\n"; } + + CPPUNIT_ASSERT_MESSAGE("The content_filters two key/value pairs", content_filters.size() == 2); + string key_1 = R"(href="OPeNDAP_DMRpp_DATA_ACCESS_URL")"; + CPPUNIT_ASSERT_MESSAGE("The content_filters missing a value", content_filters.find(key_1) != content_filters.end()); + string key_2 = R"(href="OPeNDAP_DMRpp_MISSING_DATA_ACCESS_URL")"; + CPPUNIT_ASSERT_MESSAGE("The content_filters missing a value", content_filters.find(key_2) != content_filters.end()); + + CPPUNIT_ASSERT_MESSAGE("The content_filters incorrect value", content_filters[key_1] == R"(href="https://foo/bar.h5" dmrpp:trust="true")"); + CPPUNIT_ASSERT_MESSAGE("The content_filters incorrect value", content_filters[key_2] == R"(href="https://foo/bar.h5.missing" dmrpp:trust="true")"); + } + + // This tests if a map the is not empty is first cleared before values are added. + void test_get_content_filters_reused_map() { + TheBESKeys::TheKeys()->set_key(NGAP_INJECT_DATA_URL_KEY, "true"); // clear this to the default + map> content_filters; + // make the content_filters 'used' + content_filters["foo"] = "bar"; + content_filters["baz"] = "clyde"; + NgapContainer container; + container.set_real_name("https://foo/bar.h5"); + + bool do_content_filtering = container.get_daac_content_filters(content_filters); + CPPUNIT_ASSERT_MESSAGE("The key is set, 'do_content_filtering' should be true", do_content_filtering); + CPPUNIT_ASSERT_MESSAGE("The content_filters v/r parameter should have the filter values", !content_filters.empty()); + + if (debug) + for (auto const &p: content_filters) { cerr << "{" << p.first << ": " << p.second << "}\n"; } + + CPPUNIT_ASSERT_MESSAGE("The content_filters two key/value pairs", content_filters.size() == 2); + string key_1 = R"(href="OPeNDAP_DMRpp_DATA_ACCESS_URL")"; + CPPUNIT_ASSERT_MESSAGE("The content_filters missing a value", content_filters.find(key_1) != content_filters.end()); + string key_2 = R"(href="OPeNDAP_DMRpp_MISSING_DATA_ACCESS_URL")"; + CPPUNIT_ASSERT_MESSAGE("The content_filters missing a value", content_filters.find(key_2) != content_filters.end()); + + CPPUNIT_ASSERT_MESSAGE("The content_filters incorrect value", content_filters[key_1] == R"(href="https://foo/bar.h5" dmrpp:trust="true")"); + CPPUNIT_ASSERT_MESSAGE("The content_filters incorrect value", content_filters[key_2] == R"(href="https://foo/bar.h5.missing" dmrpp:trust="true")"); + } + + void test_filter_response() { + TheBESKeys::TheKeys()->set_key(NGAP_INJECT_DATA_URL_KEY, "true"); // clear this to the default + map> content_filters; + NgapContainer container; + container.set_real_name("https://foo/bar.h5"); + + bool do_content_filtering = container.get_daac_content_filters(content_filters); + CPPUNIT_ASSERT_MESSAGE("The key is set, 'do_content_filtering' should be true", do_content_filtering); + + string xml_content = R"()"; + DBG(cerr << "Before filtering: " << xml_content << '\n'); + container.filter_response(content_filters, xml_content); + DBG(cerr << "... after filtering: " << xml_content << '\n'); + CPPUNIT_ASSERT_MESSAGE("Value1 not replaced", xml_content.find(R"(href="https://foo/bar.h5" dmrpp:trust="true")") != string::npos); + CPPUNIT_ASSERT_MESSAGE("Value2 not replaced", xml_content.find(R"(href="https://foo/bar.h5.missing" dmrpp:trust="true")") != string::npos); + } + + void test_set_real_name_using_cmr_or_cache_using_cmr() { + const string provider_name = "GHRC_DAAC"; + const string collection_concept_id ="C1996541017-GHRC_DAAC"; + const string granule_name = "amsua15_2020.028_12915_1139_1324_WI.nc"; + + const string resty_path = "providers/" + provider_name + "/concepts/" + collection_concept_id + "/granules/" + granule_name; + + set_bes_keys(); + + NgapRequestHandler::d_use_cmr_cache = true; + + NgapContainer container; + container.set_real_name(resty_path); + container.set_real_name_using_cmr_or_cache(); + + const string expected = "https://data.ghrc.earthdata.nasa.gov/ghrcw-protected/amsua15sp__1/amsu-a/noaa-15/data/nc/2020/0128/amsua15_2020.028_12915_1139_1324_WI.nc"; + CPPUNIT_ASSERT_MESSAGE("Expected URL not returned", container.get_real_name() == expected); + } + + void test_set_real_name_using_cmr_or_cache_using_cache() { + const string provider_name = "GHRC_DAAC"; + const string collection_concept_id ="C1996541017-GHRC_DAAC"; + const string granule_name = "amsua15_2020.028_12915_1139_1324_WI.nc"; + + const string resty_path = "providers/" + provider_name + "/concepts/" + collection_concept_id + "/granules/" + granule_name; + + set_bes_keys(); + + NgapRequestHandler::d_use_cmr_cache = true; + + const string uid_value = "bugsbunny"; + BESContextManager::TheManager()->set_context("uid", uid_value); + + // this ctor sets ngap_path, needed by set_real_name_using_cmr_or_cache(). + NgapContainer container("c", resty_path, "ngap"); + container.set_real_name_using_cmr_or_cache(); + + const string expected = "https://data.ghrc.earthdata.nasa.gov/ghrcw-protected/amsua15sp__1/amsu-a/noaa-15/data/nc/2020/0128/amsua15_2020.028_12915_1139_1324_WI.nc"; + string cache_value; + bool found = NgapRequestHandler::d_cmr_mem_cache.get(resty_path + ":" + uid_value, cache_value); + + CPPUNIT_ASSERT_MESSAGE("Expected URL from CMR not cached", found); + CPPUNIT_ASSERT_MESSAGE("Expected URL from CMR not cached", cache_value == expected); + } + + void test_set_real_name_using_cmr_or_cache_using_cache_default_ctor() { + const string provider_name = "GHRC_DAAC"; + const string collection_concept_id ="C1996541017-GHRC_DAAC"; + const string granule_name = "amsua15_2020.028_12915_1139_1324_WI.nc"; + + const string resty_path = "providers/" + provider_name + "/concepts/" + collection_concept_id + "/granules/" + granule_name; + + set_bes_keys(); + + NgapRequestHandler::d_use_cmr_cache = true; + + const string uid_value = "bugsbunny"; + BESContextManager::TheManager()->set_context("uid", uid_value); + + // this ctor does not set ngap_path, so use the setter. + NgapContainer container; + container.set_ngap_path(resty_path); + container.set_real_name(resty_path); + container.set_real_name_using_cmr_or_cache(); + + const string expected = "https://data.ghrc.earthdata.nasa.gov/ghrcw-protected/amsua15sp__1/amsu-a/noaa-15/data/nc/2020/0128/amsua15_2020.028_12915_1139_1324_WI.nc"; + string cache_value; + bool found = NgapRequestHandler::d_cmr_mem_cache.get(resty_path + ":" + uid_value, cache_value); + + CPPUNIT_ASSERT_MESSAGE("Expected URL from CMR not cached", found); + CPPUNIT_ASSERT_MESSAGE("Expected URL from CMR not cached", cache_value == expected); + } + + void test_access() { + const string provider_name = "GHRC_DAAC"; + const string collection_concept_id ="C1996541017-GHRC_DAAC"; + const string granule_name = "amsua15_2020.028_12915_1139_1324_WI.nc"; + + const string resty_path = "providers/" + provider_name + "/concepts/" + collection_concept_id + "/granules/" + granule_name; + + set_bes_keys(); + + NgapRequestHandler::d_use_cmr_cache = true; + + configure_ngap_handler(); + + const string uid_value = "bugsbunny"; + BESContextManager::TheManager()->set_context("uid", uid_value); + const string token_value = "Bearer XYZ"; + BESContextManager::TheManager()->set_context("edl_auth_token", token_value); + + NgapContainer container; + container.set_ngap_path(resty_path); + container.set_real_name(resty_path); + string file_name; + CPPUNIT_ASSERT_THROW_MESSAGE("Expected NGAP to balk, requiring auth", file_name = container.access(), BESError); + } + + void test_get_dmrpp_from_cache_or_remote_source() { + const string real_path = "http://test.opendap.org/opendap/data/dmrpp/a2_local_twoD.h5"; + + set_bes_keys(); + + configure_ngap_handler(); + + NgapContainer container; + container.set_real_name(real_path); + string dmrpp_string; + CPPUNIT_ASSERT_MESSAGE("Getting the DMRPP should work", + container.get_dmrpp_from_cache_or_remote_source(dmrpp_string)); + CPPUNIT_ASSERT_MESSAGE("The file name should be set", !dmrpp_string.empty()); + CPPUNIT_ASSERT_MESSAGE("The file name should be the cache file name", + dmrpp_string.find("50 50") != string::npos); + } + + void test_get_dmrpp_from_cache_or_remote_source_twice() { + const string real_path = "http://test.opendap.org/opendap/data/dmrpp/a2_local_twoD.h5"; + + set_bes_keys(); + + configure_ngap_handler(); + + NgapContainer container; + container.set_real_name(real_path); + string dmrpp_string; + CPPUNIT_ASSERT_MESSAGE("Getting the DMRPP should work", + container.get_dmrpp_from_cache_or_remote_source(dmrpp_string)); + CPPUNIT_ASSERT_MESSAGE("The file name should be set", !dmrpp_string.empty()); + CPPUNIT_ASSERT_MESSAGE("The file name should be the cache file name", + dmrpp_string.find("50 50") != string::npos); + + CPPUNIT_ASSERT_MESSAGE("Getting the DMRPP should work", + container.get_dmrpp_from_cache_or_remote_source(dmrpp_string)); + CPPUNIT_ASSERT_MESSAGE("The file name should be set", !dmrpp_string.empty()); + CPPUNIT_ASSERT_MESSAGE("The file name should be the cache file name", + dmrpp_string.find("50 50") != string::npos); + } + + void test_get_dmrpp_from_cache_or_remote_source_two_containers() { + const string real_path = "http://test.opendap.org/opendap/data/dmrpp/a2_local_twoD.h5"; + + set_bes_keys(); + + configure_ngap_handler(); + + NgapContainer container; + container.set_real_name(real_path); + string dmrpp_string; + CPPUNIT_ASSERT_MESSAGE("Getting the DMRPP should work", + container.get_dmrpp_from_cache_or_remote_source(dmrpp_string)); + CPPUNIT_ASSERT_MESSAGE("The file name should be set", !dmrpp_string.empty()); + CPPUNIT_ASSERT_MESSAGE("The file name should be the cache file name", + dmrpp_string.find("50 50") != string::npos); + + NgapContainer container2; + container2.set_real_name(real_path); + string dmrpp_string2; + CPPUNIT_ASSERT_MESSAGE("Getting the DMRPP should work", + container2.get_dmrpp_from_cache_or_remote_source(dmrpp_string2)); + CPPUNIT_ASSERT_MESSAGE("The file name should be set", !dmrpp_string2.empty()); + CPPUNIT_ASSERT_MESSAGE("The file name should be the cache file name", + dmrpp_string2.find("50 50") != string::npos); + } + + void test_get_dmrpp_from_cache_or_remote_source_clean_mem_cache() { + const string real_path = "http://test.opendap.org/opendap/data/dmrpp/a2_local_twoD.h5"; + + set_bes_keys(); + + configure_ngap_handler(); + + NgapContainer container; + container.set_real_name(real_path); + string dmrpp_string; + CPPUNIT_ASSERT_MESSAGE("Getting the DMRPP should work", + container.get_dmrpp_from_cache_or_remote_source(dmrpp_string)); + CPPUNIT_ASSERT_MESSAGE("The file name should be set", !dmrpp_string.empty()); + CPPUNIT_ASSERT_MESSAGE("The file name should be the cache file name", + dmrpp_string.find("50 50") != string::npos); + + NgapRequestHandler::d_dmrpp_mem_cache.clear(); + + NgapContainer container2; + container2.set_real_name(real_path); + string dmrpp_string2; + CPPUNIT_ASSERT_MESSAGE("Getting the DMRPP should work", + container2.get_dmrpp_from_cache_or_remote_source(dmrpp_string2)); + CPPUNIT_ASSERT_MESSAGE("The file name should be set", !dmrpp_string2.empty()); + CPPUNIT_ASSERT_MESSAGE("The file name should be the cache file name", + dmrpp_string2.find("50 50") != string::npos); + } + + // This version tests that when a DMR++ is not in the mem cache and is pulled + // from the file cache, it is put in the memory cache so the next access will + // find it in the mem cache + void test_get_dmrpp_from_cache_or_remote_source_clean_mem_cache_2() { + const string real_path = "http://test.opendap.org/opendap/data/dmrpp/a2_local_twoD.h5"; + + set_bes_keys(); + + + NgapContainer container; + container.set_real_name(real_path); + string dmrpp_string; + CPPUNIT_ASSERT_MESSAGE("Getting the DMRPP should work", + container.get_dmrpp_from_cache_or_remote_source(dmrpp_string)); + CPPUNIT_ASSERT_MESSAGE("The file name should be set", !dmrpp_string.empty()); + CPPUNIT_ASSERT_MESSAGE("The file name should be the cache file name", + dmrpp_string.find("50 50") != string::npos); + + NgapRequestHandler::d_dmrpp_mem_cache.clear(); + + NgapContainer container2; + container2.set_real_name(real_path); + string dmrpp_string2; + CPPUNIT_ASSERT_MESSAGE("Getting the DMRPP should work", + container2.get_dmrpp_from_cache_or_remote_source(dmrpp_string2)); + CPPUNIT_ASSERT_MESSAGE("The file name should be set", !dmrpp_string2.empty()); + CPPUNIT_ASSERT_MESSAGE("The file name should be the cache file name", + dmrpp_string2.find("50 50") != string::npos); + + NgapContainer container3; + container3.set_real_name(real_path); + string dmrpp_string3; + CPPUNIT_ASSERT_MESSAGE("Getting the DMRPP should work", + container3.get_dmrpp_from_cache_or_remote_source(dmrpp_string3)); + CPPUNIT_ASSERT_MESSAGE("The file name should be set", !dmrpp_string3.empty()); + CPPUNIT_ASSERT_MESSAGE("The file name should be the cache file name", + dmrpp_string3.find("50 50") != string::npos); + } + + void test_get_dmrpp_from_cache_or_remote_source_twice_no_cache() { + const string real_path = "http://test.opendap.org/opendap/data/dmrpp/a2_local_twoD.h5"; + + set_bes_keys(); + + NgapRequestHandler::d_use_dmrpp_cache = false; + + NgapContainer container; + container.set_real_name(real_path); + string dmrpp_string; + CPPUNIT_ASSERT_MESSAGE("Getting the DMRPP should work", + container.get_dmrpp_from_cache_or_remote_source(dmrpp_string)); + CPPUNIT_ASSERT_MESSAGE("The file name should be set", !dmrpp_string.empty()); + CPPUNIT_ASSERT_MESSAGE("The file name should be the cache file name", + dmrpp_string.find("50 50") != string::npos); + + CPPUNIT_ASSERT_MESSAGE("Getting the DMRPP should work", + container.get_dmrpp_from_cache_or_remote_source(dmrpp_string)); + CPPUNIT_ASSERT_MESSAGE("The file name should be set", !dmrpp_string.empty()); + CPPUNIT_ASSERT_MESSAGE("The file name should be the cache file name", + dmrpp_string.find("50 50") != string::npos); + } + + CPPUNIT_TEST_SUITE( NgapContainerTest ); + + CPPUNIT_TEST(test_inject_data_url_default); + CPPUNIT_TEST(test_inject_data_url_set); + CPPUNIT_TEST(test_get_content_filters_default); + CPPUNIT_TEST(test_get_content_filters_set); + CPPUNIT_TEST(test_get_content_filters_reused_map); + CPPUNIT_TEST(test_filter_response); + + CPPUNIT_TEST(test_set_real_name_using_cmr_or_cache_using_cmr); + CPPUNIT_TEST(test_set_real_name_using_cmr_or_cache_using_cache); + CPPUNIT_TEST(test_set_real_name_using_cmr_or_cache_using_cache_default_ctor); + + CPPUNIT_TEST(test_access); + CPPUNIT_TEST(test_get_dmrpp_from_cache_or_remote_source); + CPPUNIT_TEST(test_get_dmrpp_from_cache_or_remote_source_twice); + CPPUNIT_TEST(test_get_dmrpp_from_cache_or_remote_source_two_containers); + CPPUNIT_TEST(test_get_dmrpp_from_cache_or_remote_source_twice_no_cache); + CPPUNIT_TEST(test_get_dmrpp_from_cache_or_remote_source_clean_mem_cache_2); + CPPUNIT_TEST(test_get_dmrpp_from_cache_or_remote_source_clean_mem_cache); + + CPPUNIT_TEST_SUITE_END(); +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(NgapContainerTest); + +} // namespace dmrpp + +int main(int argc, char*argv[]) +{ + bool status = bes_run_tests(argc, argv, "cerr,ngap,cache"); + + return status ? 0 : 1; +} diff --git a/retired/modules/ngap_module/unit-tests/NgapOwnedContainerTest b/retired/modules/ngap_module/unit-tests/NgapOwnedContainerTest new file mode 100755 index 0000000000..b34efc4290 --- /dev/null +++ b/retired/modules/ngap_module/unit-tests/NgapOwnedContainerTest @@ -0,0 +1,210 @@ +#! /bin/sh + +# NgapOwnedContainerTest - temporary wrapper script for .libs/NgapOwnedContainerTest +# Generated by libtool (GNU libtool) 2.5.4 +# +# The NgapOwnedContainerTest program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s|\([`"$\\]\)|\\\1|g' + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command="" + +# This environment variable determines our operation mode. +if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then + # install mode needs the following variables: + generated_by_libtool_version='2.5.4' + notinst_deplibs=' /Users/jimg/src/opendap/hyrax/bes/dispatch/libbes_dispatch.la' +else + # When we are sourced in execute mode, $file and $ECHO are already set. + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + file="$0" + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + ECHO="printf %s\\n" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ that is used only on +# windows platforms, and (c) all begin with the string --lt- +# (application programs are unlikely to have options that match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's ../../../libtool value, followed by no. +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=$0 + shift + for lt_opt + do + case "$lt_opt" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%/[^/]*$%%'` + test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=. + lt_dump_F=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%^.*/%%'` + cat "$lt_dump_D/$lt_dump_F" + exit 0 + ;; + --lt-*) + $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n "$lt_option_debug"; then + echo "NgapOwnedContainerTest:NgapOwnedContainerTest:$LINENO: libtool wrapper (GNU libtool) 2.5.4" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + $ECHO "NgapOwnedContainerTest:NgapOwnedContainerTest:$LINENO: newargv[$lt_dump_args_N]: $lt_arg" + lt_dump_args_N=`expr $lt_dump_args_N + 1` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ + + if test -n "$lt_option_debug"; then + $ECHO "NgapOwnedContainerTest:NgapOwnedContainerTest:$LINENO: newargv[0]: $progdir/$program" 1>&2 + func_lt_dump_args ${1+"$@"} 1>&2 + fi + exec "$progdir/$program" ${1+"$@"} + + $ECHO "$0: cannot exec $program $*" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from $@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case " $* " in + *\ --lt-*) + for lt_wr_arg + do + case $lt_wr_arg in + --lt-*) ;; + *) set x "$@" "$lt_wr_arg"; shift;; + esac + shift + done ;; + esac + func_exec_program_core ${1+"$@"} +} + + # Parse options + func_parse_lt_options "$0" ${1+"$@"} + + # Find the directory that this script lives in. + thisdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'` + test "x$thisdir" = "x$file" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=`ls -ld "$file" | /usr/bin/sed -n 's/.*-> //p'` + while test -n "$file"; do + destdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'` + + # If there was a directory component, then change thisdir. + if test "x$destdir" != "x$file"; then + case "$destdir" in + [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;; + *) thisdir="$thisdir/$destdir" ;; + esac + fi + + file=`$ECHO "$file" | /usr/bin/sed 's%^.*/%%'` + file=`ls -ld "$thisdir/$file" | /usr/bin/sed -n 's/.*-> //p'` + done + + # Usually 'no', except on cygwin/mingw/windows when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no + if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then + # special case for '.' + if test "$thisdir" = "."; then + thisdir=`pwd` + fi + # remove .libs from thisdir + case "$thisdir" in + *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /usr/bin/sed 's%[\\/][^\\/]*$%%'` ;; + .libs ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=`cd "$thisdir" && pwd` + test -n "$absdir" && thisdir="$absdir" + + program='NgapOwnedContainerTest' + progdir="$thisdir/.libs" + + + if test -f "$progdir/$program"; then + # Add our own library path to DYLD_LIBRARY_PATH + DYLD_LIBRARY_PATH="/Users/jimg/src/opendap/hyrax/bes/dispatch/.libs:$DYLD_LIBRARY_PATH" + + # Some systems cannot cope with colon-terminated DYLD_LIBRARY_PATH + # The second colon is a workaround for a bug in BeOS R4 sed + DYLD_LIBRARY_PATH=`$ECHO "$DYLD_LIBRARY_PATH" | /usr/bin/sed 's/::*$//'` + + export DYLD_LIBRARY_PATH + + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + # Run the actual program with our arguments. + func_exec_program ${1+"$@"} + fi + else + # The program doesn't exist. + $ECHO "$0: error: '$progdir/$program' does not exist" 1>&2 + $ECHO "This script is just a wrapper for $program." 1>&2 + $ECHO "See the libtool documentation for more information." 1>&2 + exit 1 + fi +fi diff --git a/retired/modules/ngap_module/unit-tests/NgapOwnedContainerTest.cc b/retired/modules/ngap_module/unit-tests/NgapOwnedContainerTest.cc new file mode 100644 index 0000000000..01ae6b8091 --- /dev/null +++ b/retired/modules/ngap_module/unit-tests/NgapOwnedContainerTest.cc @@ -0,0 +1,382 @@ +// -*- mode: c++; c-basic-offset:4 -*- + +// This file is part of the BES component of the Hyrax Data Server. + +// Copyright (c) 2023 OPeNDAP, Inc. +// Author: James Gallagher +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. + +#include "config.h" + +#include + +#include "BESUtil.h" +#include "TheBESKeys.h" +#include "BESContextManager.h" +#include "BESInternalError.h" +#include "BESSyntaxUserError.h" + +#include "NgapOwnedContainer.h" +#include "NgapRequestHandler.h" + +#include "run_tests_cppunit.h" +#include "test_config.h" + +using namespace std; + +auto const DMRPP_LOCATION = "https://dmrpp-sit-poc.s3.amazonaws.com"; +auto const DMRPP_TEST_BUCKET_OPENDAP_AWS = "https://s3.amazonaws.com/cloudydap"; +auto const TEST_DATA_LOCATION = string("file://") + TEST_SRC_DIR; + +#define TEST_NAME DBG(cerr << __PRETTY_FUNCTION__ << "()\n") +#define prolog string("NgapOwnedContainerTest::").append(__func__).append("() - ") + +namespace ngap { + +class NgapOwnedContainerTest: public CppUnit::TestFixture { + string d_cache_dir = string(TEST_BUILD_DIR) + "/owned-cache"; + +public: + // Called once before everything gets tested + NgapOwnedContainerTest() = default; + ~NgapOwnedContainerTest() override = default; + NgapOwnedContainerTest(const NgapOwnedContainerTest &src) = delete; + const NgapOwnedContainerTest &operator=(const NgapOwnedContainerTest & rhs) = delete; + + void set_bes_keys() const { + TheBESKeys::TheKeys()->set_key("BES.LogName", "./bes.log"); + TheBESKeys::TheKeys()->set_key("BES.Catalog.catalog.RootDirectory", "/tmp"); // any dir that exists will do + TheBESKeys::TheKeys()->set_key("BES.Catalog.catalog.TypeMatch", "any-value:will-do"); + TheBESKeys::TheKeys()->set_key("AllowedHosts", ".*"); + // Use the env var creds for real access to DMR++ in S3. This works + // only for a given URL. On my machine that is https://s3.amazonaws.com/cloudydap. + // jhrg 5/17/24 + TheBESKeys::TheKeys()->set_key("CredentialsManager.config", "ENV_CREDS"); + } + + void configure_ngap_handler() const { + NgapRequestHandler::d_use_dmrpp_cache = true; + NgapRequestHandler::d_dmrpp_file_cache_dir = d_cache_dir; // This is made if it doesn't exist + NgapRequestHandler::d_dmrpp_file_cache_size_mb = 100 * MEGABYTE; // MB + NgapRequestHandler::d_dmrpp_file_cache_purge_size_mb = 20 * MEGABYTE; // MB + NgapRequestHandler::d_dmrpp_file_cache.initialize(NgapRequestHandler::d_dmrpp_file_cache_dir, + NgapRequestHandler::d_dmrpp_file_cache_size_mb, + NgapRequestHandler::d_dmrpp_file_cache_purge_size_mb); + NgapRequestHandler::d_dmrpp_mem_cache.initialize(100, 20); + } + + void setUp() override { + set_bes_keys(); + configure_ngap_handler(); + } + + // Delete the cache dir after each test; really only needed for the + // tests toward the end of the suite that test the FileCache. + void tearDown() override { + NgapRequestHandler::d_dmrpp_file_cache.clear(); + NgapRequestHandler::d_dmrpp_mem_cache.clear(); + } + + void test_file_to_string() { + TEST_NAME; + string content; + string file_name = string(TEST_SRC_DIR) + "/data/chunked_enum.h5.dmrpp"; + int fd = open(file_name.c_str(), O_RDONLY); + CPPUNIT_ASSERT_MESSAGE("The file " + file_name + " should be open", fd != -1); + CPPUNIT_ASSERT_MESSAGE("The file should be read", NgapOwnedContainer::file_to_string(fd, content)); + CPPUNIT_ASSERT_MESSAGE("The file should be closed", close(fd) == 0); + CPPUNIT_ASSERT_MESSAGE("The file should have content", !content.empty()); + DBG2(cerr << "Content length : " << content.size() << '\n'); + CPPUNIT_ASSERT_MESSAGE("The file should be > 1k (was" + to_string(content.size()) + ").", content.size() > 1'000); + } + + void test_file_to_string_bigger_than_buffer() { + TEST_NAME; + string content; + string file_name = string(TEST_SRC_DIR) + "/NgapApiTest.cc"; // ~16k while the buffer is 4k + int fd = open(file_name.c_str(), O_RDONLY); + CPPUNIT_ASSERT_MESSAGE("The file " + file_name + " should be open", fd != -1); + CPPUNIT_ASSERT_MESSAGE("The file should be read", NgapOwnedContainer::file_to_string(fd, content)); + CPPUNIT_ASSERT_MESSAGE("The file should be closed", close(fd) == 0); + CPPUNIT_ASSERT_MESSAGE("The file should have content", !content.empty()); + DBG2(cerr << "Content length : " << content.size() << '\n'); + CPPUNIT_ASSERT_MESSAGE("The file should be > 16k (was " + to_string(content.size()) + ").", content.size() > 15'000); + } + + void test_file_to_string_file_not_open() { + TEST_NAME; + string content; + int fd = -1; + CPPUNIT_ASSERT_MESSAGE("The file descriptor should be -1", fd == -1); + CPPUNIT_ASSERT_MESSAGE("The function should return false", !NgapOwnedContainer::file_to_string(fd, content)); + CPPUNIT_ASSERT_MESSAGE("The string should be empty", content.empty()); + } + + void test_build_dmrpp_url_to_owned_bucket() { + TEST_NAME; + string rest_path = "collections/C1996541017-GHRC_DAAC/granules/amsua15_2020.028_12915_1139_1324_WI.nc"; + string expected = "https://dmrpp-sit-poc.s3.amazonaws.com/C1996541017-GHRC_DAAC/amsua15_2020.028_12915_1139_1324_WI.nc.dmrpp"; + string actual = NgapOwnedContainer::build_dmrpp_url_to_owned_bucket(rest_path, DMRPP_LOCATION); + CPPUNIT_ASSERT_MESSAGE("The URL should be built (got: " + actual + " expected: " + expected + ").", + actual == expected); + } + + void test_build_dmrpp_url_to_owned_bucket_bad_path() { + TEST_NAME; + string rest_path = "collections/C1996541017-GHRC_DAAC/granules/amsua15_2020.028_12915_1139_1324_WI.nc/extra"; + CPPUNIT_ASSERT_THROW_MESSAGE("The function should throw", + NgapOwnedContainer::build_dmrpp_url_to_owned_bucket(rest_path, DMRPP_LOCATION), BESSyntaxUserError); + } + + void test_build_dmrpp_url_to_owned_bucket_bad_path_2() { + TEST_NAME; + string rest_path = "C1996541017-GHRC_DAAC/granules/amsua15_2020.028_12915_1139_1324_WI.nc"; + CPPUNIT_ASSERT_THROW_MESSAGE("The function should throw", + NgapOwnedContainer::build_dmrpp_url_to_owned_bucket(rest_path, DMRPP_LOCATION), BESSyntaxUserError); + } + + void test_build_dmrpp_url_to_owned_bucket_bad_path_3() { + TEST_NAME; + string rest_path = "collections/C1996541017-GHRC_DAAC/amsua15_2020.028_12915_1139_1324_WI.nc"; + CPPUNIT_ASSERT_THROW_MESSAGE("The function should throw", + NgapOwnedContainer::build_dmrpp_url_to_owned_bucket(rest_path, DMRPP_LOCATION), BESSyntaxUserError); + } + + void test_build_dmrpp_url_to_owned_bucket_bad_path_4() { + TEST_NAME; + string rest_path = "C1996541017-GHRC_DAAC/amsua15_2020.028_12915_1139_1324_WI.nc"; + CPPUNIT_ASSERT_THROW_MESSAGE("The function should throw", + NgapOwnedContainer::build_dmrpp_url_to_owned_bucket(rest_path, DMRPP_LOCATION), BESSyntaxUserError); + } + void test_build_dmrpp_url_to_owned_bucket_bad_path_5() { + TEST_NAME; + string rest_path = ""; + CPPUNIT_ASSERT_THROW_MESSAGE("The function should throw", + NgapOwnedContainer::build_dmrpp_url_to_owned_bucket(rest_path, DMRPP_LOCATION), BESSyntaxUserError); + } + + void test_item_in_cache() { + TEST_NAME; + string dmrpp_string; + NgapOwnedContainer container; + container.set_real_name("/data/dmrpp/a2_local_twoD.h5"); + CPPUNIT_ASSERT_MESSAGE("The item should not be in the cache", !container.get_item_from_dmrpp_cache(dmrpp_string)); + CPPUNIT_ASSERT_MESSAGE("The item should empty", dmrpp_string.empty()); + } + + void test_cache_item() { + TEST_NAME; + string dmrpp_string = "cached DMR++"; + NgapOwnedContainer container; + container.set_real_name("/data/dmrpp/a2_local_twoD.h5"); + CPPUNIT_ASSERT_MESSAGE("The item should be added to the cache", container.put_item_in_dmrpp_cache(dmrpp_string)); + string cached_value; + CPPUNIT_ASSERT_MESSAGE("The item should be in the cache", container.get_item_from_dmrpp_cache(cached_value)); + CPPUNIT_ASSERT_MESSAGE("The item should be the same", cached_value == dmrpp_string); + } + + void test_cache_item_stomp() { + TEST_NAME; + string dmrpp_string = "cached DMR++"; + NgapOwnedContainer container; + container.set_real_name("/data/dmrpp/a2_local_twoD.h5"); + CPPUNIT_ASSERT_MESSAGE("The item should be added to the cache", container.put_item_in_dmrpp_cache(dmrpp_string)); + string cached_value; + CPPUNIT_ASSERT_MESSAGE("The item should be in the cache", container.get_item_from_dmrpp_cache(cached_value)); + CPPUNIT_ASSERT_MESSAGE("The item should be the same", cached_value == dmrpp_string); + + // now 'stomp' on the cached item + CPPUNIT_ASSERT_MESSAGE("The item should not be added to the cache", !container.put_item_in_dmrpp_cache( + "Over-written cache item")); + CPPUNIT_ASSERT_MESSAGE("The item should be in the cache", container.get_item_from_dmrpp_cache(cached_value)); + DBG2(cerr << "Cached value: " << cached_value << '\n'); + CPPUNIT_ASSERT_MESSAGE("The item should be the same", cached_value == dmrpp_string); + } + + void test_get_dmrpp_from_cache_or_remote_source() { + TEST_NAME; + string dmrpp_string; + NgapOwnedContainer container; + // The REST path will become data/d_int.h5 + container.set_real_name("collections/data/granules/d_int.h5"); + // Set the location of the data as a file:// URL for this test. + container.set_data_source_location(TEST_DATA_LOCATION); + CPPUNIT_ASSERT_MESSAGE("The DMR++ should be found", container.get_dmrpp_from_cache_or_remote_source(dmrpp_string)); + DBG2(cerr << "DMR++: " << dmrpp_string << '\n'); + CPPUNIT_ASSERT_MESSAGE("The DMR++ should be in the string", !dmrpp_string.empty()); + } + + void test_get_dmrpp_from_cache_or_remote_source_cache_consistency() { + TEST_NAME; + string dmrpp_string; + NgapOwnedContainer container; + // The REST path will become data/d_int.h5 + string real_name = "collections/data/granules/d_int.h5"; + container.set_real_name(real_name); + // Set the location of the data as a file:// URL for this test. + container.set_data_source_location(TEST_DATA_LOCATION); + + string cache_value; + int status = container.get_item_from_dmrpp_cache(cache_value); + CPPUNIT_ASSERT_MESSAGE("The DMR++ should not be in the cache (found: " + cache_value + ").", !status); + + CPPUNIT_ASSERT_MESSAGE("The DMR++ should be found", container.get_dmrpp_from_cache_or_remote_source(dmrpp_string)); + DBG2(cerr << "DMR++: " << dmrpp_string << '\n'); + CPPUNIT_ASSERT_MESSAGE("The DMR++ should be in the string", !dmrpp_string.empty()); + + CPPUNIT_ASSERT_MESSAGE("The DMR++ should be in the cache", container.get_item_from_dmrpp_cache(cache_value)); + CPPUNIT_ASSERT_MESSAGE("The DMR++ should be in the cached value", !cache_value.empty()); + } + + void test_get_dmrpp_from_cache_or_remote_source_test_both_caches() { + TEST_NAME; + string dmrpp_string; + NgapOwnedContainer container; + // The REST path will become data/d_int.h5 + string real_name = "collections/data/granules/d_int.h5"; + container.set_real_name(real_name); + // Set the location of the data as a file:// URL for this test. + container.set_data_source_location(TEST_DATA_LOCATION); + + string key = FileCache::hash_key(real_name); + FileCache::Item item; + bool result = NgapRequestHandler::d_dmrpp_file_cache.get(key, item, LOCK_SH); + CPPUNIT_ASSERT_MESSAGE("The DMR++ should not be in the file cache.", !result); + + string cache_value; + result = NgapRequestHandler::d_dmrpp_mem_cache.get(real_name, cache_value); + CPPUNIT_ASSERT_MESSAGE("The DMR++ should not be in the memory cache.", !result); + + CPPUNIT_ASSERT_MESSAGE("The DMR++ should be found", container.get_dmrpp_from_cache_or_remote_source(dmrpp_string)); + DBG2(cerr << "DMR++: " << dmrpp_string << '\n'); + CPPUNIT_ASSERT_MESSAGE("The DMR++ should be in the string", !dmrpp_string.empty()); + + result = NgapRequestHandler::d_dmrpp_file_cache.get(key, item, LOCK_SH); + CPPUNIT_ASSERT_MESSAGE("The DMR++ should not be in the file cache.", result); + + result = NgapRequestHandler::d_dmrpp_mem_cache.get(real_name, cache_value); + CPPUNIT_ASSERT_MESSAGE("The DMR++ should not be in the memory cache.", result); + } + + void test_get_dmrpp_from_cache_or_remote_source_test_cache_use() { + TEST_NAME; + string dmrpp_string; + NgapOwnedContainer container; + // The REST path will become data/d_int.h5 + container.set_real_name("collections/data/granules/d_int.h5"); + // Set the location of the data as a file:// URL for this test. + container.set_data_source_location(TEST_DATA_LOCATION); + + string cached_value; + int status = container.get_item_from_dmrpp_cache(cached_value); + CPPUNIT_ASSERT_MESSAGE("The DMR++ should not be in the cache (found: " + cached_value + ").", !status); + CPPUNIT_ASSERT_MESSAGE("The DMR++ should not be in the cached value", cached_value.empty()); + + CPPUNIT_ASSERT_MESSAGE("The DMR++ should be found", container.get_dmrpp_from_cache_or_remote_source(dmrpp_string)); + DBG2(cerr << "DMR++: " << dmrpp_string << '\n'); + CPPUNIT_ASSERT_MESSAGE("The DMR++ should be in the string", !dmrpp_string.empty()); + + CPPUNIT_ASSERT_MESSAGE("The DMR++ should be in the cache", container.get_dmrpp_from_cache_or_remote_source(cached_value)); + DBG2(cerr << "DMR++: " << cached_value << '\n'); + CPPUNIT_ASSERT_MESSAGE("The DMR++ should be in the cached value", !cached_value.empty()); + } + + void test_access() { + TEST_NAME; + + NgapOwnedContainer container; + // The REST path will become data/d_int.h5 + container.set_real_name("collections/data/granules/d_int.h5"); + // Set the location of the data as a file:// URL for this test. + container.set_data_source_location(TEST_DATA_LOCATION); + + string dmrpp = container.access(); + DBG2(cerr << "DMR++: " << dmrpp << '\n'); + CPPUNIT_ASSERT_MESSAGE("The DMR++ should be in the string", !dmrpp.empty()); + + string attrs = container.get_attributes(); + CPPUNIT_ASSERT_MESSAGE("The container attributes should be 'as-string'", attrs == "as-string"); + + CPPUNIT_ASSERT_MESSAGE("The container type should be 'dmrpp'", container.get_container_type() == "dmrpp"); + } + + void test_access_s3() { + TEST_NAME; + + if (getenv("CMAC_URL") == nullptr) { + DBG(cerr << "Skipping test_access_s3 because AWS_ACCESS_KEY_ID is not set.\n"); + return; + } + + NgapOwnedContainer container; + // The REST path will become ngap_owned/d_int.h5. This exists in the S3 bucket + // s3-module-test-bucket that DMRPP_TEST_BUCKET_OPENDAP_AWS points toward. jhrg 5/17/24 + container.set_real_name("collections/ngap_owned/granules/d_int.h5"); + // Set the location of the data as a file:// URL for this test. + container.set_data_source_location(DMRPP_TEST_BUCKET_OPENDAP_AWS); + + string dmrpp = container.access(); + DBG2(cerr << "DMR++: " << dmrpp << '\n'); + CPPUNIT_ASSERT_MESSAGE("The response should not be empty", !dmrpp.empty()); + string dmrpp_str = R"(dmrpp:href="https://s3.amazonaws.com/cloudydap/ngap_owned/d_int.h5")"; + CPPUNIT_ASSERT_MESSAGE("The response should be a DMR++ XML document", dmrpp.find(dmrpp_str) != string::npos); + + string attrs = container.get_attributes(); + CPPUNIT_ASSERT_MESSAGE("The container attributes should be 'as-string'", attrs == "as-string"); + + CPPUNIT_ASSERT_MESSAGE("The container type should be 'dmrpp'", container.get_container_type() == "dmrpp"); + } + + CPPUNIT_TEST_SUITE( NgapOwnedContainerTest ); + + CPPUNIT_TEST(test_file_to_string); + CPPUNIT_TEST(test_file_to_string_bigger_than_buffer); + CPPUNIT_TEST(test_file_to_string_file_not_open); + + CPPUNIT_TEST(test_build_dmrpp_url_to_owned_bucket); + CPPUNIT_TEST(test_build_dmrpp_url_to_owned_bucket_bad_path); + CPPUNIT_TEST(test_build_dmrpp_url_to_owned_bucket_bad_path_2); + CPPUNIT_TEST(test_build_dmrpp_url_to_owned_bucket_bad_path_3); + CPPUNIT_TEST(test_build_dmrpp_url_to_owned_bucket_bad_path_4); + CPPUNIT_TEST(test_build_dmrpp_url_to_owned_bucket_bad_path_5); + + CPPUNIT_TEST(test_item_in_cache); + CPPUNIT_TEST(test_cache_item); + CPPUNIT_TEST(test_cache_item_stomp); + + CPPUNIT_TEST(test_get_dmrpp_from_cache_or_remote_source); + CPPUNIT_TEST(test_get_dmrpp_from_cache_or_remote_source_cache_consistency); + CPPUNIT_TEST(test_get_dmrpp_from_cache_or_remote_source_test_both_caches); + CPPUNIT_TEST(test_get_dmrpp_from_cache_or_remote_source_test_cache_use); + + CPPUNIT_TEST(test_access); + CPPUNIT_TEST(test_access_s3); + + CPPUNIT_TEST_SUITE_END(); +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(NgapOwnedContainerTest); + +} // namespace dmrpp + +int main(int argc, char*argv[]) +{ + bool status = bes_run_tests(argc, argv, "cerr,ngap,cache"); + + return status ? 0 : 1; +} diff --git a/retired/modules/ngap_module/unit-tests/NgapRequestHandlerTest b/retired/modules/ngap_module/unit-tests/NgapRequestHandlerTest new file mode 100755 index 0000000000..f3592511d2 --- /dev/null +++ b/retired/modules/ngap_module/unit-tests/NgapRequestHandlerTest @@ -0,0 +1,210 @@ +#! /bin/sh + +# NgapRequestHandlerTest - temporary wrapper script for .libs/NgapRequestHandlerTest +# Generated by libtool (GNU libtool) 2.5.4 +# +# The NgapRequestHandlerTest program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s|\([`"$\\]\)|\\\1|g' + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command="" + +# This environment variable determines our operation mode. +if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then + # install mode needs the following variables: + generated_by_libtool_version='2.5.4' + notinst_deplibs=' /Users/jimg/src/opendap/hyrax/bes/dispatch/libbes_dispatch.la' +else + # When we are sourced in execute mode, $file and $ECHO are already set. + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + file="$0" + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + ECHO="printf %s\\n" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ that is used only on +# windows platforms, and (c) all begin with the string --lt- +# (application programs are unlikely to have options that match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's ../../../libtool value, followed by no. +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=$0 + shift + for lt_opt + do + case "$lt_opt" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%/[^/]*$%%'` + test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=. + lt_dump_F=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%^.*/%%'` + cat "$lt_dump_D/$lt_dump_F" + exit 0 + ;; + --lt-*) + $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n "$lt_option_debug"; then + echo "NgapRequestHandlerTest:NgapRequestHandlerTest:$LINENO: libtool wrapper (GNU libtool) 2.5.4" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + $ECHO "NgapRequestHandlerTest:NgapRequestHandlerTest:$LINENO: newargv[$lt_dump_args_N]: $lt_arg" + lt_dump_args_N=`expr $lt_dump_args_N + 1` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ + + if test -n "$lt_option_debug"; then + $ECHO "NgapRequestHandlerTest:NgapRequestHandlerTest:$LINENO: newargv[0]: $progdir/$program" 1>&2 + func_lt_dump_args ${1+"$@"} 1>&2 + fi + exec "$progdir/$program" ${1+"$@"} + + $ECHO "$0: cannot exec $program $*" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from $@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case " $* " in + *\ --lt-*) + for lt_wr_arg + do + case $lt_wr_arg in + --lt-*) ;; + *) set x "$@" "$lt_wr_arg"; shift;; + esac + shift + done ;; + esac + func_exec_program_core ${1+"$@"} +} + + # Parse options + func_parse_lt_options "$0" ${1+"$@"} + + # Find the directory that this script lives in. + thisdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'` + test "x$thisdir" = "x$file" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=`ls -ld "$file" | /usr/bin/sed -n 's/.*-> //p'` + while test -n "$file"; do + destdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'` + + # If there was a directory component, then change thisdir. + if test "x$destdir" != "x$file"; then + case "$destdir" in + [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;; + *) thisdir="$thisdir/$destdir" ;; + esac + fi + + file=`$ECHO "$file" | /usr/bin/sed 's%^.*/%%'` + file=`ls -ld "$thisdir/$file" | /usr/bin/sed -n 's/.*-> //p'` + done + + # Usually 'no', except on cygwin/mingw/windows when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no + if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then + # special case for '.' + if test "$thisdir" = "."; then + thisdir=`pwd` + fi + # remove .libs from thisdir + case "$thisdir" in + *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /usr/bin/sed 's%[\\/][^\\/]*$%%'` ;; + .libs ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=`cd "$thisdir" && pwd` + test -n "$absdir" && thisdir="$absdir" + + program='NgapRequestHandlerTest' + progdir="$thisdir/.libs" + + + if test -f "$progdir/$program"; then + # Add our own library path to DYLD_LIBRARY_PATH + DYLD_LIBRARY_PATH="/Users/jimg/src/opendap/hyrax/bes/dispatch/.libs:$DYLD_LIBRARY_PATH" + + # Some systems cannot cope with colon-terminated DYLD_LIBRARY_PATH + # The second colon is a workaround for a bug in BeOS R4 sed + DYLD_LIBRARY_PATH=`$ECHO "$DYLD_LIBRARY_PATH" | /usr/bin/sed 's/::*$//'` + + export DYLD_LIBRARY_PATH + + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + # Run the actual program with our arguments. + func_exec_program ${1+"$@"} + fi + else + # The program doesn't exist. + $ECHO "$0: error: '$progdir/$program' does not exist" 1>&2 + $ECHO "This script is just a wrapper for $program." 1>&2 + $ECHO "See the libtool documentation for more information." 1>&2 + exit 1 + fi +fi diff --git a/retired/modules/ngap_module/unit-tests/NgapRequestHandlerTest.cc b/retired/modules/ngap_module/unit-tests/NgapRequestHandlerTest.cc new file mode 100644 index 0000000000..0fb0b67651 --- /dev/null +++ b/retired/modules/ngap_module/unit-tests/NgapRequestHandlerTest.cc @@ -0,0 +1,144 @@ +// -*- mode: c++; c-basic-offset:4 -*- + +// This file is part of the BES component of the Hyrax Data Server. + +// Copyright (c) 2023 OPeNDAP, Inc. +// Author: James Gallagher +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. + +#include "config.h" + +#include + +#include "libdap/util.h" + +#include "BESUtil.h" +#include "TheBESKeys.h" +#include "NgapRequestHandler.h" + +#include "test_config.h" + +#include "run_tests_cppunit.h" + +using namespace std; + +#define prolog string("NgapRequestHandlerTest::").append(__func__).append("() - ") + +namespace ngap { + +class NgapRequestHandlerTest: public CppUnit::TestFixture { + unique_ptr d_rh = make_unique("test"); + +public: + // Called once before everything gets tested + NgapRequestHandlerTest() = default; + ~NgapRequestHandlerTest() override = default; + NgapRequestHandlerTest(const NgapRequestHandlerTest &src) = delete; + const NgapRequestHandlerTest &operator=(const NgapRequestHandlerTest & rhs) = delete; + + // setUp; Called before each test; not used. + + // tearDown; Called after each test; not used. + + void test_compiled_default_cache_keys() { + // Test the values without any conf file loaded. + CPPUNIT_ASSERT_MESSAGE("Expected the CMR cache to not be used by default", !NgapRequestHandler::d_use_cmr_cache); + CPPUNIT_ASSERT_MESSAGE("Expected the DMR++ cache to not be used by default", !NgapRequestHandler::d_use_dmrpp_cache); + + CPPUNIT_ASSERT_MESSAGE("Expected the CMR cache threshold to be 100", NgapRequestHandler::d_cmr_cache_size_items == 100); + CPPUNIT_ASSERT_MESSAGE("Expected the DMR++ cache threshold to be 100", NgapRequestHandler::d_dmrpp_mem_cache_size_items == 100); + CPPUNIT_ASSERT_MESSAGE("Expected the CMR cache space to be 20", NgapRequestHandler::d_cmr_cache_purge_items == 20); + CPPUNIT_ASSERT_MESSAGE("Expected the DMR++ cache space to be 20", NgapRequestHandler::d_dmrpp_mem_cache_purge_items == 20); + } + + void test_cmr_cache_disabled() { + TheBESKeys::TheKeys()->reload_keys(BESUtil::assemblePath(TEST_BUILD_DIR, "bes.cache.conf")); + + TheBESKeys::TheKeys()->set_key("NGAP.UseCMRCache", "false"); + + d_rh = make_unique("test_no_cmr_cache"); + + CPPUNIT_ASSERT_MESSAGE("Expected the CMR cache to be false", !NgapRequestHandler::d_use_cmr_cache); + CPPUNIT_ASSERT_MESSAGE("Expected the DMR++ cache to be used by default", NgapRequestHandler::d_use_dmrpp_cache); + + CPPUNIT_ASSERT_MESSAGE("Expected the CMR cache threshold to be 100", NgapRequestHandler::d_cmr_cache_size_items == 100); + CPPUNIT_ASSERT_MESSAGE("Expected the DMR++ cache threshold to be 100", NgapRequestHandler::d_dmrpp_mem_cache_size_items == 100); + CPPUNIT_ASSERT_MESSAGE("Expected the CMR cache space to be 20", NgapRequestHandler::d_cmr_cache_purge_items == 20); + CPPUNIT_ASSERT_MESSAGE("Expected the DMR++ cache space to be 20", NgapRequestHandler::d_dmrpp_mem_cache_purge_items == 20); + } + + void test_dmrpp_cache_disabled() { + TheBESKeys::TheKeys()->reload_keys(BESUtil::assemblePath(TEST_BUILD_DIR, "bes.cache.conf")); + TheBESKeys::TheKeys()->set_key("NGAP.UseDMRppCache", "false"); // NGAP.UseDMRppCache + + d_rh = make_unique("test_no_dmrpp_cache"); + + CPPUNIT_ASSERT_MESSAGE("Expected the CMR cache to be used by default", NgapRequestHandler::d_use_cmr_cache); + CPPUNIT_ASSERT_MESSAGE("Expected the DMR++ cache to be false", !NgapRequestHandler::d_use_dmrpp_cache); + + // These will still have the default values + CPPUNIT_ASSERT_MESSAGE("Expected the CMR cache threshold to be 100", NgapRequestHandler::d_cmr_cache_size_items == 100); + CPPUNIT_ASSERT_MESSAGE("Expected the DMR++ cache threshold to be 100", NgapRequestHandler::d_dmrpp_mem_cache_size_items == 100); + CPPUNIT_ASSERT_MESSAGE("Expected the CMR cache space to be 20", NgapRequestHandler::d_cmr_cache_purge_items == 20); + CPPUNIT_ASSERT_MESSAGE("Expected the DMR++ cache space to be 20", NgapRequestHandler::d_dmrpp_mem_cache_purge_items == 20); + } + + void test_custom_cache_params() { + TheBESKeys::TheKeys()->reload_keys(BESUtil::assemblePath(TEST_BUILD_DIR, "bes.cache.conf")); + + TheBESKeys::TheKeys()->set_key("NGAP.CMRCacheSize.Items", "17"); + TheBESKeys::TheKeys()->set_key("NGAP.CMRCachePurge.Items", "7"); + + TheBESKeys::TheKeys()->set_key("NGAP.DMRppCacheSize.Items", "17"); + TheBESKeys::TheKeys()->set_key("NGAP.DMRppCachePurge.Items", "7"); + + d_rh = make_unique("test_no_dmrpp_cache"); + + CPPUNIT_ASSERT_MESSAGE("Expected the CMR cache to be used by default", NgapRequestHandler::d_use_cmr_cache); + CPPUNIT_ASSERT_MESSAGE("Expected the DMR++ cache to be used by default", NgapRequestHandler::d_use_dmrpp_cache); + + // These will still have the default values + CPPUNIT_ASSERT_MESSAGE("Expected the CMR cache threshold to be 17", NgapRequestHandler::d_cmr_cache_size_items == 17); + CPPUNIT_ASSERT_MESSAGE("Expected the DMR++ cache threshold to be 17", NgapRequestHandler::d_dmrpp_mem_cache_size_items == 17); + CPPUNIT_ASSERT_MESSAGE("Expected the CMR cache space to be 7", NgapRequestHandler::d_cmr_cache_purge_items == 7); + CPPUNIT_ASSERT_MESSAGE("Expected the DMR++ cache space to be 7", NgapRequestHandler::d_dmrpp_mem_cache_purge_items == 7); + } + + CPPUNIT_TEST_SUITE( NgapRequestHandlerTest ); + + CPPUNIT_TEST(test_compiled_default_cache_keys); + + CPPUNIT_TEST(test_dmrpp_cache_disabled); + CPPUNIT_TEST(test_cmr_cache_disabled); + + CPPUNIT_TEST(test_custom_cache_params); + + CPPUNIT_TEST_SUITE_END(); +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(NgapRequestHandlerTest); + +} // namespace dmrpp + + +int main(int argc, char*argv[]) +{ + bool status = bes_run_tests(argc, argv, "cerr,ngap,cache"); + + return status ? 0 : 1; +} diff --git a/retired/modules/ngap_module/unit-tests/README b/retired/modules/ngap_module/unit-tests/README new file mode 100644 index 0000000000..f10288b60e --- /dev/null +++ b/retired/modules/ngap_module/unit-tests/README @@ -0,0 +1,4 @@ +This directory holds files used to test the NgapOwnedContainer class +of the Hyrax/bes circa version 1.17.0. + +jhrg 5/17/24 diff --git a/retired/modules/ngap_module/unit-tests/bes.cache.conf b/retired/modules/ngap_module/unit-tests/bes.cache.conf new file mode 100644 index 0000000000..2ee4d21274 --- /dev/null +++ b/retired/modules/ngap_module/unit-tests/bes.cache.conf @@ -0,0 +1,34 @@ + +BES.modules+=ngap +BES.module.ngap=/Users/jimg/src/opendap/hyrax/bes/modules/ngap/.libs/libngap_module.so + +BES.modules+=h5 +BES.module.h5=/Users/jimg/src/opendap/hyrax/bes/modules/hdf5_handler/.libs/libhdf5_module.so +BES.Catalog.catalog.TypeMatch+=h5:.*\.(HDF5|h5|he5)(\.bz2|\.gz|\.Z)?$; + +BES.modules+=dmrpp +BES.module.dmrpp=/Users/jimg/src/opendap/hyrax/bes/modules/dmrpp/libdmrpp_module.so +BES.Catalog.catalog.TypeMatch+=dmrpp:.*\.dmrpp(\.bz2|\.gz|\.Z)?$; + +BES.Catalog.catalog.RootDirectory=/Users/jimg/src/opendap/hyrax/bes/modules/ngap_module + +BES.LogName=/dev/null + +AllowedHosts = ^https:\/\/cmr\.(uat\.|sit\.)?earthdata\.nasa\.gov\/.*$ + +NGAP.inject_data_urls = true + +# These are here for unit tests that change these values; the bes.conf file +# does not list these so that we can test the defaults compiled into the code. +# jhrg 9/28/23 + +NGAP.UseCMRCache = true +NGAP.UseDMRppCache = true + +NGAP.CMRCacheSize.Items = 100 +NGAP.CMRCachePurge.Items = 20 +NGAP.DMRppCacheSize.Items = 100 +NGAP.DMRppCachePurge.Items = 20 +NGAP.DMRppFileCacheSize.MB = 10000 +NGAP.DMRppFileCachePurge.MB = 2000 +NGAP.DMRppFileCacheDir = /tmp diff --git a/retired/modules/ngap_module/unit-tests/bes.cache.conf.in b/retired/modules/ngap_module/unit-tests/bes.cache.conf.in new file mode 100644 index 0000000000..6c14b3d79c --- /dev/null +++ b/retired/modules/ngap_module/unit-tests/bes.cache.conf.in @@ -0,0 +1,34 @@ + +BES.modules+=ngap +BES.module.ngap=@abs_top_builddir@/modules/ngap/.libs/libngap_module.so + +BES.modules+=h5 +BES.module.h5=@abs_top_builddir@/modules/hdf5_handler/.libs/libhdf5_module.so +BES.Catalog.catalog.TypeMatch+=h5:.*\.(HDF5|h5|he5)(\.bz2|\.gz|\.Z)?$; + +BES.modules+=dmrpp +BES.module.dmrpp=@abs_top_builddir@/modules/dmrpp/libdmrpp_module.so +BES.Catalog.catalog.TypeMatch+=dmrpp:.*\.dmrpp(\.bz2|\.gz|\.Z)?$; + +BES.Catalog.catalog.RootDirectory=@abs_top_builddir@/modules/ngap_module + +BES.LogName=/dev/null + +AllowedHosts = ^https:\/\/cmr\.(uat\.|sit\.)?earthdata\.nasa\.gov\/.*$ + +NGAP.inject_data_urls = true + +# These are here for unit tests that change these values; the bes.conf file +# does not list these so that we can test the defaults compiled into the code. +# jhrg 9/28/23 + +NGAP.UseCMRCache = true +NGAP.UseDMRppCache = true + +NGAP.CMRCacheSize.Items = 100 +NGAP.CMRCachePurge.Items = 20 +NGAP.DMRppCacheSize.Items = 100 +NGAP.DMRppCachePurge.Items = 20 +NGAP.DMRppFileCacheSize.MB = 10000 +NGAP.DMRppFileCachePurge.MB = 2000 +NGAP.DMRppFileCacheDir = /tmp diff --git a/retired/modules/ngap_module/unit-tests/bes.conf.in b/retired/modules/ngap_module/unit-tests/bes.conf.in new file mode 100644 index 0000000000..184fd740c7 --- /dev/null +++ b/retired/modules/ngap_module/unit-tests/bes.conf.in @@ -0,0 +1,42 @@ + +BES.LogName = ./bes.log +BES.Catalog.catalog.RootDirectory=@abs_top_srcdir@/modules/ngap_module +BES.Catalog.catalog.TypeMatch=dmrpp:.*\.(dmrpp)$; + +BES.modules+=ngap +BES.module.ngap=@abs_top_builddir@/modules/ngap/.libs/libngap_module.so + +BES.modules+=h5 +BES.module.h5=@abs_top_builddir@/modules/hdf5_handler/.libs/libhdf5_module.so +BES.Catalog.catalog.TypeMatch+=h5:.*\.(HDF5|h5|he5)(\.bz2|\.gz|\.Z)?$; + +BES.modules+=dmrpp +BES.module.dmrpp=@abs_top_builddir@/modules/dmrpp/libdmrpp_module.so +BES.Catalog.catalog.TypeMatch+=dmrpp:.*\.dmrpp(\.bz2|\.gz|\.Z)?$; + +BES.Catalog.catalog.RootDirectory=@abs_top_builddir@/modules/ngap_module + +BES.LogName=/dev/null + +AllowedHosts = ^https:\/\/cmr\.(uat\.|sit\.)?earthdata\.nasa\.gov\/.*$ + +NGAP.inject_data_urls = true + +NGAP.UseDMRppCache = true + +# Defaults: 100 entries and purge 20 entries when the threshold is exceeded. +# NGAP.DMRppCacheSize = 100 +# NGAP.DMRppCachePurge = 20 + +NGAP.UseCMRCache = true + +# Same defaults and meaning as for the CMR cache +# NGAP.CMRCacheSize = 100 +# NGAP.CMRCachePurge = 20 + +# This is the default value - used for tests. +# Set this to your own S3 bucket where DMR++ documents can be found. +# NGAP.DataSourceLocation = https://s3.amazonaws.com/cloudydap + +# Set this to true to try the OPeNDAP bucket for DMR++ documents. +NGAP.UseOPeNDAPBucket = false diff --git a/retired/modules/ngap_module/unit-tests/cmr_json_responses/ECOv002_L1B_GEO_22172_008_20220604T024955_0700_01.json b/retired/modules/ngap_module/unit-tests/cmr_json_responses/ECOv002_L1B_GEO_22172_008_20220604T024955_0700_01.json new file mode 100644 index 0000000000..3dd5293b37 --- /dev/null +++ b/retired/modules/ngap_module/unit-tests/cmr_json_responses/ECOv002_L1B_GEO_22172_008_20220604T024955_0700_01.json @@ -0,0 +1,140 @@ +{ + "hits" : 1, + "took" : 351, + "items" : [ { + "meta" : { + "concept-type" : "granule", + "concept-id" : "G2289016111-LPCLOUD", + "revision-id" : 2, + "native-id" : "ECOv002_L1B_GEO_22172_008_20220604T024955_0700_01", + "collection-concept-id" : "C2076087338-LPCLOUD", + "provider-id" : "LPCLOUD", + "format" : "application/echo10+xml", + "revision-date" : "2024-05-15T05:25:34.926Z" + }, + "umm" : { + "TemporalExtent" : { + "RangeDateTime" : { + "BeginningDateTime" : "2022-06-04T02:49:55.580Z", + "EndingDateTime" : "2022-06-04T02:50:47.550Z" + } + }, + "OrbitCalculatedSpatialDomains" : [ { + "BeginOrbitNumber" : 22172, + "EndOrbitNumber" : 22172 + } ], + "GranuleUR" : "ECOv002_L1B_GEO_22172_008_20220604T024955_0700_01", + "AdditionalAttributes" : [ { + "Name" : "identifier_product_doi", + "Values" : [ "10.5067/ECOSTRESS/ECO_L1B_GEO.002" ] + }, { + "Name" : "identifier_product_doi_authority", + "Values" : [ "http://doi.org" ] + } ], + "MeasuredParameters" : [ { + "ParameterName" : "L1B_GEO" + } ], + "SpatialExtent" : { + "HorizontalSpatialDomain" : { + "Geometry" : { + "BoundingRectangles" : [ { + "WestBoundingCoordinate" : -111.20681, + "EastBoundingCoordinate" : -105.44751, + "NorthBoundingCoordinate" : 38.495663, + "SouthBoundingCoordinate" : 33.238541 + } ] + } + } + }, + "ProviderDates" : [ { + "Date" : "2022-06-10T03:09:27.345Z", + "Type" : "Insert" + }, { + "Date" : "2022-06-10T03:09:27.345Z", + "Type" : "Update" + } ], + "CollectionReference" : { + "ShortName" : "ECO_L1B_GEO", + "Version" : "002" + }, + "PGEVersionClass" : { + "PGEVersion" : "7.000000" + }, + "RelatedUrls" : [ { + "Format" : "Not provided", + "Description" : "Download ECOv002_L1B_GEO_22172_008_20220604T024955_0700_01.cmr.xml", + "Type" : "GET DATA", + "URL" : "https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/ECO_L1B_GEO.002/ECOv002_L1B_GEO_22172_008_20220604T024955_0700_01/ECOv002_L1B_GEO_22172_008_20220604T024955_0700_01.cmr.xml" + }, { + "Format" : "Not provided", + "Description" : "This link provides direct download access via S3 to the granule", + "Type" : "GET DATA", + "URL" : "s3://lp-prod-protected/ECO_L1B_GEO.002/ECOv002_L1B_GEO_22172_008_20220604T024955_0700_01/ECOv002_L1B_GEO_22172_008_20220604T024955_0700_01.cmr.xml" + }, { + "Format" : "Not provided", + "Description" : "Download ECOv002_L1B_GEO_22172_008_20220604T024955_0700_01.h5", + "Type" : "GET DATA", + "URL" : "https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/ECO_L1B_GEO.002/ECOv002_L1B_GEO_22172_008_20220604T024955_0700_01/ECOv002_L1B_GEO_22172_008_20220604T024955_0700_01.h5" + }, { + "Format" : "Not provided", + "Description" : "This link provides direct download access via S3 to the granule", + "Type" : "GET DATA", + "URL" : "s3://lp-prod-protected/ECO_L1B_GEO.002/ECOv002_L1B_GEO_22172_008_20220604T024955_0700_01/ECOv002_L1B_GEO_22172_008_20220604T024955_0700_01.h5" + }, { + "Format" : "Not provided", + "Description" : "Download ECOv002_L1B_GEO_22172_008_20220604T024955_0700_01.h5.dmrpp", + "Type" : "GET DATA", + "URL" : "https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/ECO_L1B_GEO.002/ECOv002_L1B_GEO_22172_008_20220604T024955_0700_01/ECOv002_L1B_GEO_22172_008_20220604T024955_0700_01.h5.dmrpp" + }, { + "Format" : "Not provided", + "Description" : "This link provides direct download access via S3 to the granule", + "Type" : "GET DATA", + "URL" : "s3://lp-prod-protected/ECO_L1B_GEO.002/ECOv002_L1B_GEO_22172_008_20220604T024955_0700_01/ECOv002_L1B_GEO_22172_008_20220604T024955_0700_01.h5.dmrpp" + }, { + "Format" : "Not provided", + "Description" : "Download ECOv002_L1B_GEO_22172_008_20220604T024955_0700_01.cmr.xml", + "Type" : "VIEW RELATED INFORMATION", + "URL" : "https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/ECO_L1B_GEO.002/ECOv002_L1B_GEO_22172_008_20220604T024955_0700_01/ECOv002_L1B_GEO_22172_008_20220604T024955_0700_01.cmr.xml" + }, { + "Format" : "Not provided", + "Description" : "This link provides direct download access via S3 to the granule", + "Type" : "VIEW RELATED INFORMATION", + "URL" : "s3://lp-prod-protected/ECO_L1B_GEO.002/ECOv002_L1B_GEO_22172_008_20220604T024955_0700_01/ECOv002_L1B_GEO_22172_008_20220604T024955_0700_01.cmr.xml" + }, { + "Format" : "Not provided", + "Description" : "api endpoint to retrieve temporary credentials valid for same-region direct s3 access", + "Type" : "VIEW RELATED INFORMATION", + "URL" : "https://data.lpdaac.earthdatacloud.nasa.gov/s3credentials" + }, { + "Subtype" : "OPENDAP DATA", + "Format" : "Not provided", + "Description" : "OPeNDAP request URL", + "Type" : "USE SERVICE API", + "URL" : "https://opendap.earthdata.nasa.gov/collections/C2076087338-LPCLOUD/granules/ECOv002_L1B_GEO_22172_008_20220604T024955_0700_01" + } ], + "DataGranule" : { + "DayNightFlag" : "Night", + "Identifiers" : [ { + "Identifier" : "ECOv002_L1B_GEO_22172_008_20220604T024955_0700_01", + "IdentifierType" : "ProducerGranuleId" + } ], + "ProductionDateTime" : "2022-06-04T08:32:22.478Z", + "ArchiveAndDistributionInformation" : [ { + "Name" : "Not provided", + "Size" : 732.459, + "SizeUnit" : "MB", + "Format" : "Not provided" + } ] + }, + "Platforms" : [ { + "ShortName" : "ISS", + "Instruments" : [ { + "ShortName" : "ECOSTRESS", + "ComposedOf" : [ { + "ShortName" : "PHyTIR" + } ] + } ] + } ] + } + } ] +} \ No newline at end of file diff --git a/retired/modules/ngap_module/unit-tests/cmr_json_responses/README b/retired/modules/ngap_module/unit-tests/cmr_json_responses/README new file mode 100644 index 0000000000..074941edbc --- /dev/null +++ b/retired/modules/ngap_module/unit-tests/cmr_json_responses/README @@ -0,0 +1,6 @@ +How to build these CMR granule_ur responses + +burl -o .json \ +'https://cmr.earthdata.nasa.gov/search/granules.umm_json_v1_4?pretty=true&collection_concept_id=>&granule_ur=' + +You can use ask_cmr in the pydmr project, but that requires some work on the response it prints. diff --git a/retired/modules/ngap_module/unit-tests/cmr_json_responses/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.json b/retired/modules/ngap_module/unit-tests/cmr_json_responses/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.json new file mode 100644 index 0000000000..00e10d00bd --- /dev/null +++ b/retired/modules/ngap_module/unit-tests/cmr_json_responses/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.json @@ -0,0 +1,330 @@ +{ + "hits" : 1, + "took" : 307, + "items" : [ { + "meta" : { + "concept-type" : "granule", + "concept-id" : "G2653766826-POCLOUD", + "revision-id" : 3, + "native-id" : "cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21", + "collection-concept-id" : "C2251464384-POCLOUD", + "provider-id" : "POCLOUD", + "format" : "application/vnd.nasa.cmr.umm+json", + "revision-date" : "2023-04-11T21:03:32.226Z" + }, + "umm" : { + "TemporalExtent" : { + "RangeDateTime" : { + "EndingDateTime" : "2023-04-10T23:59:59.999Z", + "BeginningDateTime" : "2023-04-10T00:00:00.499Z" + } + }, + "GranuleUR" : "cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21", + "ProviderDates" : [ { + "Type" : "Insert", + "Date" : "2023-04-11T20:55:54.356Z" + }, { + "Type" : "Update", + "Date" : "2023-04-11T20:55:54.356Z" + } ], + "SpatialExtent" : { + "HorizontalSpatialDomain" : { + "Geometry" : { + "BoundingRectangles" : [ { + "WestBoundingCoordinate" : -180, + "SouthBoundingCoordinate" : -40, + "EastBoundingCoordinate" : 180, + "NorthBoundingCoordinate" : 40 + } ] + } + } + }, + "DataGranule" : { + "ArchiveAndDistributionInformation" : [ { + "SizeUnit" : "MB", + "Size" : 9.918212890625E-5, + "Checksum" : { + "Value" : "1d1d77934b9099fd8da3f1fca53cfc07", + "Algorithm" : "MD5" + }, + "Name" : "cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.nc.md5" + }, { + "SizeUnit" : "MB", + "Size" : 1290.025263786316, + "Checksum" : { + "Value" : "faefeaf1e3d43701048629093f9abd3f", + "Algorithm" : "MD5" + }, + "Name" : "cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.nc" + } ], + "DayNightFlag" : "Unspecified", + "ProductionDateTime" : "2023-04-11T19:38:10.000Z" + }, + "CollectionReference" : { + "Version" : "2.1", + "ShortName" : "CYGNSS_L1_V2.1" + }, + "RelatedUrls" : [ { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-protected/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.nc", + "Description" : "Download cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.nc", + "Type" : "GET DATA" + }, { + "URL" : "s3://podaac-ops-cumulus-protected/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.nc", + "Description" : "This link provides direct download access via S3 to the granule", + "Type" : "GET DATA" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.nc.md5", + "Description" : "Download cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.nc.md5", + "Type" : "EXTENDED METADATA" + }, { + "URL" : "s3://podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.nc.md5", + "Description" : "This link provides direct download access via S3 to the granule", + "Type" : "EXTENDED METADATA" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/s3credentials", + "Description" : "api endpoint to retrieve temporary credentials valid for same-region direct s3 access", + "Type" : "VIEW RELATED INFORMATION" + }, { + "URL" : "https://opendap.earthdata.nasa.gov/collections/C2251464384-POCLOUD/granules/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21", + "Type" : "USE SERVICE API", + "Subtype" : "OPENDAP DATA", + "Description" : "OPeNDAP request URL" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.prn_code.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.sv_num.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.track_id.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.ddm_ant.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.zenith_code_phase.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.sp_ddmi_delay_correction.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.sp_ddmi_dopp_correction.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.add_range_to_sp.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.add_range_to_sp_pvt.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.sp_ddmi_dopp.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.sp_fsw_delay.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.sp_delay_error.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.sp_dopp_error.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.fsw_comp_delay_shift.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.fsw_comp_dopp_shift.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.prn_fig_of_merit.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.tx_clk_bias.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.sp_alt.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.sp_inc_angle.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.sp_theta_orbit.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.sp_az_orbit.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.sp_theta_body.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.sp_az_body.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.sp_rx_gain.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.gps_eirp.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.gps_tx_power_db_w.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.gps_ant_gain_db_i.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.gps_off_boresight_angle_deg.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.direct_signal_snr.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.ddm_snr.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.ddm_noise_floor.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.inst_gain.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.lna_noise_figure.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.rx_to_sp_range.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.tx_to_sp_range.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.bb_nearest.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.fresnel_coeff.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.ddm_nbrcs.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.ddm_les.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.nbrcs_scatter_area.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.les_scatter_area.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.brcs_ddm_peak_bin_delay_row.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.brcs_ddm_peak_bin_dopp_col.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.brcs_ddm_sp_bin_delay_row.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.brcs_ddm_sp_bin_dopp_col.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.ddm_brcs_uncert.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + }, { + "URL" : "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/CYGNSS_L1_V2.1/2023/100/cyg04.ddmi.s20230410-000000-e20230410-235959.l1.power-brcs.a21.d21.quality_flags.png", + "Type" : "GET RELATED VISUALIZATION", + "Subtype" : "DIRECT DOWNLOAD", + "MimeType" : "image/png" + } ] + } + } ] +} \ No newline at end of file diff --git a/retired/modules/ngap_module/unit-tests/data/chunked_enum.h5 b/retired/modules/ngap_module/unit-tests/data/chunked_enum.h5 new file mode 100644 index 0000000000..95303fecd5 Binary files /dev/null and b/retired/modules/ngap_module/unit-tests/data/chunked_enum.h5 differ diff --git a/retired/modules/ngap_module/unit-tests/data/chunked_enum.h5.dmr b/retired/modules/ngap_module/unit-tests/data/chunked_enum.h5.dmr new file mode 100644 index 0000000000..9badcd7728 --- /dev/null +++ b/retired/modules/ngap_module/unit-tests/data/chunked_enum.h5.dmr @@ -0,0 +1,35 @@ + + + + + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + + + diff --git a/retired/modules/ngap_module/unit-tests/data/chunked_enum.h5.dmrpp b/retired/modules/ngap_module/unit-tests/data/chunked_enum.h5.dmrpp new file mode 100644 index 0000000000..5b6b03cbfd --- /dev/null +++ b/retired/modules/ngap_module/unit-tests/data/chunked_enum.h5.dmrpp @@ -0,0 +1,39 @@ + + + + + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + UNKNOWN + + + + + + diff --git a/retired/modules/ngap_module/unit-tests/data/d_int.h5 b/retired/modules/ngap_module/unit-tests/data/d_int.h5 new file mode 100644 index 0000000000..14e549c57e Binary files /dev/null and b/retired/modules/ngap_module/unit-tests/data/d_int.h5 differ diff --git a/retired/modules/ngap_module/unit-tests/data/d_int.h5.dmr b/retired/modules/ngap_module/unit-tests/data/d_int.h5.dmr new file mode 100644 index 0000000000..e0ac83c6f3 --- /dev/null +++ b/retired/modules/ngap_module/unit-tests/data/d_int.h5.dmr @@ -0,0 +1,80 @@ + + + + + + -32768 + + + 32767 + + + d16_1 + + + /d16_1 + + + + + + + -32768 + + + 32767 + + + -32768 + 32767 + + + -32768 + 1 + 2 + 32767 + + + d16_2 + + + /d16_2 + + + + + + + + -2147483648 + + + 2147483647 + + + d32_1 + + + /d32_1 + + + + + + + + + + -2147483648 + + + 2147483647 + + + d32_2 + + + /d32_2 + + + diff --git a/retired/modules/ngap_module/unit-tests/data/d_int.h5.dmrpp b/retired/modules/ngap_module/unit-tests/data/d_int.h5.dmrpp new file mode 100644 index 0000000000..c384e22fb0 --- /dev/null +++ b/retired/modules/ngap_module/unit-tests/data/d_int.h5.dmrpp @@ -0,0 +1,66 @@ + + + + + + -32768 + + + 32767 + + + + + + + + -32768 + + + 32767 + + + -32768 + 32767 + + + -32768 + 1 + 2 + 32767 + + + + + + + + + -2147483648 + + + 2147483647 + + + + + + + + + + + -2147483648 + + + 2147483647 + + + + diff --git a/retired/modules/ngap_module/unit-tests/data/ngap_cache_for_tests/place_holder b/retired/modules/ngap_module/unit-tests/data/ngap_cache_for_tests/place_holder new file mode 100644 index 0000000000..e69de29bb2 diff --git a/retired/modules/ngap_module/unit-tests/test_config.h.in b/retired/modules/ngap_module/unit-tests/test_config.h.in new file mode 100644 index 0000000000..ce92914a95 --- /dev/null +++ b/retired/modules/ngap_module/unit-tests/test_config.h.in @@ -0,0 +1,9 @@ +#ifndef E_test_config_h +#define E_test_config_h + +#define TEST_SRC_DIR "@abs_srcdir@" +#define TEST_BUILD_DIR "@abs_builddir@" +#define TEST_DATA_DIR "@abs_top_srcdir@/modules/ngap_module/data" + +#endif + diff --git a/retired/modules/ngap_module/unit-tests/tmp/bes-autotest-5512.1-logs.tar.gz b/retired/modules/ngap_module/unit-tests/tmp/bes-autotest-5512.1-logs.tar.gz new file mode 100644 index 0000000000..bfcf2aaf9b Binary files /dev/null and b/retired/modules/ngap_module/unit-tests/tmp/bes-autotest-5512.1-logs.tar.gz differ diff --git a/retired/modules/ngap_module/unit-tests/tmp/dispatch/unit-tests/catalog_test_baselines/get_site_map.txt b/retired/modules/ngap_module/unit-tests/tmp/dispatch/unit-tests/catalog_test_baselines/get_site_map.txt new file mode 100644 index 0000000000..41fbd94fa9 --- /dev/null +++ b/retired/modules/ngap_module/unit-tests/tmp/dispatch/unit-tests/catalog_test_baselines/get_site_map.txt @@ -0,0 +1,4 @@ +https://machine/opendap/child_dir/child_file.conf.html +https://machine/opendap/child_dir/child_file1.html +https://machine/opendap/file1.html +https://machine/opendap/file2.html diff --git a/translate-ip-numbers.py b/translate-ip-numbers.py new file mode 100644 index 0000000000..87165efb97 --- /dev/null +++ b/translate-ip-numbers.py @@ -0,0 +1,36 @@ +import socket + +def get_hostname(ip_address): + """ + Attempts to retrieve the hostname for a given IP address using reverse DNS lookup. + + Args: + ip_address: The IP address to get the hostname for (string). + + Returns: + The hostname if found, otherwise returns the original IP address (string). + """ + try: + hostname = socket.gethostbyaddr(ip_address)[0] + return hostname + except socket.herror: + # Handle potential errors during lookup + return ip_address + +def process_file(filename): + """ + Reads an input file with lines containing count numbers and IP addresses, + attempts reverse DNS lookup for IPs, and prints the results. + + Args: + filename: The name of the text file to process (string). + """ + with open(filename, 'r') as file: + for line in file: + # Split the line based on whitespace (assuming port is first) + count, ip_address = line.strip().split() + hostname = get_hostname(ip_address) + print(f"Count: {count}, IP: {ip_address}, Hostname: {hostname}") + +# Replace 'ip_list.txt' with your actual filename +process_file('accesses.06.26.24.txt')