1 // ServerFunctionsList.cc
2
3 // This file is part of bes, A C++ back-end server implementation framework
4 // for the OPeNDAP Data Access Protocol.
5
6 // Copyright (c) 2013 OPeNDAP, Inc.
7 // Author: James Gallagher <jgallagher@opendap.org>
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 //
23 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24
25 #include "config.h"
26
27 #ifdef HAVE_STDLIB_H
28 #include <stdlib.h>
29 #endif
30
31 #include <pthread.h>
32
33 #include <iostream>
34 #include <algorithm>
35
36 //#define DODS_DEBUG
37
38 #include <expr.h>
39 #include "debug.h"
40
41 #include "ServerFunctionsList.h"
42
43 using namespace std;
44 using namespace libdap;
45
46 namespace libdap {
47
48 static pthread_once_t ServerFunctionsList_instance_control = PTHREAD_ONCE_INIT;
49
50 ServerFunctionsList *ServerFunctionsList::d_instance = 0 ;
51
52 /**
53 * private static that only gets called once in the life cycle of the process.
54 */
initialize_instance()55 void ServerFunctionsList::initialize_instance() {
56 if (d_instance == 0) {
57 DBG(cerr << "ServerFunctionsList::initialize_instance() - Creating singleton ServerFunctionList instance." << endl);
58 d_instance = new ServerFunctionsList;
59 #if HAVE_ATEXIT
60 atexit(delete_instance);
61 #endif
62 }
63 }
64
65 /**
66 * Private static function can only be called by friends andf pThreads code.
67 */
delete_instance()68 void ServerFunctionsList::delete_instance() {
69 DBG(cerr << "ServerFunctionsList::delete_instance() - Deleting singleton ServerFunctionList instance." << endl);
70 delete d_instance;
71 d_instance = 0;
72 }
73
74 /**
75 * Private method insures that nobody can try to delete the singleton class.
76 */
77
~ServerFunctionsList()78 ServerFunctionsList::~ServerFunctionsList() {
79 SFLIter fit;
80 for(fit=d_func_list.begin(); fit!=d_func_list.end() ; fit++){
81 ServerFunction *func = fit->second;
82 DBG(cerr << "ServerFunctionsList::~ServerFunctionsList() - Deleting ServerFunction " << func->getName() << " from ServerFunctionsList." << endl);
83 delete func;
84 }
85 d_func_list.clear();
86 }
87
TheList()88 ServerFunctionsList * ServerFunctionsList::TheList() {
89 pthread_once(&ServerFunctionsList_instance_control, initialize_instance);
90 DBG(cerr << "ServerFunctionsList::TheList() - Returning singleton ServerFunctionList instance." << endl);
91 return d_instance;
92 }
93
94 /**
95 * Adds the passed ServerFunction pointer to the list of ServerFunctions using
96 * the value of ServerFunction.getName() as the key in the list.
97 *
98 * @brief Adds the passed ServerFunction pointer to the list of ServerFunctions.
99 * @param *func A pointer to the ServerFunction object to add to the ServerFunctionList.
100 * The pointer is copied, not the object referenced; this class does not
101 * delete the pointer.
102 */
add_function(ServerFunction * func)103 void ServerFunctionsList::add_function(ServerFunction *func )
104 {
105 DBG(cerr << "ServerFunctionsList::add_function() - Adding ServerFunction " << func->getName() << endl);
106 d_func_list.insert(std::make_pair(func->getName(),func));
107 }
108
109 /**
110 * Returns the first boolean function in the list whose key value matches the passed string name.
111 * When a match is found the function returns true and sets returned value parameter *f to
112 * the boolean function held by the ServerFunction object extracted from the list.
113 *
114 * Method:
115 * Looks through the list of ServerFunctions and compares each function's key value (which
116 * would be the value of SurverFunction.getName()) with the value of the string parameter
117 * 'name'. When they match then the returned value parameter is set to the value returned
118 * by ServerFunction.get_btp_func(). If the ServerFunction _is not_ a instance of a boolean
119 * function then the return value will be 0 (null) and the search for matching function will continue.
120 * If the ServerFunction _is_ a boolean function then the returned value will be non-zero and
121 * the search will return true (it found the thing) and the returned value parameter *f will have
122 * it's value set to the boolean function.
123 *
124 * @brief Find a boolean function with a given name in the function list.
125 * @param name A string containing the name of the function to find.
126 * @param *f A returned value parameter through which a point to the desired function is returned.
127 *
128 */
find_function(const std::string & name,bool_func * f) const129 bool ServerFunctionsList::find_function(const std::string &name, bool_func *f) const
130 {
131 if (d_func_list.empty())
132 return false;
133
134 std::pair <SFLCIter, SFLCIter> ret;
135 ret = d_func_list.equal_range(name);
136 for (SFLCIter it = ret.first; it != ret.second; ++it) {
137 if (name == it->first && (*f = it->second->get_bool_func())){
138 DBG(cerr << "ServerFunctionsList::find_function() - Found boolean function " << it->second->getName() << endl);
139 return true;
140 }
141 }
142
143 return false;
144 }
145
146 /**
147 * Returns the first BaseType function in the list whose key value matches the passed string name.
148 * When a match is found the function returns true and sets returned value parameter *f to
149 * the BaseType function held by the ServerFunction object extracted from the list.
150 *
151 * Method:
152 * Looks through the list of ServerFunctions and compares each function's key value (which
153 * would be the value of SurverFunction.getName()) with the value of the string parameter
154 * 'name'. When they match then the returned value parameter is set to the value returned
155 * by ServerFunction.get_btp_func(). If the ServerFunction _is not_ a instance of a BaseType
156 * function then the return value will be 0 (null) and the search for matching function will continue.
157 * If the ServerFunction _is_ a BaseType function then the returned value will be non-zero and
158 * the search will return true (it found the thing) and the returned value parameter *f will have
159 * it's value set to the BaseType function.
160 *
161 * @brief Find a BaseType function with a given name in the function list.
162 * @param name A string containing the name of the function to find.
163 * @param *f A returned value parameter through which a point to the desired function is returned.
164 *
165 */
find_function(const string & name,btp_func * f) const166 bool ServerFunctionsList::find_function(const string &name, btp_func *f) const
167 {
168 if (d_func_list.empty())
169 return false;
170 DBG(cerr << "ServerFunctionsList::find_function() - Looking for ServerFunction '" << name << "'" << endl);
171
172 std::pair <SFLCIter, SFLCIter> ret;
173 ret = d_func_list.equal_range(name);
174 for (SFLCIter it = ret.first; it != ret.second; ++it) {
175 if (name == it->first && (*f = it->second->get_btp_func())){
176 DBG(cerr << "ServerFunctionsList::find_function() - Found basetype function " << it->second->getName() << endl);
177 return true;
178 }
179 }
180
181 return false;
182 }
183
184 /**
185 * Returns the first projection function in the list whose key value matches the passed string name.
186 * When a match is found the function returns true and sets returned value parameter *f to
187 * the projection function held by the ServerFunction object extracted from the list.
188 *
189 * Method:
190 * Looks through the list of ServerFunctions and looks at each function's key value (which
191 * would be the value of SurverFunction.getName() for each function). When a function has the same
192 * key name as the value of the string parameter 'name', then the returned value parameter is set
193 * the value returned by ServerFunction.get_proj_func(). If the ServerFunction _is not_ a projection
194 * function then the return value will be 0 (null) and the search for matching function will continue.
195 * If the ServerFunction _is_ a projection then the returned value will be non-zero and the search will
196 * return true (it found the thing) and the returned value parameter *f will have it's value set
197 * to the projection function.
198 *
199 * @brief Find a projection function with a given name in the function list.
200 * @param name A string containing the name of the function to find.
201 * @param *f A returned value parameter through which a point to the desired function is returned.
202 *
203 */
find_function(const string & name,proj_func * f) const204 bool ServerFunctionsList::find_function(const string &name, proj_func *f) const
205 {
206 if (d_func_list.empty())
207 return false;
208
209 std::pair <SFLCIter, SFLCIter> ret;
210 ret = d_func_list.equal_range(name);
211 for (SFLCIter it = ret.first; it != ret.second; ++it) {
212 if (name == it->first && (*f = it->second->get_proj_func())){
213 DBG(cerr << "ServerFunctionsList::find_function() - Found projection function " << it->second->getName() << endl);
214 return true;
215 }
216 }
217
218 return false;
219 }
220
221 /**
222 * Find a DAP4 function in the Server Functions List.
223 *
224 * @param name Look for this function name
225 * @param f Value-result parameter. NULL if the function is not found
226 * @return True if the function was found, otherwise false.
227 */
find_function(const string & name,D4Function * f) const228 bool ServerFunctionsList::find_function(const string &name, D4Function *f) const
229 {
230 if (d_func_list.empty())
231 return false;
232
233 std::pair <SFLCIter, SFLCIter> ret;
234 ret = d_func_list.equal_range(name);
235 for (SFLCIter it = ret.first; it != ret.second; ++it) {
236 if (name == it->first && (*f = it->second->get_d4_function())) {
237 return true;
238 }
239 }
240
241 return false;
242 }
243
244 /** @brief Returns an iterator pointing to the first key pair in the ServerFunctionList. */
begin()245 ServerFunctionsList::SFLIter ServerFunctionsList::begin()
246 {
247 return d_func_list.begin();
248 }
249
250 /** @brief Returns an iterator pointing to the last key pair in the ServerFunctionList. */
end()251 ServerFunctionsList::SFLIter ServerFunctionsList::end()
252 {
253 return d_func_list.end();
254 }
255
256 /**
257 *
258 *
259 * @brief Returns the ServerFunction pointed to by the passed iterator.
260 *
261 */
getFunction(SFLIter it)262 ServerFunction *ServerFunctionsList::getFunction(SFLIter it)
263 {
264 return (*it).second;
265 }
266
getFunctionNames(vector<string> * names)267 void ServerFunctionsList::getFunctionNames(vector<string> *names){
268 SFLIter fit;
269 for(fit = d_func_list.begin(); fit != d_func_list.end(); fit++) {
270 ServerFunction *func = fit->second;
271 names->push_back(func->getName());
272 }
273 }
274
275 } // namespace libdap
276