NCBI C++ ToolKit
remote_cgi_wn.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: remote_cgi_wn.cpp 100706 2023-08-31 20:10:36Z lavr $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Authors: Maxim Didenko, Dmitry Kazimirov
27  *
28  * File Description: NetSchedule worker node sample
29  *
30  */
31 
32 #include <ncbi_pch.hpp>
33 
34 #include "exec_helpers.hpp"
35 
36 #include <cgi/ncbicgi.hpp>
37 
38 #include <functional>
39 #include <iterator>
40 
42 
43 struct IsStandard
44 {
45  typedef string argument_type;
46  bool operator() (const string& val) const;
47  static const char* const sm_StandardCgiEnv[];
48 };
49 
50 const char* const IsStandard::sm_StandardCgiEnv[] = {
51  "DOCUMENT_ROOT",
52  "GATEWAY_INTERFACE",
53  "PROXIED_IP",
54  "QUERY_STRING",
55  "REMOTE_ADDR",
56  "REMOTE_PORT",
57  "REMOTE_IDENT",
58  "REQUEST_METHOD",
59  "REQUEST_URI",
60  "SCRIPT_FILENAME",
61  "SCRIPT_NAME",
62  "SCRIPT_URI",
63  "SCRIPT_URL",
64  "SERVER_ADDR",
65  "SERVER_ADMIN",
66  "SERVER_NAME",
67  "SERVER_PORT",
68  "SERVER_PROTOCOL",
69  "SERVER_SIGNATURE",
70  "SERVER_SOFTWARE",
71  "SERVER_METHOD",
72  "PATH_INFO",
73  "PATH_TRANSLATED",
74  "AUTH_TYPE",
75  "CONTENT_TYPE",
76  "CONTENT_LENGTH",
77  "UNIQUE_ID",
78  NULL
79 };
80 
81 inline bool IsStandard::operator() (const string& val) const
82 {
83  if (NStr::StartsWith(val, "HTTP_")) return true;
84  for( int i = 0; sm_StandardCgiEnv[i] != NULL; ++i) {
85  if (NStr::Compare(val, sm_StandardCgiEnv[i]) == 0) return true;
86  }
87  return false;
88 }
89 
90 template <typename Cont>
91 struct HasValue
92 {
93  typedef string argument_type;
94  HasValue(const Cont& cont) : m_Cont(cont) {}
95  inline bool operator() (const string& val) const
96  {
97  return find(m_Cont.begin(), m_Cont.end(), val) != m_Cont.end();
98  }
99  const Cont& m_Cont;
100 };
101 
102 template <typename T>
103 struct SNot : T
104 {
105  SNot(T o) : T(std::move(o)) {}
106  bool operator() (const string& val) const { return !T::operator()(val); }
107 };
108 
109 template <typename T>
110 SNot<T> Not(T o) { return o; }
111 
113 {
114 public:
115  CCgiEnvHolder(const CRemoteAppLauncher& remote_app_launcher,
116  const CNcbiEnvironment& client_env,
117  const CNetScheduleJob& job,
118  const string& service_name,
119  const string& queue_name);
120 
121  const char* const* GetEnv() const { return &m_Env[0]; }
122 
123 private:
124  list<string> m_EnvValues;
125  vector<const char*> m_Env;
126 };
127 
129  const CNcbiEnvironment& client_env,
130  const CNetScheduleJob& job,
131  const string& service_name,
132  const string& queue_name)
133 {
134  list<string> cln_names;
135  client_env.Enumerate(cln_names);
136  list<string> names(cln_names.begin(), cln_names.end());
137 
138  names.erase(remove_if(names.begin(), names.end(),
139  Not(IsStandard())), names.end());
140 
141  names.erase(remove_if(names.begin(), names.end(),
142  HasValue<list<string> >(remote_app_launcher.GetExcludedEnv())),
143  names.end());
144 
145  list<string> inc_names(cln_names.begin(), cln_names.end());
146 
147  inc_names.erase(remove_if(inc_names.begin(),inc_names.end(),
148  Not(HasValue<list<string> >(remote_app_launcher.GetIncludedEnv()))),
149  inc_names.end());
150 
151  names.insert(names.begin(),inc_names.begin(), inc_names.end());
152  const CRemoteAppLauncher::TEnvMap& added_env =
153  remote_app_launcher.GetAddedEnv();
154  ITERATE(CRemoteAppLauncher::TEnvMap, it, added_env) {
155  m_EnvValues.push_back(it->first + "=" +it->second);
156  }
157 
158  ITERATE(list<string>, it, names) {
159  if (added_env.find(*it) == added_env.end())
160  m_EnvValues.push_back(*it + "=" + client_env.Get(*it));
161  }
162 
163  list<string> local_names;
164  const CNcbiEnvironment& local_env = remote_app_launcher.GetLocalEnv();
165  local_env.Enumerate(local_names);
166  ITERATE(list<string>, it, local_names) {
167  const string& s = *it;
168  if (added_env.find(s) == added_env.end()
169  && find(names.begin(), names.end(), s) == names.end())
170  m_EnvValues.push_back(s + "=" + local_env.Get(s));
171  }
172 
173  m_EnvValues.push_back("NCBI_NS_SERVICE=" + service_name);
174  m_EnvValues.push_back("NCBI_NS_QUEUE=" + queue_name);
175  m_EnvValues.push_back("NCBI_NS_JID=" + job.job_id);
176  m_EnvValues.push_back("NCBI_JOB_AFFINITY=" + job.affinity);
177 
178  if (!job.client_ip.empty())
179  m_EnvValues.push_back("NCBI_LOG_CLIENT_IP=" + job.client_ip);
180 
181  if (!job.session_id.empty())
182  m_EnvValues.push_back("NCBI_LOG_SESSION_ID=" + job.session_id);
183 
184  if (!job.page_hit_id.empty())
185  m_EnvValues.push_back("NCBI_LOG_HIT_ID=" + job.page_hit_id);
186 
187  ITERATE(list<string>, it, m_EnvValues) {
188  m_Env.push_back(it->c_str());
189  }
190  m_Env.push_back(NULL);
191 }
192 
193 
194 ///////////////////////////////////////////////////////////////////////
195 
197 {
198 public:
200  const CRemoteAppLauncher& remote_app_launcher);
201 
202  virtual ~CRemoteCgiJob() {}
203 
205 
206 private:
208 };
209 
211 {
212  if (context.IsLogRequested()) {
213  LOG_POST(Note << "Job " << context.GetJobKey() + " input: " +
214  context.GetJobInput());
215  }
216 
217  unique_ptr<CCgiRequest> request;
218 
219  try {
220  request.reset(new CCgiRequest(context.GetIStream(),
223  }
224  catch (exception&) {
225  ERR_POST("Cannot deserialize remote_cgi job");
226  context.CommitJobWithFailure(
227  "Error while parsing CGI request stream");
228  return -1;
229  }
230 
232  request->GetEnvironment(),
233  context.GetJob(),
234  context.GetWorkerNode().GetServiceName(),
235  context.GetQueueName());
236  vector<string> args;
237 
238  CNcbiOstrstream err;
239  CNcbiStrstream str_in;
240  CNcbiIstream* in = request->GetInputStream();
241  if (!in)
242  in = &str_in;
243 
244  int ret = -1;
245  bool finished_ok = m_RemoteAppLauncher.ExecRemoteApp(args,
246  *in,
247  context.GetOStream(),
248  err,
249  ret,
250  context,
251  0,
252  env.GetEnv());
253 
254  m_RemoteAppLauncher.FinishJob(finished_ok, ret, context);
255 
256  if (context.IsLogRequested()) {
257  if ( !IsOssEmpty(err) )
258  LOG_POST(Note << "STDERR: " << (string)CNcbiOstrstreamToString(err));
259 
260  LOG_POST(Note << "Job " << context.GetJobKey() <<
261  " is " << context.GetCommitStatusDescription(
262  context.GetCommitStatus()) <<
263  ". Exit code: " << ret <<
264  "; output: " << context.GetJobOutput());
265  }
266 
267  return ret;
268 }
269 
271  const CRemoteAppLauncher& remote_app_launcher) :
272  m_RemoteAppLauncher(remote_app_launcher)
273 {
275 }
276 
277 #define GRID_APP_NAME "remote_cgi"
278 extern const char kGridAppName[] = GRID_APP_NAME;
279 
281 
282 int main(int argc, const char* argv[])
283 {
285  return Main<TRemoteAppJobFactory, CRemoteAppBaseListener>(argc, argv);
286 }
void remove_if(Container &c, Predicate *__pred)
Definition: chainer.hpp:69
vector< const char * > m_Env
const char *const * GetEnv() const
list< string > m_EnvValues
CCgiEnvHolder(const CRemoteAppLauncher &remote_app_launcher, const CNcbiEnvironment &client_env, const CNetScheduleJob &job, const string &service_name, const string &queue_name)
CCgiRequest::
Definition: ncbicgi.hpp:685
void SetReuseJobObject(bool value)
static CGridGlobals & GetInstance()
CNcbiEnvironment –.
Definition: ncbienv.hpp:110
CNcbiOstrstreamToString class helps convert CNcbiOstrstream to a string Sample usage:
Definition: ncbistre.hpp:802
const CNcbiEnvironment & GetLocalEnv() const
const list< string > & GetIncludedEnv() const
const list< string > & GetExcludedEnv() const
void FinishJob(bool finished_ok, int ret, CWorkerNodeJobContext &context) const
bool ExecRemoteApp(const vector< string > &args, CNcbiIstream &in, CNcbiOstream &out, CNcbiOstream &err, int &exit_value, CWorkerNodeJobContext &job_context, unsigned app_run_timeout, const char *const env[]) const
const TEnvMap & GetAddedEnv() const
virtual ~CRemoteCgiJob()
int Do(CWorkerNodeJobContext &context)
Execute the job.
CRemoteCgiJob(const IWorkerNodeInitContext &context, const CRemoteAppLauncher &remote_app_launcher)
const CRemoteAppLauncher & m_RemoteAppLauncher
Worker Node job context.
Worker Node Job interface.
const_iterator end() const
Definition: map.hpp:152
const_iterator find(const key_type &key) const
Definition: map.hpp:153
#define T(s)
Definition: common.h:230
static const struct name_t names[]
static HENV env
Definition: transaction2.c:38
#define GRID_APP_CHECK_VERSION_ARGS()
#define ITERATE(Type, Var, Cont)
ITERATE macro to sequence through container elements.
Definition: ncbimisc.hpp:815
@ fDoNotParseContent
do not automatically parse the request's content body (from "istr")
Definition: ncbicgi.hpp:712
@ fIgnoreQueryString
do not parse $QUERY_STRING (or cmd.line if $REQUEST_METHOD not def)
Definition: ncbicgi.hpp:708
#define NULL
Definition: ncbistd.hpp:225
#define ERR_POST(message)
Error posting with file, line number information but without error codes.
Definition: ncbidiag.hpp:186
#define LOG_POST(message)
This macro is deprecated and it's strongly recomended to move in all projects (except tests) to macro...
Definition: ncbidiag.hpp:226
const string & Get(const string &name, bool *found=NULL) const
Get environment value by name.
Definition: ncbienv.cpp:109
void Enumerate(list< string > &names, const string &prefix=kEmptyStr) const
Find all variable names starting with an optional prefix.
Definition: ncbienv.cpp:133
string job_id
Output job key.
bool IsOssEmpty(CNcbiOstrstream &oss)
Definition: ncbistre.hpp:831
IO_PREFIX::istream CNcbiIstream
Portable alias for istream.
Definition: ncbistre.hpp:146
static int Compare(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n, const char *s2, ECase use_case=eCase)
Compare of a substring with another string.
Definition: ncbistr.hpp:5297
static bool StartsWith(const CTempString str, const CTempString start, ECase use_case=eCase)
Check if a string starts with a specified prefix value.
Definition: ncbistr.hpp:5412
where both of them are integers Note
int i
std::istream & in(std::istream &in_, double &x_)
SNot< T > Not(T o)
const char kGridAppName[]
#define GRID_APP_NAME
int main(int argc, const char *argv[])
USING_NCBI_SCOPE
Job description.
HasValue(const Cont &cont)
const Cont & m_Cont
string argument_type
bool operator()(const string &val) const
static const char *const sm_StandardCgiEnv[]
bool operator()(const string &val) const
string argument_type
SNot(T o)
bool operator()(const string &val) const
static CS_CONTEXT * context
Definition: will_convert.c:21
Modified on Wed May 22 11:30:57 2024 by modify_doxy.py rev. 669887