bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
NgapRequestHandler.cc
1// NgapContainer.cc
2
3// -*- mode: c++; c-basic-offset:4 -*-
4
5// This file is part of ngap_module, A C++ module that can be loaded in to
6// the OPeNDAP Back-End Server (BES) and is able to handle remote requests.
7
8// Copyright (c) 2020 OPeNDAP, Inc.
9// Author: Nathan Potter <ndp@opendap.org>
10//
11// This library is free software; you can redistribute it and/or
12// modify it under the terms of the GNU Lesser General Public
13// License as published by the Free Software Foundation; either
14// version 2.1 of the License, or (at your option) any later version.
15//
16// This library is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19// Lesser General Public License for more details.
20//
21// You should have received a copy of the GNU Lesser General Public
22// License along with this library; if not, write to the Free Software
23// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24//
25// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
26// Authors:
27// ndp Nathan Potter <ndp@opendap.org>
28
29#include "config.h"
30
31#include <libdap/InternalErr.h>
32
33#include <BESResponseHandler.h>
34#include <BESResponseNames.h>
35#include <BESVersionInfo.h>
36#include <BESConstraintFuncs.h>
37#include <BESServiceRegistry.h>
38#include <TheBESKeys.h>
39#include <BESLog.h>
40#include <BESUtil.h>
41
42#include "NgapRequestHandler.h"
43#include "NgapNames.h"
44
45using namespace std;
46using namespace libdap;
47using namespace ngap;
48
49// CMR caching
50unsigned int NgapRequestHandler::d_cmr_cache_size_items = 100; // Entries, not size in bytes, MB, etc.
51unsigned int NgapRequestHandler::d_cmr_cache_purge_items = 20;
52
53bool NgapRequestHandler::d_use_cmr_cache = false;
54MemoryCache<std::string> NgapRequestHandler::d_cmr_mem_cache;
55
56// DMR++ caching
57unsigned int NgapRequestHandler::d_dmrpp_mem_cache_size_items = 100;
58unsigned int NgapRequestHandler::d_dmrpp_mem_cache_purge_items = 20;
59
60bool NgapRequestHandler::d_use_dmrpp_cache = false;
61MemoryCache<std::string> NgapRequestHandler::d_dmrpp_mem_cache;
62
63long long NgapRequestHandler::d_dmrpp_file_cache_size_mb = 10'000; // 10,000 MB ~= 10GB, roughly
64long long NgapRequestHandler::d_dmrpp_file_cache_purge_size_mb = 2'000; // 2,000 MB ~= 2GB
65string NgapRequestHandler::d_dmrpp_file_cache_dir = "/tmp/hyrax_dmrpp_cache";
66
67FileCache NgapRequestHandler::d_dmrpp_file_cache;
68
69NgapRequestHandler::NgapRequestHandler(const string &name) :
71{
72 add_method(VERS_RESPONSE, NgapRequestHandler::ngap_build_vers);
73 add_method(HELP_RESPONSE, NgapRequestHandler::ngap_build_help);
74
75 // Read BES keys to determine if the caches should be used. jhrg 9/22/23
76 NgapRequestHandler::d_use_cmr_cache
77 = TheBESKeys::read_bool_key(USE_CMR_CACHE, NgapRequestHandler::d_use_cmr_cache);
78 if (NgapRequestHandler::d_use_cmr_cache) {
79 NgapRequestHandler::d_cmr_cache_size_items
80 = TheBESKeys::read_int_key(CMR_CACHE_THRESHOLD, NgapRequestHandler::d_cmr_cache_size_items);
81 NgapRequestHandler::d_cmr_cache_purge_items
82 = TheBESKeys::read_int_key(CMR_CACHE_SPACE, NgapRequestHandler::d_cmr_cache_purge_items);
83 if (!d_cmr_mem_cache.initialize(d_cmr_cache_size_items, d_cmr_cache_purge_items)) {
84 ERROR_LOG("NgapRequestHandler::NgapRequestHandler() - failed to initialize CMR cache");
85 }
86 }
87
88 NgapRequestHandler::d_use_dmrpp_cache
89 = TheBESKeys::read_bool_key(USE_DMRPP_CACHE, NgapRequestHandler::d_use_dmrpp_cache);
90 if (NgapRequestHandler::d_use_dmrpp_cache) {
91 NgapRequestHandler::d_dmrpp_mem_cache_size_items
92 = TheBESKeys::read_int_key(DMRPP_CACHE_THRESHOLD, NgapRequestHandler::d_dmrpp_mem_cache_size_items);
93 NgapRequestHandler::d_dmrpp_mem_cache_purge_items
94 = TheBESKeys::read_int_key(DMRPP_CACHE_SPACE, NgapRequestHandler::d_dmrpp_mem_cache_purge_items);
95 if (!d_dmrpp_mem_cache.initialize(d_dmrpp_mem_cache_size_items, d_dmrpp_mem_cache_purge_items)) {
96 ERROR_LOG("NgapRequestHandler::NgapRequestHandler() - failed to initialize DMR++ cache");
97 }
98
99 // Now set up the file cache. Note that the sizes in the bes.conf file are in MB,
100 // so convert them to bytes. jhrg 11/14/23
101 NgapRequestHandler::d_dmrpp_file_cache_size_mb
102 = MEGABYTE * TheBESKeys::read_ulong_key(DMRPP_FILE_CACHE_THRESHOLD,
103 NgapRequestHandler::d_dmrpp_file_cache_size_mb);
104 NgapRequestHandler::d_dmrpp_file_cache_purge_size_mb
105 = MEGABYTE * TheBESKeys::read_ulong_key(DMRPP_FILE_CACHE_SPACE,
106 NgapRequestHandler::d_dmrpp_file_cache_purge_size_mb);
107 NgapRequestHandler::d_dmrpp_file_cache_dir
108 = TheBESKeys::read_string_key(DMRPP_FILE_CACHE_DIR,
109 NgapRequestHandler::d_dmrpp_file_cache_dir);
110 if (BESUtil::mkdir_p(NgapRequestHandler::d_dmrpp_file_cache_dir, 0775) != 0) {
111 ERROR_LOG("DMR++ file cache directory '" + NgapRequestHandler::d_dmrpp_file_cache_dir + "' error: "
112 + strerror(errno));
113 }
114 if (!NgapRequestHandler::d_dmrpp_file_cache.initialize(NgapRequestHandler::d_dmrpp_file_cache_dir,
115 NgapRequestHandler::d_dmrpp_file_cache_size_mb,
116 NgapRequestHandler::d_dmrpp_file_cache_purge_size_mb)) {
117 ERROR_LOG("NgapRequestHandler::NgapRequestHandler() - failed to initialize DMR++ file cache");
118 }
119 }
120}
121
122bool NgapRequestHandler::ngap_build_vers(BESDataHandlerInterface &dhi)
123{
124 auto info = dynamic_cast<BESVersionInfo *>(dhi.response_handler->get_response_object());
125 if (!info) throw InternalErr(__FILE__, __LINE__, "Expected a BESVersionInfo instance");
126
127 info->add_module(MODULE_NAME, MODULE_VERSION);
128 return true;
129}
130
131bool NgapRequestHandler::ngap_build_help(BESDataHandlerInterface &dhi)
132{
133 auto info = dynamic_cast<BESInfo *>(dhi.response_handler->get_response_object());
134 if (!info) throw InternalErr(__FILE__, __LINE__, "Expected a BESInfo instance");
135
136 // This is an example. If you had a help file you could load it like
137 // this and if your handler handled the following responses.
138 map<string, string, std::less<>> attrs;
139 attrs["name"] = MODULE_NAME;
140 attrs["version"] = MODULE_VERSION;
141
142 list<string> services;
143 BESServiceRegistry::TheRegistry()->services_handled(NGAP_NAME, services);
144 if (!services.empty()) {
145 string handles = BESUtil::implode(services, ',');
146 attrs["handles"] = handles;
147 }
148 info->begin_tag("module", &attrs);
149 info->end_tag("module");
150
151 return true;
152}
153
154void NgapRequestHandler::dump(ostream &strm) const
155{
156 strm << BESIndent::LMarg << "NgapRequestHandler::dump - (" << (void *) this << ")" << endl;
157 BESIndent::Indent();
159 BESIndent::UnIndent();
160}
Structure storing information used by the BES to handle the request.
Represents a specific data type request handler.
virtual void dump(std::ostream &strm) const
dumps information about this object
virtual BESResponseObject * get_response_object()
return the current response object
virtual void services_handled(const std::string &handler, std::list< std::string > &services)
returns the list of servies provided by the handler in question
static int mkdir_p(const std::string &path, mode_t mode)
Definition BESUtil.cc:1254
static std::string implode(const std::list< std::string > &values, char delim)
Definition BESUtil.cc:620
Implementation of a caching mechanism for files.
Definition FileCache.h:122
static int read_int_key(const std::string &key, int default_value)
Read an integer-valued key from the bes.conf file.
static bool read_bool_key(const std::string &key, bool default_value)
Read a boolean-valued key from the bes.conf file.
static std::string read_string_key(const std::string &key, const std::string &default_value)
Read a string-valued key from the bes.conf file.
static unsigned long read_ulong_key(const std::string &key, unsigned long default_value)
Read an integer-valued key from the bes.conf file.
A simple memory cache.
Definition MemoryCache.h:64
void dump(std::ostream &strm) const override
dumps information about this object