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

Go to the SVN repository for this file.

1 /* $Id: cgi2rcgi.cpp 81054 2018-01-31 16:38:31Z sadyrovr $
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  * Author: Maxim Didenko, Dmitry Kazimirov
27  *
28  * File Description:
29  *
30  */
31 
32 #include <ncbi_pch.hpp>
33 
34 #include <cgi/cgiapp_cached.hpp>
35 #include <cgi/cgictx.hpp>
36 #include <cgi/cgi_serial.hpp>
37 
38 #include <html/commentdiag.hpp>
39 #include <html/html.hpp>
40 #include <html/page.hpp>
41 
42 #include <util/xregexp/regexp.hpp>
43 #include <util/checksum.hpp>
44 #include <util/retry_ctx.hpp>
45 
48 
50 
51 #include <corelib/ncbistr.hpp>
52 #include <corelib/ncbimisc.hpp>
53 #include <corelib/ncbi_system.hpp>
54 
55 #include <array>
56 #include <vector>
57 #include <map>
58 #include <sstream>
59 #include <unordered_map>
60 
61 #define GRID_APP_NAME "cgi2rcgi"
62 
64 
65 #define HTTP_NCBI_JSID "NCBI-JSID"
66 
67 static const string kSinceTime = "ctg_time";
68 
69 
70 /** @addtogroup NetScheduleClient
71  *
72  * @{
73  */
74 
75 /////////////////////////////////////////////////////////////////////////////
76 // Grid Cgi Context
77 // Context in which a request is processed
78 //
79 class CGridCgiContext
80 {
81 public:
83  CHTMLPage& custom_http_header, CCgiContext& ctx);
84 
85  // Get the HTML page
86  CHTMLPage& GetHTMLPage() { return m_Page; }
87 
88  // Get the self URL
89  string GetSelfURL() const;
90 
91  // Get current job progress message
92  const string& GetJobProgressMessage() const
93  { return m_ProgressMsg; }
94 
95  // Get a value from a CGI request. if there is no an entry with a
96  // given name it returns an empty string.
97  const string& GetPersistentEntryValue(const string& entry_name) const;
98 
99  void GetQueryStringEntryValue(const string& entry_name,
100  string& value) const;
101  void GetRequestEntryValue(const string& entry_name, string& value) const;
102 
104 
105  void PullUpPersistentEntry(const string& entry_name);
106  void PullUpPersistentEntry(const string& entry_name, string& value);
107  void DefinePersistentEntry(const string& entry_name, const string& value);
108  const TPersistentEntries& GetPersistentEntries() const
109  { return m_PersistentEntries; }
110 
112 
113  // Get CGI Context
115 
116  void SelectView(const string& view_name);
117  bool NeedRenderPage() const { return m_NeedRenderPage; }
119  bool NeedMetaRefresh() const { return m_NeedMetaRefresh; }
120 
121  string& GetJobKey() { return m_JobKey; }
122  string& GetJqueryCallback() { return m_JqueryCallback; }
123 
124 public:
125  // Remove all persistent entries from cookie and self url.
126  void Clear();
127 
128  void SetJobProgressMessage(const string& msg)
129  { m_ProgressMsg = msg; }
130 
131 private:
132  CHTMLPage& m_Page;
136  TPersistentEntries m_PersistentEntries;
137  string m_ProgressMsg;
138  string m_JobKey;
140  bool m_NeedRenderPage;
142 };
143 
144 
145 /////////////////////////////////////////////////////////////////////////////
146 
147 
149  CHTMLPage& custom_http_header, CCgiContext& ctx) :
150  m_Page(page),
151  m_CustomHTTPHeader(custom_http_header),
152  m_CgiContext(ctx),
153  m_NeedRenderPage(true)
154 {
155  const CCgiRequest& req = ctx.GetRequest();
156  string query_string = req.GetProperty(eCgi_QueryString);
158 
159  const string kNoMetaRefreshHeader = "X_NCBI_RETRY_NOMETAREFRESH";
160  const string& no_meta_refresh = req.GetRandomProperty(kNoMetaRefreshHeader);
161  m_NeedMetaRefresh = no_meta_refresh.empty() || no_meta_refresh == "0";
162 }
163 
165 {
166  string url = m_CgiContext.GetSelfURL();
167  bool first = true;
169  for (it = m_PersistentEntries.begin();
170  it != m_PersistentEntries.end(); ++it) {
171  const string& name = it->first;
172  const string& value = it->second;
173  if (!name.empty() && !value.empty()) {
174  if (first) {
175  url += '?';
176  first = false;
177  }
178  else
179  url += '&';
180  url += name + '=' + NStr::URLEncode(value);
181  }
182  }
183  return url;
184 }
185 
187  const string& entry_name) const
188 {
190  if (it != m_PersistentEntries.end())
191  return it->second;
192  return kEmptyStr;
193 }
194 
195 void CGridCgiContext::GetQueryStringEntryValue(const string& entry_name,
196  string& value) const
197 {
199  if (NStr::CompareNocase(entry_name, eit->first) == 0) {
200  string v = eit->second;
201  if (!v.empty())
202  value = v;
203  }
204  }
205 }
206 
207 void CGridCgiContext::GetRequestEntryValue(const string& entry_name,
208  string& value) const
209 {
211  ITERATE(TCgiEntries, eit, entries) {
212  if (NStr::CompareNocase(entry_name, eit->first) == 0) {
213  string v = eit->second;
214  if (!v.empty())
215  value = v;
216  }
217  }
218 }
219 
220 void CGridCgiContext::PullUpPersistentEntry(const string& entry_name)
221 {
222  string value = kEmptyStr;
223  PullUpPersistentEntry(entry_name, value);
224 }
225 
227  const string& entry_name, string& value)
228 {
229  GetQueryStringEntryValue(entry_name, value);
230  if (value.empty())
231  GetRequestEntryValue(entry_name, value);
233  DefinePersistentEntry(entry_name, value);
234 }
235 
236 void CGridCgiContext::DefinePersistentEntry(const string& entry_name,
237  const string& value)
238 {
239  if (value.empty()) {
241  m_PersistentEntries.find(entry_name);
242  if (it != m_PersistentEntries.end())
244  } else {
245  m_PersistentEntries[entry_name] = value;
246  }
247 }
248 
250  CHTMLPlainText::EEncodeMode encode_mode)
251 {
253  string tag("QUERY_STRING:" + eit->first);
254  m_Page.AddTagMap(tag, new CHTMLPlainText(encode_mode, eit->second));
256  new CHTMLPlainText(encode_mode, eit->second));
257  }
258 }
259 
261 {
263 }
264 
265 void CGridCgiContext::SelectView(const string& view_name)
266 {
267  m_CustomHTTPHeader.AddTagMap("CUSTOM_HTTP_HEADER",
268  new CHTMLText("<@HEADER_" + view_name + "@>"));
269  m_Page.AddTagMap("STAT_VIEW", new CHTMLText("<@VIEW_" + view_name + "@>"));
270 }
271 
272 /////////////////////////////////////////////////////////////////////////////
273 //
274 // Grid CGI Front-end Application
275 //
276 // Class for CGI applications starting background jobs using
277 // NetSchedule. Implements job submission, status check,
278 // error processing, etc. All request processing is done on the back end.
279 // CGI application is responsible for UI rendering.
280 //
282 {
283 public:
284  // This method is called on the CGI application initialization -- before
285  // starting to process a HTTP request or even receiving one.
286  virtual void Init();
287 
288  // Factory method for the Context object construction.
291  int ifd, int ofd, int flags);
292 
293  // The main method of this CGI application.
294  // HTTP requests are processed in this method.
295  virtual int ProcessRequest(CCgiContext& ctx);
296 
297 private:
298  void DefineRefreshTags(CGridCgiContext& grid_ctx, const string& url, int delay);
299 
300 private:
301  void ListenJobs(CCgiContext& ctx, const string& job_ids_value, const string& timeout_value);
302  void CheckJob(CGridCgiContext& grid_ctx);
303  void SubmitJob(CCgiRequest& request, CGridCgiContext& grid_ctx);
304  void PopulatePage(CGridCgiContext& grid_ctx);
305  int RenderPage();
308 
312 
315  auto_ptr<CGridClient> m_GridClient;
317 
318 private:
319  enum {
322  };
323 
324  // This method is called when result is available immediately
325  void OnJobDone(CGridCgiContext&);
326 
327  // This method is called when the worker node reported a failure.
328  void OnJobFailed(const string& msg, CGridCgiContext& ctx);
329 
330  string m_Title;
334  string m_DateFormat;
338 
339  auto_ptr<CHTMLPage> m_Page;
340  auto_ptr<CHTMLPage> m_CustomHTTPHeader;
341 
343  vector<string> m_HtmlIncs;
344 
348 
350 
354 };
355 
357 {
358  // Standard CGI framework initialization
360 
361  // Grid client initialization
363  string grid_cgi_section("grid_cgi");
364 
365  // Must correspond to TEnableVersionRequest
366  config.Set("CGI", "EnableVersionRequest", "false");
367 
368  // Default value must correspond to SRCgiWait value
369  m_RefreshDelay = config.GetInt(grid_cgi_section,
370  "refresh_delay", 5, IRegistry::eReturn);
371 
372  m_RefreshWait = config.GetInt(grid_cgi_section,
373  "refresh_wait", 0, IRegistry::eReturn);
374  if (m_RefreshWait < 0) m_RefreshWait = 0;
375  if (m_RefreshWait > 20) m_RefreshWait = 20;
376 
377  m_FirstDelay = config.GetInt(grid_cgi_section,
378  "expect_complete", 5, IRegistry::eReturn);
379 
380  if (m_FirstDelay > 20)
381  m_FirstDelay = 20;
382 
383  if (m_FirstDelay < 0)
384  m_FirstDelay = 0;
385 
388 
389  m_GridClient.reset(new CGridClient(
392  config.GetBool(grid_cgi_section, "automatic_cleanup",
393  true, IRegistry::eReturn) ?
395  config.GetBool(grid_cgi_section, "use_progress",
396  true, IRegistry::eReturn) ?
398 
399  // Allows CGI client to put the diagnostics to:
400  // HTML body (as comments) -- using CGI arg "&diag-destination=comments"
401  RegisterDiagFactory("comments", new CCommentDiagFactory);
402  // E-mail -- using CGI arg "&diag-destination=email:user@host"
404 
405 
406  // Initialize processing of both cmd-line arguments and HTTP entries
407 
408  // Create CGI argument descriptions class
409  // (For CGI applications only keys can be used)
410  auto_ptr<CArgDescriptions> arg_desc(new CArgDescriptions);
411 
412  // Specify USAGE context
413  arg_desc->SetUsageContext(GetArguments().GetProgramBasename(),
414  "Cgi2RCgi application");
415 
416  arg_desc->AddOptionalKey("Cancel",
417  "Cancel",
418  "Cancel Job",
420 
421  // Setup arg.descriptions for this application
422  SetupArgDescriptions(arg_desc.release());
423 
424  // Read configuration parameters
425  string cgi2rcgi_section("cgi2rcgi");
426 
427  m_ContentType = config.GetString(cgi2rcgi_section,
428  "content_type", kEmptyStr);
429  if (m_ContentType.empty() || m_ContentType == "text/html") {
431  m_HTMLPassThrough = config.GetBool(cgi2rcgi_section,
432  "html_pass_through", false);
433  } else {
434  m_TargetEncodeMode = m_ContentType == "application/json" ?
436  m_HTMLPassThrough = true;
437  }
438 
439  m_Title = config.GetString(cgi2rcgi_section, "cgi_title",
440  "Remote CGI Status Checker");
441 
442  m_HtmlTemplate = config.GetString(cgi2rcgi_section, "html_template",
443  "cgi2rcgi.html");
444 
445  string incs = config.GetString(cgi2rcgi_section, "html_template_includes",
446  "cgi2rcgi.inc.html");
447 
448  NStr::Split(incs, ",; ", m_HtmlIncs,
450 
451 
452  m_FallBackUrl = config.GetString(cgi2rcgi_section,
453  "fall_back_url", kEmptyStr);
454  m_FallBackDelay = config.GetInt(cgi2rcgi_section,
455  "error_fall_back_delay", -1, IRegistry::eReturn);
456 
457  m_CancelGoBackDelay = config.GetInt(cgi2rcgi_section,
458  "cancel_fall_back_delay", 0, IRegistry::eReturn);
459 
460  if (m_FallBackUrl.empty()) {
461  m_FallBackDelay = -1;
462  m_CancelGoBackDelay = -1;
463  }
464 
465  m_AffinitySource = 0;
466  m_AffinitySetLimit = 0;
467  m_AffinityName = config.GetString(cgi2rcgi_section,
468  "affinity_name", kEmptyStr);
469 
470  if (!m_AffinityName.empty()) {
471  vector<string> affinity_methods;
472  NStr::Split(config.GetString(cgi2rcgi_section,
473  "affinity_source", "GET"), ", ;&|", affinity_methods,
475  for (vector<string>::const_iterator it = affinity_methods.begin();
476  it != affinity_methods.end(); ++it) {
477  if (*it == "GET")
479  else if (*it == "POST")
481  else {
482  NCBI_THROW_FMT(CArgException, eConstraint,
483  "Invalid affinity_source value '" << *it << '\'');
484  }
485  }
486  m_AffinitySetLimit = config.GetInt(cgi2rcgi_section,
487  "narrow_affinity_set_to", 0);
488  }
489 
490  // Disregard the case of CGI arguments
492 
493  if (config.GetBool(cgi2rcgi_section, "donot_parse_content",
494  true, IRegistry::eReturn) &&
497 
498  SetRequestFlags(flags);
499 
500  m_DateFormat = config.GetString(cgi2rcgi_section,
501  "date_format", "D B Y, h:m:s");
502 
503  m_ElapsedTimeFormat = config.GetString(cgi2rcgi_section,
504  "elapsed_time_format", "S");
505 
506  m_InterceptJQueryCallback = config.GetBool("CGI", "CORS_JQuery_Callback_Enable",
507  false, IRegistry::eReturn);
508 
509  m_AddJobIdToHeader = config.GetBool(cgi2rcgi_section, "add_job_id_to_response",
510  false, IRegistry::eReturn);
511 
512  m_PortAdded = false;
513 }
514 
517  int ifd, int ofd, int flags)
518 {
521  inp, out, ifd, ofd, flags);
522 
525  inp, out, ifd, ofd, flags | CCgiRequest::fSaveRequestContent);
526 
527  // The 'env' argument is only valid in FastCGI mode.
528  if (env == NULL)
529  env = &SetEnvironment();
530 
531  size_t content_length = 0;
532 
533  try {
534  content_length = (size_t) NStr::StringToUInt(
536  }
537  catch (...) {
538  }
539 
540  // Based on the CONTENT_LENGTH CGI parameter, decide whether to parse
541  // the POST request in search of the job_key parameter.
542  return CCgiApplicationCached::CreateContextWithFlags(args, env, inp,
543  out, ifd, ofd, flags | (content_length > 0 &&
544  content_length < 128 ? CCgiRequest::fSaveRequestContent :
545  CCgiRequest::fDoNotParseContent));
546 }
547 
548 static const string kGridCgiForm =
549  "<FORM METHOD=\"GET\" ACTION=\"<@SELF_URL@>\">\n"
550  "<@HIDDEN_FIELDS@>\n<@STAT_VIEW@>\n"
551  "</FORM>";
552 
553 static const string kPlainTextView = "<@STAT_VIEW@>";
554 
556 {
557 public:
559 
560  virtual bool TestAttribute(const string& attr_name,
561  const string& test_pattern);
562 
563 private:
565 };
566 
567 bool CRegexpTemplateFilter::TestAttribute(const string& attr_name,
568  const string& test_pattern)
569 {
570  CNCBINode* node = m_Page->MapTag(attr_name);
571 
572  if (node == NULL)
573  return false;
574 
575  CNcbiOstrstream node_stream;
576 
577  node->Print(node_stream, CNCBINode::ePlainText);
578 
579  CRegexp regexp(test_pattern, CRegexp::fCompile_ignore_case);
580 
581  return regexp.IsMatch(node_stream.str());
582 }
583 
584 #define CALLBACK_PARAM "callback="
585 
586 static void s_RemoveCallbackParameter(string* query_string)
587 {
588  SIZE_TYPE callback_pos = NStr::Find(*query_string, CALLBACK_PARAM);
589 
590  if (callback_pos == NPOS)
591  return;
592 
593  // See if 'callback' is the last parameter in the query string.
594  const char* callback_end = strchr(query_string->c_str() +
595  callback_pos + sizeof(CALLBACK_PARAM) - 1, '&');
596  if (callback_end != NULL)
597  query_string->erase(callback_pos,
598  callback_end - query_string->data() - callback_pos + 1);
599  else if (callback_pos == 0)
600  query_string->clear();
601  else if (query_string->at(callback_pos - 1) == '&')
602  query_string->erase(callback_pos - 1);
603 }
604 
606 {
608 
609  // Add server port to client node name.
610  if (!m_PortAdded) {
611  m_PortAdded = true;
612  const string port(env.Get(CCgiRequest::GetPropertyName(eCgi_ServerPort)));
614  }
615 
616  // Given "CGI context", get access to its "HTTP request" and
617  // "HTTP response" sub-objects
618  CCgiRequest& request = ctx.GetRequest();
619  m_Response = &ctx.GetResponse();
621 
624 
625  // Create an HTML page (using the template HTML file)
626  try {
627  m_Page.reset(new CHTMLPage(m_Title, m_HtmlTemplate));
628  CHTMLText* stat_view = new CHTMLText(!m_HTMLPassThrough ?
630  m_Page->AddTagMap("VIEW", stat_view);
631  }
632  catch (exception& e) {
633  ERR_POST("Failed to create " << m_Title << " HTML page: " << e.what());
634  return 2;
635  }
636  m_CustomHTTPHeader.reset(new CHTMLPage);
637  m_CustomHTTPHeader->SetTemplateString("<@CUSTOM_HTTP_HEADER@>");
638  CGridCgiContext grid_ctx(*m_Page, *m_CustomHTTPHeader, ctx);
639 
640  string listen_jobs;
641  string timeout;
642  grid_ctx.PullUpPersistentEntry("listen_jobs", listen_jobs);
643  grid_ctx.PullUpPersistentEntry("timeout", timeout);
644 
645  grid_ctx.PullUpPersistentEntry("job_key", grid_ctx.GetJobKey());
646  grid_ctx.PullUpPersistentEntry("Cancel");
647 
649 
651 
652  try {
654  TCgiEntries& entries = request.GetEntries();
655  TCgiEntries::iterator jquery_callback_it = entries.find("callback");
656  if (jquery_callback_it != entries.end()) {
657  grid_ctx.GetJqueryCallback() = jquery_callback_it->second;
658  entries.erase(jquery_callback_it);
659  string query_string_param(
661  string query_string = env.Get(query_string_param);
662  if (!query_string.empty()) {
663  s_RemoveCallbackParameter(&query_string);
664  env.Set(query_string_param, query_string);
665  }
666  }
667  }
668 
670 
671  try {
672  if (!listen_jobs.empty()) {
673  ListenJobs(ctx, listen_jobs, timeout);
674  grid_ctx.NeedRenderPage(false);
675  } else
676  if (!grid_ctx.GetJobKey().empty()) {
677  CheckJob(grid_ctx);
678  } else {
679  SubmitJob(request, grid_ctx);
680  }
681  } // try
682  catch (exception& ex) {
683  ERR_POST("Job's reported as failed: " << ex.what());
684  OnJobFailed(ex.what(), grid_ctx);
685  }
686 
687  if (grid_ctx.NeedRenderPage()) PopulatePage(grid_ctx);
688  } //try
689  catch (exception& e) {
690  ERR_POST("Failed to populate " << m_Title <<
691  " HTML page: " << e.what());
692  return 3;
693  }
694 
695  return grid_ctx.NeedRenderPage() ? RenderPage() : 0;
696 }
697 
699 {
700  switch (job_status) {
703  return true;
704 
705  default:
706  return false;
707  }
708 }
709 
711 {
714 
715  SJob(const string& id) { job_id = id; }
716 };
717 
718 void CCgi2RCgiApp::ListenJobs(CCgiContext& ctx, const string& job_ids_value, const string& timeout_value)
719 {
720  CTimeout timeout;
721 
722  try {
723  timeout.Set(NStr::StringToDouble(timeout_value));
724  }
725  catch (...) {
726  }
727 
728  CDeadline deadline(timeout);
729 
730  vector<string> job_ids;
731  NStr::Split(job_ids_value, ",", job_ids);
732 
733  if (job_ids.empty()) return;
734 
735  unordered_map<string, SJob> jobs;
736 
737  for (const auto& job_id : job_ids) {
738  jobs.emplace(job_id, job_id);
739  }
740 
741 
742  // Request notifications unless there is a job that is already not pending/running
743 
744  CNetScheduleSubmitter submitter = m_GridClient->GetNetScheduleSubmitter();
746 
747  bool wait_notifications = true;
748 
749  for (auto&& j : jobs) {
750  const auto& job_id = j.first;
751  auto& job = j.second;
752 
753  wait_notifications = wait_notifications && !deadline.IsExpired();
754 
755  try {
756  if (wait_notifications) {
757  tie(job.status, ignore, job.progress_msg) =
758  handler.RequestJobWatching(m_NetScheduleAPI, job_id, deadline);
759  } else {
760  job.status = m_NetScheduleAPI.GetJobDetails(job);
761  }
762  } catch (CNetScheduleException& ex) {
764  job.status = CNetScheduleAPI::eJobNotFound;
765  }
766 
767  wait_notifications = wait_notifications && s_IsPendingOrRunning(job.status);
768  }
769 
770 
771  // If all jobs are still pending/running, wait for a notification
772 
773  if (wait_notifications) {
774  while (handler.WaitForNotification(deadline)) {
775  SNetScheduleOutputParser parser(handler.GetMessage());
776 
777  auto it = jobs.find(parser("job_key"));
778 
779  // If it's one of requested jobs
780  if (it != jobs.end()) {
781  auto& job = it->second;
782  job.status = CNetScheduleAPI::StringToStatus(parser("job_status"));
783  job.progress_msg = parser("msg");
784  job.progress_msg_truncated = !parser("msg_truncated").empty();
785 
786  if (!s_IsPendingOrRunning(job.status)) break;
787  }
788  }
789 
790  // Recheck still pending/running jobs, just in case
791  for (auto&& j : jobs) {
792  auto& job = j.second;
793 
794  if (s_IsPendingOrRunning(job.status)) {
795  job.progress_msg_truncated = false;
796 
797  try {
798  job.status = m_NetScheduleAPI.GetJobDetails(job);
799  } catch (CNetScheduleException& ex) {
801  job.status = CNetScheduleAPI::eJobNotFound;
802  job.progress_msg.clear();
803  }
804  }
805  }
806  }
807 
808 
809  // Output jobs and their current states
810 
811  CNcbiOstream& out = ctx.GetResponse().out();
812  char delimiter = '{';
813  out << "Content-type: application/json\nStatus: 200 OK\n\n";
814 
815  for (const auto& j : jobs) {
816  const auto& job_id = j.first;
817  const auto& job = j.second;
818 
819  const auto status = CNetScheduleAPI::StatusToString(job.status);
820  const auto message = NStr::JsonEncode(job.progress_msg);
821  out << delimiter << "\n \"" << job_id << "\":\n {\n \"Status\": \"" << status << "\"";
822 
823  if (!job.progress_msg.empty()) {
824  out << ",\n \"Message\": \"" << message << "\"";
825  if (job.progress_msg_truncated) out << ",\n \"Truncated\": true";
826  }
827 
828  out << "\n }";
829  delimiter = ',';
830  }
831 
832  out << "\n}" << endl;
833 }
834 
836 {
837  bool done = true;
838 
839  GetDiagContext().Extra().Print("ctg_poll", "true");
840  m_GridClient->SetJobKey(grid_ctx.GetJobKey());
841 
842  if (m_RefreshWait) {
843  CDeadline wait_deadline(m_RefreshWait);
844 
847  grid_ctx.GetJobKey(),
848  wait_deadline,
852  done = CheckIfJobDone(grid_ctx, status);
853  } else {
854  done = CheckIfJobDone(grid_ctx);
855  }
856 
857  if (done)
858  grid_ctx.Clear();
859  else {
860  // Check if job cancellation has been requested
861  // via the user interface(HTML).
862  if (GetArgs()["Cancel"] ||
863  !grid_ctx.GetPersistentEntryValue("Cancel").empty())
864  m_GridClient->CancelJob(grid_ctx.GetJobKey());
865 
866  DefineRefreshTags(grid_ctx, grid_ctx.GetSelfURL(), m_RefreshDelay);
867  }
868 }
869 
871  CGridCgiContext& grid_ctx)
872 {
873  bool done = true;
874 
875  if (!m_AffinityName.empty()) {
876  string affinity;
879  affinity);
880  if (affinity.empty() &&
882  grid_ctx.GetRequestEntryValue(m_AffinityName, affinity);
883  if (!affinity.empty()) {
884  if (m_AffinitySetLimit > 0) {
886  crc32.AddChars(affinity.data(), affinity.length());
887  affinity = NStr::UIntToString(
888  crc32.GetChecksum() % m_AffinitySetLimit);
889  }
890  m_GridClient->SetJobAffinity(affinity);
891  }
892  }
893  try {
894  // The job is ready to be sent to the queue.
895  // Prepare the input data.
896  CNcbiOstream& os = m_GridClient->GetOStream();
897  // Send the input data.
898  request.Serialize(os);
899  string saved_content(kEmptyStr);
900  try {
901  saved_content = request.GetContent();
902  }
903  catch (...) {
904  // An exception is normal when the content
905  // is not saved, disregard the exception.
906  }
907  if (!saved_content.empty())
908  os.write(saved_content.data(), saved_content.length());
909 
912 
913  CNetScheduleAPI::EJobStatus status = m_GridClient->SubmitAndWait(m_FirstDelay);
914 
915  CNetScheduleJob& job(m_GridClient->GetJob());
916 
917  grid_ctx.GetJobKey() = job.job_id;
918 
919  grid_ctx.DefinePersistentEntry("job_key", grid_ctx.GetJobKey());
920  GetDiagContext().Extra().Print("job_key", grid_ctx.GetJobKey());
921 
922  done = !s_IsPendingOrRunning(status) && CheckIfJobDone(grid_ctx, status);
923 
924  if (!done) {
925  // The job has just been submitted.
926  // Render a report page
927  grid_ctx.SelectView("JOB_SUBMITTED");
928  DefineRefreshTags(grid_ctx, grid_ctx.GetSelfURL(),
930  }
931  }
932  catch (CNetScheduleException& ex) {
933  ERR_POST("Failed to submit a job: " << ex.what());
934  OnJobFailed(ex.GetErrCode() ==
936  "NetSchedule Queue is busy" : ex.what(), grid_ctx);
937  done = true;
938  }
939  catch (exception& ex) {
940  ERR_POST("Failed to submit a job: " << ex.what());
941  OnJobFailed(ex.what(), grid_ctx);
942  done = true;
943  }
944 
945  if (done)
946  grid_ctx.Clear();
947 }
948 
950 {
951  CHTMLPlainText* self_url =
952  new CHTMLPlainText(grid_ctx.GetSelfURL(), true);
953  m_Page->AddTagMap("SELF_URL", self_url);
954  m_CustomHTTPHeader->AddTagMap("SELF_URL", self_url);
955 
956  if (!m_HTMLPassThrough) {
957  // Preserve persistent entries as hidden fields
958  string hidden_fields;
960  grid_ctx.GetPersistentEntries().begin();
961  it != grid_ctx.GetPersistentEntries().end(); ++it)
962  hidden_fields += "<INPUT TYPE=\"HIDDEN\" NAME=\"" + it->first
963  + "\" VALUE=\"" + it->second + "\">\n";
964  m_Page->AddTagMap("HIDDEN_FIELDS",
965  new CHTMLPlainText(hidden_fields, true));
966  }
967 
968  CTime now(GetFastLocalTime());
969  m_Page->AddTagMap("DATE",
970  new CHTMLText(now.AsString(m_DateFormat)));
971  string since_time = grid_ctx.GetPersistentEntryValue(kSinceTime);
972  if (!since_time.empty()) {
973  m_Page->AddTagMap("SINCE_TIME", new CHTMLText(since_time));
974  m_CustomHTTPHeader->AddTagMap("SINCE_TIME",
975  new CHTMLText(since_time));
976  time_t tt = NStr::StringToInt(since_time);
977  CTime start;
978  start.SetTimeT(tt);
979  m_Page->AddTagMap("SINCE",
980  new CHTMLText(start.AsString(m_DateFormat)));
981  CTimeSpan ts = now - start;
982  m_Page->AddTagMap("ELAPSED_TIME_MSG_HERE",
983  new CHTMLText("<@ELAPSED_TIME_MSG@>"));
984  m_Page->AddTagMap("ELAPSED_TIME",
986  }
987  m_Page->AddTagMap("JOB_ID", new CHTMLText(grid_ctx.GetJobKey()));
988  m_CustomHTTPHeader->AddTagMap("JOB_ID", new CHTMLText(grid_ctx.GetJobKey()));
989  if (m_AddJobIdToHeader) {
991  }
992  string progress_message;
993  try {
994  progress_message = m_GridClient->GetProgressMessage();
995  }
996  catch (CException& e) {
997  ERR_POST("Could not retrieve progress message for " <<
998  grid_ctx.GetJobKey() << ": " << e);
999  }
1000  grid_ctx.SetJobProgressMessage(progress_message);
1001  grid_ctx.GetHTMLPage().AddTagMap("PROGERSS_MSG",
1002  new CHTMLPlainText(m_TargetEncodeMode, progress_message));
1003  grid_ctx.GetHTMLPage().AddTagMap("PROGRESS_MSG",
1004  new CHTMLPlainText(m_TargetEncodeMode, progress_message));
1005 }
1006 
1008 {
1009  // Compose and flush the resultant HTML page
1010  try {
1011  CRegexpTemplateFilter filter(m_Page.get());
1012 
1013  vector<string>::const_iterator it;
1014  for (it = m_HtmlIncs.begin(); it != m_HtmlIncs.end(); ++it) {
1015  string lib = NStr::TruncateSpaces(*it);
1016  m_Page->LoadTemplateLibFile(lib, &filter);
1017  m_CustomHTTPHeader->LoadTemplateLibFile(lib, &filter);
1018  }
1019 
1020  stringstream header_stream;
1021  m_CustomHTTPHeader->Print(header_stream, CNCBINode::ePlainText);
1022 
1023  string header_line;
1024  string status_line;
1025 
1026  enum {
1027  eNoStatusLine,
1028  eReadingStatusLine,
1029  eGotStatusLine
1030  } status_line_status = eNoStatusLine;
1031 
1033  while (header_stream.good()) {
1034  getline(header_stream, header_line);
1035  if (header_line.empty())
1036  continue;
1037  if (status_line_status == eReadingStatusLine) {
1038  if (isspace(header_line[0])) {
1039  status_line += header_line;
1040  continue;
1041  }
1042  status_line_status = eGotStatusLine;
1043  }
1044  if (NStr::StartsWith(header_line, "Status:", NStr::eNocase)) {
1045  status_line_status = eReadingStatusLine;
1046  status_line = header_line;
1047  continue;
1048  }
1049  out << header_line << "\r\n";
1050  }
1051  if (status_line_status != eNoStatusLine) {
1052  CTempString status_code_and_reason(
1053  status_line.data() + (sizeof("Status:") - 1),
1054  status_line.size() - (sizeof("Status:") - 1));
1055  NStr::TruncateSpacesInPlace(status_code_and_reason);
1056  CTempString status_code, reason;
1057  NStr::SplitInTwo(status_code_and_reason, CTempString(" \t", 2),
1058  status_code, reason,
1060  m_Response->SetStatus(NStr::StringToUInt(status_code), reason);
1061  }
1063  m_Page->Print(out, CNCBINode::eHTML);
1064  }
1065  catch (exception& e) {
1066  ERR_POST("Failed to compose/send " << m_Title <<
1067  " HTML page: " << e.what());
1068  return 4;
1069  }
1070 
1071  return 0;
1072 }
1073 
1075  const string& url, int idelay)
1076 {
1077  const auto idelay_str = NStr::IntToString(idelay);
1078 
1079  if (!m_HTMLPassThrough && idelay >= 0 && grid_ctx.NeedMetaRefresh()) {
1080  CHTMLText* redirect = new CHTMLText(
1081  "<META HTTP-EQUIV=Refresh "
1082  "CONTENT=\"<@REDIRECT_DELAY@>; URL=<@REDIRECT_URL@>\">");
1083  m_Page->AddTagMap("REDIRECT", redirect);
1084 
1085  CHTMLPlainText* delay = new CHTMLPlainText(idelay_str);
1086  m_Page->AddTagMap("REDIRECT_DELAY", delay);
1087  }
1088 
1089  CHTMLPlainText* h_url = new CHTMLPlainText(url, true);
1090  m_Page->AddTagMap("REDIRECT_URL", h_url);
1091  m_CustomHTTPHeader->AddTagMap("REDIRECT_URL", h_url);
1092  m_Response->SetHeaderValue("Expires", "0");
1093  m_Response->SetHeaderValue("Pragma", "no-cache");
1094  m_Response->SetHeaderValue("Cache-Control",
1095  "no-cache, no-store, max-age=0, private, must-revalidate");
1096 
1097  if (idelay >= 0) {
1098  m_Response->SetHeaderValue("NCBI-RCGI-RetryURL", url);
1099 
1100  // Must correspond to SRCgiWait values
1103  }
1104 }
1105 
1106 
1108  CGridCgiContext& grid_ctx)
1109 {
1111  try {
1112  status = m_GridClient->GetStatus();
1113  }
1114  catch (CNetSrvConnException& e) {
1115  ERR_POST("Failed to retrieve job status for " <<
1116  grid_ctx.GetJobKey() << ": " << e);
1117 
1119 
1121 
1122  CNetServer bad_server(service.GetServer(key.host, key.port));
1123 
1124  // Skip to the next available server in the service.
1125  // If the server that caused a connection exception
1126  // was the only server in the service, rethrow the
1127  // exception.
1128  CNetServiceIterator it(service.ExcludeServer(bad_server));
1129 
1130  if (!it)
1131  throw;
1132 
1133  CNetScheduleAdmin::TQueueInfo queue_info;
1134 
1135  m_NetScheduleAPI.GetAdmin().GetQueueInfo(it.GetServer(), queue_info);
1136 
1138  grid_ctx.GetPersistentEntryValue(kSinceTime)) +
1139  NStr::StringToUInt(queue_info["timeout"]))
1141  else {
1142  status = CNetScheduleAPI::eRunning;
1143  grid_ctx.GetHTMLPage().AddTagMap("MSG",
1145  "Failed to retrieve job status: " + e.GetMsg()));
1146  }
1147  }
1148 
1149  return CheckIfJobDone(grid_ctx, status);
1150 }
1151 
1153  CGridCgiContext& grid_ctx, CNetScheduleAPI::EJobStatus status)
1154 {
1155  bool done = true;
1156  const string status_str = CNetScheduleAPI::StatusToString(status);
1157  grid_ctx.GetCGIContext().GetResponse().SetHeaderValue("NCBI-RCGI-JobStatus",
1158  status_str);
1159  grid_ctx.GetHTMLPage().AddTagMap("JOB_STATUS",
1160  new CHTMLPlainText(status_str, true));
1161 
1162  switch (status) {
1164  // The worker node has finished the job and the
1165  // result is ready to be retrieved.
1166  OnJobDone(grid_ctx);
1167  break;
1168 
1170  // a job has failed
1171  OnJobFailed(m_GridClient->GetErrorMessage(), grid_ctx);
1172  break;
1173 
1175  // The job has been canceled
1177  // Render a job cancellation page
1178  grid_ctx.SelectView("JOB_CANCELED");
1179 
1180  DefineRefreshTags(grid_ctx, m_FallBackUrl.empty() ?
1181  grid_ctx.GetCGIContext().GetSelfURL() : m_FallBackUrl,
1183  break;
1184 
1186  // The job has expired
1187  OnJobFailed("Job is not found.", grid_ctx);
1188  break;
1189 
1191  // The job is in the NetSchedule queue and
1192  // is waiting for a worker node.
1193  // Render a status report page
1194  grid_ctx.SelectView("JOB_PENDING");
1195  done = false;
1196  break;
1197 
1199  // The job is being processed by a worker node
1200  // Render a status report page
1201  grid_ctx.SelectView("JOB_RUNNING");
1202  done = false;
1203  break;
1204 
1205  default:
1206  LOG_POST(Note << "Unexpected job state");
1207  }
1208  SetRequestId(grid_ctx.GetJobKey(), status == CNetScheduleAPI::eDone);
1209  return done;
1210 }
1211 
1213 {
1214  CNcbiIstream& is = m_GridClient->GetIStream();
1215 
1216  if (m_GridClient->GetBlobSize() > 0) {
1218  bool no_jquery = ctx.GetJqueryCallback().empty();
1219 
1220  // No need to amend anything
1221  if (no_jquery && !m_AddJobIdToHeader) {
1222  NcbiStreamCopy(out, is);
1223  ctx.NeedRenderPage(false);
1224  return;
1225  }
1226 
1227  // Amending HTTP header
1228  string header_line;
1229  while (getline(is, header_line)) {
1231  if (header_line.empty())
1232  break;
1233 
1234  if (no_jquery)
1235  out << header_line << "\r\n";
1236  else if (NStr::StartsWith(header_line, "Content-Type", NStr::eNocase))
1237  out << "Content-Type: text/javascript\r\n";
1238  else if (!NStr::StartsWith(header_line, "Content-Length", NStr::eNocase))
1239  out << header_line << "\r\n";
1240  }
1241 
1242  if (m_AddJobIdToHeader) {
1243  out << HTTP_NCBI_JSID << ": " << ctx.GetJobKey() << "\r\n";
1244  }
1245 
1246  out << "\r\n";
1247 
1248  if (no_jquery) {
1249  NcbiStreamCopy(out, is);
1250  } else {
1251  out << ctx.GetJqueryCallback() << '(';
1252  NcbiStreamCopy(out, is);
1253  out << ')';
1254  }
1255  ctx.NeedRenderPage(false);
1256  } else {
1257  const char* str_page;
1258 
1259  switch (m_TargetEncodeMode) {
1261  str_page = "<html><head><title>Empty Result</title>"
1262  "</head><body>Empty Result</body></html>";
1263  break;
1265  str_page = "{}";
1266  break;
1267  default:
1268  str_page = "";
1269  }
1270 
1271  ctx.GetHTMLPage().SetTemplateString(str_page);
1272  }
1273 }
1274 
1275 void CCgi2RCgiApp::OnJobFailed(const string& msg,
1277 {
1279  // Render a error page
1280  ctx.SelectView("JOB_FAILED");
1281 
1282  string fall_back_url = m_FallBackUrl.empty() ?
1284  DefineRefreshTags(ctx, fall_back_url, m_FallBackDelay);
1285 
1286  ctx.GetHTMLPage().AddTagMap("MSG",
1288 }
1289 
1290 /////////////////////////////////////////////////////////////////////////////
1291 int main(int argc, const char* argv[])
1292 {
1294 
1296  grid::CVersionReporting<CCgi2RCgiApp> app;
1297  return app.AppMain(argc, argv);
1298 }
void GetRequestEntryValue(const string &entry_name, string &value) const
Definition: cgi2rcgi.cpp:207
bool Set(const string &section, const string &name, const string &value, TFlags flags=0, const string &comment=kEmptyStr)
Set the configuration parameter value.
Definition: ncbireg.cpp:826
Meaningful information encoded in the NetSchedule key.
int TFlags
Startup initialization.
Definition: ncbicgi.hpp:695
const string & GetProperty(ECgiProp prop) const
Get value of a "standard" property (return empty string if not defined)
Definition: ncbicgi.cpp:1422
#define NCBI_THROW_FMT(exception_class, err_code, message)
The same as NCBI_THROW but with message processed as output to ostream.
Definition: ncbiexpt.hpp:562
time_t GetTimeT(void) const
Get time in time_t format.
Definition: ncbitime.cpp:1399
virtual bool GetBool(const string &section, const string &name, bool default_value, TFlags flags=0, EErrAction err_action=eThrow) const
Get boolean value of specified parameter name.
Definition: ncbireg.cpp:391
static void handler(int)
static string TruncateSpaces(const string &str, ETrunc where=eTrunc_Both)
Truncate spaces in a string.
Definition: ncbistr.cpp:3081
static EJobStatus StringToStatus(const CTempString &status_str)
Parse status string into enumerator value.
static string NumericToString(TNumeric value, TNumToStringFlags flags=0, int base=10)
Convert numeric value to string.
Definition: ncbistr.hpp:664
auto_ptr< CHTMLPage > m_CustomHTTPHeader
Definition: cgi2rcgi.cpp:340
void PullUpPersistentEntry(const string &entry_name)
Save this entry as a cookie add it to serf url.
Definition: cgi2rcgi.cpp:220
static const unsigned char msg[]
Definition: ccm.c:378
static string UIntToString(unsigned int value, TNumToStringFlags flags=0, int base=10)
Convert UInt to string.
Definition: ncbistr.hpp:4833
virtual CCgiContext * CreateContextWithFlags(CNcbiArguments *args, CNcbiEnvironment *env, CNcbiIstream *inp, CNcbiOstream *out, int ifd, int ofd, int flags)
The same as CreateContext(), but allows for a custom set of flags to be specified in the CCgiRequest ...
Definition: cgi2rcgi.cpp:515
void Serialize(CNcbiOstream &os) const
Serialize/Deserialize a request to/from a stream.
Definition: ncbicgi.cpp:1556
unsigned NCBI_INT8_TYPE Uint8
Unsigned 8 byte sized integer.
Definition: ncbitype.h:146
CTempString implements a light-weight string on top of a storage buffer whose lifetime management is ...
Definition: tempstr.hpp:62
Retry context class.
const struct ncbi::grid::netcache::search::fields::KEY key
virtual int ProcessRequest(CCgiContext &ctx)
This is the method you should override.
Definition: cgi2rcgi.cpp:605
bool m_InterceptJQueryCallback
Definition: cgi2rcgi.cpp:336
Net Service exception.
void clear()
Definition: map.hpp:169
std::ofstream out("events_result.xml")
main entry point for tests
bool IsExpired(void) const
Check if the deadline is expired.
Definition: ncbitime.hpp:1819
void LoadQueryStringTags(CHTMLPlainText::EEncodeMode encode_mode)
Definition: cgi2rcgi.cpp:249
Case insensitive compare.
Definition: ncbistr.hpp:1192
virtual int GetInt(const string &section, const string &name, int default_value, TFlags flags=0, EErrAction err_action=eThrow) const
Get integer value of specified parameter name.
Definition: ncbireg.cpp:362
const TPersistentEntries & GetPersistentEntries() const
Definition: cgi2rcgi.cpp:108
Return default value.
Definition: ncbireg.hpp:205
void SubmitJob(CCgiRequest &request, CGridCgiContext &grid_ctx)
Definition: cgi2rcgi.cpp:870
container_type::const_iterator const_iterator
Definition: map.hpp:53
32-bit Cyclic Redundancy Check.
Definition: checksum.hpp:65
CNetScheduleAPIExt m_NetScheduleAPI
Definition: cgi2rcgi.cpp:313
CNcbiRegistry & GetRWConfig(void)
Get the application's cached configuration parameters, accessible to read-write for an application on...
Definition: ncbiapp.hpp:718
The HTML page.
void Clear()
Remove all persisted entries from cookie and self url.
Definition: cgi2rcgi.cpp:260
Running on a worker node.
void AddToClientNode(const string &data)
const string & GetRandomProperty(const string &key, bool http=true) const
Get value of a random client property; if "http" is TRUE then add prefix "HTTP_" to the property name...
Definition: ncbicgi.cpp:1428
CDiagContext & GetDiagContext(void)
Get diag context instance.
Definition: logging.cpp:818
CNcbiEnvironment –.
Definition: ncbienv.hpp:103
Diagnostic handler for embedding diagnostics in comments.
virtual bool TestAttribute(const string &attr_name, const string &test_pattern)
Definition: cgi2rcgi.cpp:567
void Set(const string &name, const string &value)
Set an environment variable by name.
Definition: ncbienv.cpp:146
CCgiRequest::
Definition: ncbicgi.hpp:676
void GetQueryStringEntryValue(const string &entry_name, string &value) const
Definition: cgi2rcgi.cpp:195
string m_Title
Definition: cgi2rcgi.cpp:330
virtual void Init(void)
This method is called on the CGI application initialization – before starting to process a HTTP requ...
Grid CGI Context Context in which a request is processed.
Definition: grid_cgiapp.hpp:67
virtual CNcbiOstream & Print(CNcbiOstream &out, TMode mode=eHTML)
Definition: node.cpp:296
bool m_PortAdded
Definition: cgi2rcgi.cpp:353
virtual string GetString(const string &section, const string &name, const string &default_value, TFlags flags=0) const
Get the parameter string value.
Definition: ncbireg.cpp:321
Job description.
CHTMLPage –.
Definition: page.hpp:160
const string & GetMessage() const
void DefinePersistentEntry(const string &entry_name, const string &value)
Definition: cgi2rcgi.cpp:236
bool WaitForNotification(const CDeadline &deadline, string *server_host=NULL)
CNcbiOstream & WriteHeader(void) const
Write HTTP response header to the output stream.
Definition: ncbicgir.hpp:396
void SetHeaderValue(const string &name, const string &value)
Definition: ncbicgir.cpp:151
use case insensitive CGI arguments
Definition: ncbicgi.hpp:706
const_iterator end() const
Definition: map.hpp:292
#define NULL
Definition: ncbistd.hpp:225
void PopulatePage(CGridCgiContext &grid_ctx)
Definition: cgi2rcgi.cpp:949
virtual const char * what(void) const
Standard report (includes full backlog).
Definition: ncbiexpt.cpp:340
TPersistentEntries m_PersistentEntries
Definition: cgi2rcgi.cpp:136
CNetService GetService()
#define kEmptyStr
Definition: ncbistr.hpp:121
Merge adjacent delimiters.
Definition: ncbistr.hpp:2434
CGridCgiContext(CHTMLPage &page, CCgiContext &ctx)
Definition: grid_cgiapp.cpp:46
int m_RefreshDelay
Definition: cgi2rcgi.cpp:309
static void s_RemoveCallbackParameter(string *query_string)
Definition: cgi2rcgi.cpp:586
CHTMLPage & GetHTMLPage()
Definition: cgi2rcgi.cpp:86
void AddChars(const char *str, size_t length)
Definition: checksum.hpp:285
bool m_NeedMetaRefresh
Definition: cgi2rcgi.cpp:141
CNetScheduleAPI::EJobStatus WaitForJobEvent(const string &job_key, CDeadline &deadline, CNetScheduleAPI ns_api, TJobStatusMask status_mask, int last_event_index=kMax_Int, int *new_event_index=NULL)
#define ITERATE(Type, Var, Cont)
ITERATE macro to sequence through container elements.
Definition: ncbimisc.hpp:795
#define NPOS
Definition: ncbistr.hpp:131
bool s_IsPendingOrRunning(CNetScheduleAPI::EJobStatus job_status)
Definition: cgi2rcgi.cpp:698
string m_AffinityName
Definition: cgi2rcgi.cpp:345
static string IntToString(int value, TNumToStringFlags flags=0, int base=10)
Convert int to string.
Definition: ncbistr.hpp:4808
done
Definition: token1.c:1
Job is ready (computed successfully)
void SetRequestFlags(int flags)
Set cgi parsing flag.
Definition: cgiapp.hpp:126
CTime & SetTimeT(const time_t t)
Set time using time_t time value.
Definition: ncbitime.hpp:2263
#define HTTP_NCBI_JSID
Definition: cgi2rcgi.cpp:65
static unsigned int StringToUInt(const CTempString str, TStringToNumFlags flags=0, int base=10)
Convert string to unsigned int.
Definition: ncbistr.cpp:543
HTML classes.
void ListenJobs(CCgiContext &ctx, const string &job_ids_value, const string &timeout_value)
Definition: cgi2rcgi.cpp:718
const_iterator end() const
Definition: map.hpp:152
CNetScheduleAPI::EJobStatus status
Definition: cgi2rcgi.cpp:712
Encode for HTML output.
Definition: html.hpp:267
static void SetOldPostFormat(bool value)
Set old/new format flag.
Definition: ncbidiag.cpp:3232
int m_FirstDelay
Definition: cgi2rcgi.cpp:311
static SIZE_TYPE Find(const CTempString str, const CTempString pattern, ECase use_case=eCase, EDirection direction=eForwardSearch, SIZE_TYPE occurrence=0)
Find the pattern in the string.
Definition: ncbistr.cpp:2786
CTimeSpan.
Definition: ncbitime.hpp:1276
static const string kGridCgiForm
Definition: cgi2rcgi.cpp:548
string m_ContentType
Definition: cgi2rcgi.cpp:349
vector< string > m_HtmlIncs
Definition: cgi2rcgi.cpp:343
virtual CCgiContext * CreateContextWithFlags(CNcbiArguments *args, CNcbiEnvironment *env, CNcbiIstream *inp, CNcbiOstream *out, int ifd, int ofd, int flags)
The same as CreateContext(), but allows for a custom set of flags to be specified in the CCgiRequest ...
Definition: cgiapp.cpp:835
#define CALLBACK_PARAM
Definition: cgi2rcgi.cpp:584
const char * tag
bool m_AddJobIdToHeader
Definition: cgi2rcgi.cpp:337
void OnJobDone(CGridCgiContext &)
Definition: cgi2rcgi.cpp:1212
Smart pointer to the job submission part of the NetSchedule API.
Waiting for execution.
const_iterator find(const key_type &key) const
Definition: map.hpp:153
int m_AffinitySource
Definition: cgi2rcgi.cpp:346
CNcbiOstream & out(void) const
Get output stream. Throw exception if GetOutput() is NULL.
Definition: ncbicgir.cpp:257
static DLIST_TYPE *DLIST_NAME() first(DLIST_LIST_TYPE *list)
Definition: dlist.tmpl.h:46
CDiagContext_Extra Extra(void) const
Create a temporary CDiagContext_Extra object.
Definition: ncbidiag.hpp:2130
auto_ptr< CHTMLPage > m_Page
Definition: cgi2rcgi.cpp:339
#define ERR_POST(message)
Error posting with file, line number information but without error codes.
Definition: ncbidiag.hpp:185
Explicitly canceled.
static bool SplitInTwo(const CTempString str, const CTempString delim, string &str1, string &str2, TSplitFlags flags=0)
Split a string into two pieces using the specified delimiters.
Definition: ncbistr.cpp:3455
SJob(const string &id)
Definition: cgi2rcgi.cpp:715
CHTMLPlainText::EEncodeMode m_TargetEncodeMode
Definition: cgi2rcgi.cpp:351
int main(int argc, const char *argv[])
Definition: cgi2rcgi.cpp:1291
static const char delimiter[]
string & GetJqueryCallback()
Definition: cgi2rcgi.cpp:122
static double StringToDouble(const CTempStringEx str, TStringToNumFlags flags=0)
Convert string to double.
Definition: ncbistr.cpp:1288
string AsString(const CTimeFormat &fmt=kEmptyStr) const
Transform time span to string.
Definition: ncbitime.cpp:2664
const string & GetContent(void) const
Get request content.
Definition: ncbicgi.cpp:1406
const string & GetPersistentEntryValue(const string &entry_name) const
Definition: cgi2rcgi.cpp:186
CCgiResponse * m_Response
Definition: cgi2rcgi.cpp:316
virtual void AddTagMap(const string &name, BaseTagMapper *mapper)
Tag mappers.
Definition: page.cpp:289
string m_DateFormat
Definition: cgi2rcgi.cpp:334
CCompoundIDPool GetCompoundIDPool()
CArgException –.
Definition: ncbiargs.hpp:119
CRegexp –.
Definition: regexp.hpp:69
void OnJobFailed(const string &msg, CGridCgiContext &ctx)
Definition: cgi2rcgi.cpp:1275
static wxAcceleratorEntry entries[3]
bool NeedRenderPage() const
Definition: cgi2rcgi.cpp:117
static const char * kHeader_Url
Definition: retry_ctx.hpp:208
int m_AffinitySetLimit
Definition: cgi2rcgi.cpp:347
int RenderPage()
Definition: cgi2rcgi.cpp:1007
#define GRID_APP_CHECK_VERSION_ARGS()
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:5141
const_iterator find(const key_type &key) const
Definition: map.hpp:293
CRegexpTemplateFilter(CHTMLPage *page)
Definition: cgi2rcgi.cpp:558
CCgiContext & GetCGIContext()
Definition: cgi2rcgi.cpp:114
static HENV env
Definition: transaction2.c:38
IO_PREFIX::ostream CNcbiOstream
Portable alias for ostream.
Definition: ncbistre.hpp:144
string AsString(const CTimeFormat &format=kEmptyStr, TSeconds out_tz=eCurrentTimeZone) const
Transform time to string.
Definition: ncbitime.cpp:1515
USING_NCBI_SCOPE
Definition: cgi2rcgi.cpp:63
CHTMLPage * m_Page
Definition: cgi2rcgi.cpp:564
string job_id
Output job key.
const string & Get(const string &name, bool *found=NULL) const
Get environment value by name.
Definition: ncbienv.cpp:108
#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:198
static const string kSinceTime
Definition: cgi2rcgi.cpp:67
Encode for JSON output.
Definition: html.hpp:268
CNcbiEnvironment & SetEnvironment(void)
Get a non-const copy of the application's cached environment.
Definition: ncbiapp.hpp:702
NetSchedule Framework specs.
void GetQueueInfo(CNetServer server, const string &queue_name, TQueueInfo &queue_info)
void RequireWriteHeader(bool require)
Define if WriteHeader() must be called or can be skipped.
Definition: ncbicgir.hpp:401
bool CheckIfJobDone(CGridCgiContext &)
Definition: cgi2rcgi.cpp:1107
virtual void SetupArgDescriptions(CArgDescriptions *arg_desc)
Setup the command line argument descriptions.
Definition: cgiapp.cpp:754
CHTMLPage & m_Page
CTime –.
Definition: ncbitime.hpp:290
CArgDescriptions –.
Definition: ncbiargs.hpp:514
static string StatusToString(EJobStatus status)
Printable status type.
CCgiContext & m_CgiContext
CDiagContext_Extra & Print(const string &name, const string &value)
The method does not print the argument, but adds it to the string.
Definition: ncbidiag.cpp:2496
int m_RefreshWait
Definition: cgi2rcgi.cpp:310
const TCgiEntries & GetEntries(void) const
Get a set of entries(decoded) received from the client.
Definition: ncbicgi.hpp:1158
An arbitrary string.
Definition: ncbiargs.hpp:563
void Set(EType type)
Set special value.
Definition: ncbitime.cpp:3560
Miscellaneous common-use basic types and functionality.
void DefineRefreshTags(CGridCgiContext &grid_ctx, const string &url, int delay)
Definition: cgi2rcgi.cpp:1074
void erase(iterator pos)
Definition: map.hpp:307
bool IsMatch(CTempString str, TMatch flags=fMatch_default)
Check existence substring which match a specified pattern.
Definition: regexp.cpp:188
const CNcbiArguments & GetArguments(void) const
Get the application's cached unprocessed command-line arguments.
Definition: ncbiapp.hpp:692
CNetCacheAPI m_NetCacheAPI
Definition: cgi2rcgi.cpp:314
bool NeedMetaRefresh() const
Definition: cgi2rcgi.cpp:119
bool NcbiStreamCopy(CNcbiOstream &os, CNcbiIstream &is)
Copy entire contents of stream "is" into "os".
Definition: ncbistre.cpp:216
static const char * kHeader_Delay
Definition: retry_ctx.hpp:206
Save request content (available through GetContent())
Definition: ncbicgi.hpp:712
bool progress_msg_truncated
Definition: cgi2rcgi.cpp:713
void erase(iterator pos)
Definition: map.hpp:167
CCgiContext & GetCGIContext()
Get CGI Context.
Definition: grid_cgiapp.hpp:98
static Uint8 StringToUInt8(const CTempString str, TStringToNumFlags flags=0, int base=10)
Convert string to Uint8.
Definition: ncbistr.cpp:774
static uch flags
Client API for NCBI NetSchedule server.
void SetStatus(unsigned int code, const string &reason=kEmptyStr)
Definition: ncbicgir.cpp:197
bool m_HTMLPassThrough
Definition: cgi2rcgi.cpp:352
void SetJobProgressMessage(const string &msg)
CHTMLPage & m_CustomHTTPHeader
Definition: cgi2rcgi.cpp:133
TErrCode GetErrCode(void) const
Get error code.
Definition: ncbiexpt.cpp:451
string m_JqueryCallback
Definition: cgi2rcgi.cpp:139
static void TruncateSpacesInPlace(string &str, ETrunc where=eTrunc_Both)
Truncate spaces in a string (in-place)
Definition: ncbistr.cpp:3096
Checksum (CRC32 or MD5) calculation class.
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1185
EJobStatus
Job status codes.
string GetSelfURL(void) const
Get Self URL.
Definition: cgi2rcgi.cpp:164
string m_ElapsedTimeFormat
Definition: cgi2rcgi.cpp:335
static string JsonEncode(const CTempString str)
Encode a string for JSON.
Definition: ncbistr.cpp:4494
string m_FallBackUrl
Definition: cgi2rcgi.cpp:331
void SetTemplateString(const char *template_string)
Definition: page.hpp:375
CNetScheduleAdmin GetAdmin()
Client API for NetCache server.
CNcbiRegistry –.
Definition: ncbireg.hpp:914
static SIZE_TYPE ParseEntries(const string &str, TCgiEntries &entries)
Decode the URL-encoded(FORM or ISINDEX) string "str" into a set of entries <"name", "value"> and add them to the "entries" set.
Definition: ncbicgi.cpp:1520
const string & GetJobKey(void) const
Get Current job key.
Definition: grid_cgiapp.cpp:99
NCBI_NS_STD::string::size_type SIZE_TYPE
Definition: ncbistr.hpp:130
Failed to run (execution timeout)
const string & GetJobProgressMessage() const
Definition: cgi2rcgi.cpp:92
IO_PREFIX::ostrstream CNcbiOstrstream
Portable alias for ostrstream.
Definition: ncbistre.hpp:157
static CS_CONTEXT * ctx
Definition: ct_dynamic.c:24
Uint4 GetChecksum(void) const
Return calculated checksum.
Definition: checksum.cpp:199
Do not encode prior to printing.
Definition: html.hpp:266
void CheckJob(CGridCgiContext &grid_ctx)
Definition: cgi2rcgi.cpp:835
do not automatically parse the request's content body (from "istr")
Definition: ncbicgi.hpp:704
virtual void Init()
This method is called on the CGI application initialization – before starting to process a HTTP requ...
Definition: cgi2rcgi.cpp:356
const string & GetSelfURL(ESelfUrlPort) const
Using HTTP environment variables, compose the CGI's own URL as: SCHEME://SERVER_NAME[:SERVER_PORT]/SC...
Definition: cgictx.hpp:217
TCgiEntries m_ParsedQueryString
CTimeout – Timeout interval.
Definition: ncbitime.hpp:1656
int isspace(Uchar c)
Definition: ncbictype.hpp:69
static list< string > & Split(const CTempString str, const CTempString delim, list< string > &arr, TSplitFlags flags=0, vector< SIZE_TYPE > *token_pos=NULL)
Split a string using specified delimiters.
Definition: ncbistr.cpp:3362
class CHTMLPage::CTemplateLibFilter TTemplateLibFilter
Interface for a filter, which must be passed to one the LoadTemplateLib methods to select relevant pa...
CHTMLPage & GetHTMLPage(void)
Get an HTML page.
Definition: grid_cgiapp.hpp:75
void RegisterDiagFactory(const string &key, CDiagFactory *fact)
Definition: cgiapp.cpp:1194
const CCgiResponse & GetResponse(void) const
Definition: cgictx.hpp:388
const_iterator begin() const
Definition: map.hpp:151
void SetContentType(const string &type)
Set content type (text/html by default if not provided)
Definition: ncbicgir.hpp:337
static const string kPlainTextView
Definition: cgi2rcgi.cpp:553
void SetJobProgressMessage(const string &msg)
Definition: cgi2rcgi.cpp:128
CNetScheduleSubmitter GetSubmitter()
Create an instance of CNetScheduleSubmitter.
bool NeedRenderPage() const
static string URLEncode(const CTempString str, EUrlEncode flag=eUrlEnc_SkipMarkChars)
URL-encode string.
Definition: ncbistr.cpp:5740
void SelectView(const string &view_name)
Definition: cgi2rcgi.cpp:265
Definition: dbpivot.c:60
NetSchedule internal exception.
CChecksum – Checksum calculator.
Definition: checksum.hpp:59
CTime GetFastLocalTime(void)
Quick and dirty getter of local time.
Definition: ncbitime.cpp:4138
map< string, string > TPersistentEntries
Definition: cgi2rcgi.cpp:103
int m_CancelGoBackDelay
Definition: cgi2rcgi.cpp:333
void SetRequestId(const string &rid, bool is_done)
Definition: cgiapp.cpp:1397
int m_FallBackDelay
Definition: cgi2rcgi.cpp:332
static int CompareNocase(const CTempString str, SIZE_TYPE pos, SIZE_TYPE n, const char *pattern)
Case-insensitive compare of a substring with a pattern.
Definition: ncbistr.cpp:170
virtual CNCBINode * MapTag(const string &name)
Resolve <> tag.
Definition: page.cpp:175
void NeedRenderPage(bool value)
Definition: cgi2rcgi.cpp:118
const string & GetMsg(void) const
Get message string.
Definition: ncbiexpt.cpp:459
CNcbiArguments –.
Definition: ncbienv.hpp:229
IO_PREFIX::istream CNcbiIstream
Portable alias for istream.
Definition: ncbistre.hpp:141
static Int32 incs[14]
Definition: blocksort.c:480
Truncate trailing spaces only.
Definition: ncbistr.hpp:2191
#define crc32
Definition: miniz.c:466
auto_ptr< CGridClient > m_GridClient
Definition: cgi2rcgi.cpp:315
string m_HtmlTemplate
Definition: cgi2rcgi.cpp:342
virtual const CArgs & GetArgs(void) const
Get parsed command line arguments extended with CGI parameters.
Definition: cgiapp.cpp:1039
Grid Client (the submitter).
TJobInfo RequestJobWatching(CNetScheduleAPI::TInstance ns_api, const string &job_id, const CDeadline &deadline)
EJobStatus GetJobDetails(CNetScheduleJob &job, time_t *job_exptime=NULL, ENetScheduleQueuePauseMode *pause_mode=NULL)
Get job details.
static const string GetPropertyName(ECgiProp prop)
Get name (not value!) of a "standard" property.
Definition: ncbicgi.cpp:926
CDeadline.
Definition: ncbitime.hpp:1793
string & GetJobKey()
Definition: cgi2rcgi.cpp:121
static int StringToInt(const CTempString str, TStringToNumFlags flags=0, int base=10)
Convert string to int.
Definition: ncbistr.cpp:531
const CCgiRequest & GetRequest(void) const
Definition: cgictx.hpp:374
Modified on Sun May 27 14:39:42 2018 by modify_doxy.py rev. 546573