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

Go to the SVN repository for this file.

1 /* $Id: ns_command_arguments.cpp 89004 2020-02-11 19:47:28Z satskyse $
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: Anatoliy Kuznetsov, Victor Joukov
27  *
28  * File Description: job request parameters
29  *
30  */
31 
32 #include <ncbi_pch.hpp>
34 #include <corelib/request_ctx.hpp>
35 
36 
37 #include "ns_command_arguments.hpp"
38 
39 
41 
43  { "id", eId },
44  { "key", eKey },
45  { "status", eStatus },
46  { "last_touch", eLastTouch },
47  { "erase_time", eEraseTime },
48  { "run_expiration", eRunExpiration },
49  { "read_expiration", eReadExpiration },
50  { "subm_notif_port", eSubmitNotifPort },
51  { "subm_notif_expiration", eSubmitNotifExpiration },
52  { "listener_notif", eListenerNotif },
53  { "listener_notif_expiration", eListenerNotifExpiration },
54  { "events", eEvents },
55  { "run_counter", eRunCounter },
56  { "read_counter", eReadCounter },
57  { "affinity", eAffinity },
58  { "group", eGroup },
59  { "mask", eMask },
60  { "input", eInput },
61  { "output", eOutput },
62  { "progress_msg", eProgressMsg },
63  { "remote_client_sid", eRemoteClientSID },
64  { "remote_client_ip", eRemoteClientIP },
65  { "ncbi_phid", eNcbiPHID },
66  { "need_subm_progress_msg_notif", eNeedSubmitProgressMsgNotif },
67  { "need_lsnr_progress_msg_notif", eNeedListenerProgressMsgNotif },
68  { "need_stolen_notif", eNeedStolenNotif },
69  { "gc_erase_time", eGCEraseTime },
70  { "scope", eScope }
71 };
72 
73 
74 
76 {
77  job_id = 0;
78  job_return_code = 0;
79  port = 0;
80  timeout = 0;
81  job_mask = 0;
83  count = 0;
85 
86  cmd.erase();
87  auth_token.erase();
88  input.erase();
89  output.erase();
90  affinity_token.erase();
91  job_key.erase();
92  queue_from_job_key.erase();
93  err_msg.erase();
94  comment.erase();
95  description.erase();
96  ip.erase();
97  option.erase();
98  progress_msg.erase();
99  qname.erase();
100  qclass.erase();
101  sid.erase();
102  job_statuses_string.erase();
103  aff_to_add.erase();
104  aff_to_del.erase();
105  start_after.erase();
106  group.erase();
107  alert.erase();
108  service.erase();
109  user.erase();
110  client_data.erase();
111  ncbi_phid.erase();
112  scope.erase();
113 
114  any_affinity = false;
115  wnode_affinity = false;
116  reader_affinity = false;
117  exclusive_new_aff = false;
118  mode = false;
119  drain = false;
120  effective = false;
121  pullback = false;
122  blacklist = true;
123  no_retries = false;
124  prioritized_aff = false;
125 
126  affinity_may_change = false;
127  group_may_change = false;
128 
129  need_progress_msg = false;
130  need_stolen = false;
131 
132  order_first = true;
133  dump_fields = eAll;
134 
135  job_statuses.clear();
136 }
137 
138 
139 static string s_AffOption = "aff";
140 static string s_AuthTokenOption = "auth_token";
141 static string s_AddOption = "add";
142 static string s_AnyAffOption = "any_aff";
143 static string s_AlertOption = "alert";
144 static string s_AffinityMayChangeOption = "affinity_may_change";
145 static string s_BlacklistOption = "blacklist";
146 static string s_CommentOption = "comment";
147 static string s_CountOption = "count";
148 static string s_DelOption = "del";
149 static string s_DrainOption = "drain";
150 static string s_DescriptionOption = "description";
151 static string s_DataOption = "data";
152 static string s_ExclusiveNewAffOption = "exclusive_new_aff";
153 static string s_ErrMsgOption = "err_msg";
154 static string s_EffectiveOption = "effective";
155 static string s_FieldsOption = "fields";
156 static string s_GroupOption = "group";
157 static string s_GroupMayChangeOption = "group_may_change";
158 static string s_InputOption = "input";
159 static string s_IpOption = "ip";
160 static string s_JobKeyOption = "job_key";
161 static string s_JobReturnCodeOption = "job_return_code";
162 static string s_MskOption = "msk";
163 static string s_ModeOption = "mode";
164 static string s_NcbiPhidOption = "ncbi_phid";
165 static string s_NoRetriesOption = "no_retries";
166 static string s_NeedStolenOption = "need_stolen";
167 static string s_NeedProgressMsgOption = "need_progress_msg";
168 static string s_OutputOption = "output";
169 static string s_OptionOption = "option";
170 static string s_OrderOption = "order";
171 static string s_PortOption = "port";
172 static string s_ProgressMsgOption = "progress_msg";
173 static string s_PullbackOption = "pullback";
174 static string s_PrioritizedAffOption = "prioritized_aff";
175 static string s_QNameOption = "qname";
176 static string s_QClassOption = "qclass";
177 static string s_ReaderAffOption = "reader_aff";
178 static string s_StatusOption = "status";
179 static string s_SidOption = "sid";
180 static string s_StartAfterOption = "start_after";
181 static string s_ServiceOption = "service";
182 static string s_ScopeOption = "scope";
183 static string s_TimeoutOption = "timeout";
184 static string s_UserOption = "user";
185 static string s_VersionOption = "version";
186 static string s_WnodeAffOption = "wnode_aff";
187 
188 
189 
191  const string & command,
192  bool need_to_generate,
193  CSocket & peer_socket,
195 {
196  x_Reset();
197  cmd = command;
198 
199  NON_CONST_ITERATE(TNSProtoParams, it, params) {
200  const CTempString & key = it->first;
201  const CTempString & val = it->second;
202  size_t size_to_check = 0;
203 
204 
205  if (key.empty())
206  continue;
207 
208  switch (key[0]) {
209  case 'a':
210  if (key == s_AffOption) {
213  }
214  else if (key == s_AuthTokenOption)
215  auth_token = val;
216  else if (key == s_AddOption) {
219  }
220  else if (key == s_AnyAffOption)
222  else if (key == s_AlertOption)
224  else if (key == s_AffinityMayChangeOption)
226  break;
227  case 'b':
228  if (key == s_BlacklistOption)
230  break;
231  case 'c':
232  if (key == s_CommentOption)
234  else if (key == s_CountOption)
236  break;
237  case 'd':
238  if (key == s_DelOption) {
241  }
242  else if (key == s_DrainOption)
244  else if (key == s_DescriptionOption) {
246  size_to_check = description.size();
247  }
248  else if (key == s_DataOption)
250  break;
251  case 'e':
254  else if (key == s_ErrMsgOption)
256  else if (key == s_EffectiveOption)
258  break;
259  case 'f':
260  if (key == s_FieldsOption) {
262  }
263  break;
264  case 'g':
265  if (key == s_GroupOption) {
268  }
269  else if (key == s_GroupMayChangeOption)
271  break;
272  case 'i':
273  if (key == s_InputOption) {
275  if (input.size() > kNetScheduleMaxOverflowSize)
276  NCBI_THROW(CNetScheduleException, eDataTooLong,
277  "input exceeds the max allowed length. "
278  "Received: " + to_string(input.size()) +
279  " Allowed: " +
280  to_string(kNetScheduleMaxOverflowSize));
281  }
282  else if (key == s_IpOption) {
284  if (ip.empty()) {
285  ip = peer_socket.GetPeerAddress(eSAF_IP);
286  it->second = ip;
287  }
288  }
289  break;
290  case 'j':
291  if (key == s_JobKeyOption) {
292  job_key = val;
293  if (!val.empty()) {
294  CNetScheduleKey parsed_key(val, id_pool);
295  job_id = parsed_key.id;
296  queue_from_job_key = parsed_key.queue;
297  }
298  if (job_id == 0)
300  eInvalidParameter, "Invalid job key");
301  }
302  else if (key == s_JobReturnCodeOption)
305  break;
306  case 'm':
307  if (key == s_MskOption)
309  else if (key == s_ModeOption)
311  break;
312  case 'n':
313  if (key == s_NcbiPhidOption) {
315  if (ncbi_phid.empty()) {
316  if (need_to_generate) {
318  // Dictionary is updated for the logging
319  it->second = ncbi_phid;
320  }
321  }
322  else
324  }
325  else if (key == s_NoRetriesOption)
327  else if (key == s_NeedStolenOption)
329  else if (key == s_NeedProgressMsgOption)
331  break;
332  case 'o':
333  if (key == s_OutputOption) {
335  if (output.size() > kNetScheduleMaxOverflowSize)
336  NCBI_THROW(CNetScheduleException, eDataTooLong,
337  "output exceeds the max allowed length. "
338  "Received: " + to_string(output.size()) +
339  " Allowed: " +
340  to_string(kNetScheduleMaxOverflowSize));
341  }
342  else if (key == s_OptionOption) {
344  } else if (key == s_OrderOption) {
346  }
347  break;
348  case 'p':
349  if (key == s_PortOption) {
351  if (port > 65535)
353  eInvalidParameter, "Invalid port number");
354  }
355  else if (key == s_ProgressMsgOption) {
357  size_to_check = progress_msg.size();
358  }
359  else if (key == s_PullbackOption)
361  else if (key == s_PrioritizedAffOption)
363  break;
364  case 'q':
365  if (key == s_QNameOption) {
368  }
369  else if (key == s_QClassOption) {
372  }
373  break;
374  case 'r':
375  if (key == s_ReaderAffOption)
377  break;
378  case 's':
379  if (key == s_StatusOption) {
381 
382  if (!job_statuses_string.empty()) {
383  list<string> statuses;
384  NStr::Split(job_statuses_string, ",", statuses);
385 
386  for (list<string>::const_iterator k = statuses.begin();
387  k != statuses.end(); ++k )
388  job_statuses.push_back(
390  }
391  }
392  else if (key == s_SidOption) {
394  if (sid.empty()) {
395  if (need_to_generate) {
397  it->second = sid;
398  }
399  }
400  else
402  }
403  else if (key == s_StartAfterOption) {
404  start_after = val;
405  if (!val.empty())
407  if (start_after_job_id == 0)
409  eInvalidParameter,
410  "Invalid job ID in 'start_after' option key");
411  }
412  else if (key == s_ServiceOption)
414  else if (key == s_ScopeOption)
416  break;
417  case 't':
418  if (key == s_TimeoutOption)
420  break;
421  case 'u':
422  if (key == s_UserOption)
424  break;
425  case 'v':
426  if (key == s_VersionOption)
428  break;
429  case 'w':
430  if (key == s_WnodeAffOption)
432  break;
433  default:
434  break;
435  }
436 
437 
438  if (size_to_check > kNetScheduleMaxDBDataSize - 1)
439  NCBI_THROW(CNetScheduleException, eDataTooLong,
440  "Argument '" + string(key) + "' size (" +
441  to_string(size_to_check) +
442  " bytes) exceeds the DB max limit ( " +
443  to_string(kNetScheduleMaxDBDataSize - 1) + " bytes)");
444  }
445 
446  return;
447 }
448 
449 
450 // A single affinity is a particular case of a list of affinities
451 // So it is harmless to use this function to check both:
452 // - commands which accept a single affinity
453 // - commands which accept a list of affinities
455 {
456  list<string> affs;
457  NStr::Split(val, "\t,", affs);
458  for (const auto & aff : affs)
459  if (aff.size() > kNetScheduleMaxDBDataSize - 1)
460  NCBI_THROW(
461  CNetScheduleException, eDataTooLong,
462  "Affinity token '" + aff + "' length (" +
463  to_string(aff.size()) + " bytes) exceeds the limit ( " +
464  to_string(kNetScheduleMaxDBDataSize - 1) + " bytes)");
465 }
466 
467 
468 // A single group is a particular case of a list of groups
469 // So it is harmless to use this function to check both:
470 // - commands which accept a single group
471 // - commands which accept a list of groups
473 {
474  list<string> groups;
475  NStr::Split(val, "\t,", groups);
476  for (const auto & group : groups)
477  if (group.size() > kNetScheduleMaxDBDataSize - 1)
478  NCBI_THROW(
479  CNetScheduleException, eDataTooLong,
480  "Group token '" + group + "' length (" +
481  to_string(group.size()) + " bytes) exceeds the limit ( " +
482  to_string(kNetScheduleMaxDBDataSize - 1) + " bytes)");
483 }
484 
485 
487  const string & key)
488 {
489  if (val.size() > kMaxQueueNameSize - 1) {
490  string q = "queue";
491  if (key == "qclass")
492  q += " class";
493  NCBI_THROW(CNetScheduleException, eDataTooLong,
494  "The '" + key + "' " + q + " name length (" +
495  to_string(val.size()) + " bytes) exceeds the limit ( " +
496  to_string(kMaxQueueNameSize - 1) + " bytes)");
497  }
498 }
499 
500 
502  const string & key)
503 {
504  static string zero = "0";
505  static string one = "1";
506 
507  if (val == zero)
508  return false;
509  if (val == one)
510  return true;
511 
512  NCBI_THROW(CNetScheduleException, eInvalidParameter,
513  key + " parameter accepted values are 0 and 1");
514 }
515 
516 
518 {
519  if (val.size() > kNetScheduleMaxDBErrSize - 1) {
520  // Truncate the message, see CXX-2617
521  ERR_POST(Warning << "The err_msg parameter length ("
522  << val.size() << "bytes) exceeds the limit "
523  << kNetScheduleMaxDBErrSize - 1 << " bytes) and is "
524  "truncated");
525  const string suffix = " TRUNCATED";
526  return val.substr(0, kNetScheduleMaxDBErrSize - suffix.size() - 2) +
527  suffix;
528  }
529  return val;
530 }
531 
532 
533 bool SNSCommandArguments::x_GetOrderFirst(const string & val)
534 {
535  static string first = "first";
536  static string last = "last";
537 
538  if (val == first)
539  return true;
540  if (val == last)
541  return false;
542 
543  NCBI_THROW(CNetScheduleException, eInvalidParameter,
544  "The order parameter valid values are 'first' and 'last'");
545 }
546 
547 
549 {
550  TDumpFields fields = 0;
551 
552  if (val.empty())
553  return eAll;
554 
555  list<string> field_names;
556  NStr::Split(val, ",", field_names);
557  for (const auto & field_name : field_names) {
558  auto it = ks_DumpFields.find(field_name);
559 
560  if (it == ks_DumpFields.end()) {
561  ERR_POST(Warning << "Dump field name " << field_name
562  << " is not supported. Ignore and continue.");
563  } else {
564  fields |= it->second;
565  }
566  }
567  return fields;
568 }
569 
NetSchedule internal exception.
CSocket::
CTempString implements a light-weight string on top of a storage buffer whose lifetime management is ...
Definition: tempstr.hpp:65
Definition: map.hpp:338
static DLIST_TYPE *DLIST_NAME() first(DLIST_LIST_TYPE *list)
Definition: dlist.tmpl.h:46
static DLIST_TYPE *DLIST_NAME() last(DLIST_LIST_TYPE *list)
Definition: dlist.tmpl.h:51
@ eAffinity
Definition: grid_cli.hpp:194
@ eInput
Definition: grid_cli.hpp:163
#define NON_CONST_ITERATE(Type, Var, Cont)
Non constant version of ITERATE macro.
Definition: ncbimisc.hpp:822
void SetSessionID(const string &session)
static CRequestContext & GetRequestContext(void)
Shortcut to CDiagContextThreadData::GetThreadData().GetRequestContext()
Definition: ncbidiag.cpp:1901
void SetHitID(const string &hit)
Set explicit hit id. The id is reset on request end.
#define ERR_POST(message)
Error posting with file, line number information but without error codes.
Definition: ncbidiag.hpp:186
#define NCBI_THROW(exception_class, err_code, message)
Generic macro to throw an exception, given the exception class, error code and message string.
Definition: ncbiexpt.hpp:704
void Warning(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1191
unsigned id
Job id.
string queue
Queue name, optional.
static EJobStatus StringToStatus(const CTempString &status_str)
Parse status string into enumerator value.
void GetPeerAddress(unsigned int *host, unsigned short *port, ENH_ByteOrder byte_order) const
Get peer address.
@ eSAF_IP
only numeric IP if INET socket, empty otherwise
Definition: ncbi_socket.h:1392
static int StringToInt(const CTempString str, TStringToNumFlags flags=0, int base=10)
Convert string to int.
Definition: ncbistr.cpp:630
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:3452
static string ParseEscapes(const CTempString str, EEscSeqRange mode=eEscSeqRange_Standard, char user_char='?')
Parse C-style escape sequences in the specified string.
Definition: ncbistr.cpp:4784
static unsigned int StringToUInt(const CTempString str, TStringToNumFlags flags=0, int base=10)
Convert string to unsigned int.
Definition: ncbistr.cpp:642
@ fConvErr_NoThrow
Do not throw an exception on error.
Definition: ncbistr.hpp:285
const struct ncbi::grid::netcache::search::fields::KEY key
NetSchedule client specs.
const unsigned int kNetScheduleMaxDBDataSize
const unsigned int kNetScheduleMaxDBErrSize
const char * command
static string s_MskOption
static string s_ProgressMsgOption
static string s_AlertOption
static string s_NeedStolenOption
static string s_PortOption
static string s_QClassOption
static string s_DrainOption
static string s_StartAfterOption
static string s_SidOption
static string s_AuthTokenOption
static string s_AffinityMayChangeOption
static string s_UserOption
static string s_EffectiveOption
static string s_JobReturnCodeOption
static string s_NcbiPhidOption
static string s_CountOption
static string s_IpOption
static string s_VersionOption
static string s_FieldsOption
static string s_GroupOption
static string s_CommentOption
static string s_JobKeyOption
static string s_ErrMsgOption
static string s_GroupMayChangeOption
static string s_ModeOption
static string s_AnyAffOption
static string s_AddOption
static string s_PullbackOption
static string s_WnodeAffOption
static string s_DescriptionOption
static string s_OrderOption
static string s_DelOption
static string s_ReaderAffOption
static string s_NoRetriesOption
static string s_OutputOption
static string s_OptionOption
static string s_InputOption
static string s_ScopeOption
static string s_AffOption
static string s_StatusOption
static string s_QNameOption
static string s_BlacklistOption
static string s_ExclusiveNewAffOption
static string s_ServiceOption
static map< string, EDumpFields > ks_DumpFields
static string s_DataOption
static string s_TimeoutOption
static string s_PrioritizedAffOption
static string s_NeedProgressMsgOption
long TDumpFields
@ eSubmitNotifPort
@ eSubmitNotifExpiration
@ eListenerNotifExpiration
@ eRunExpiration
@ eProgressMsg
@ eRemoteClientIP
@ eNeedSubmitProgressMsgNotif
@ eRemoteClientSID
@ eNeedListenerProgressMsgNotif
@ eGCEraseTime
@ eNeedStolenNotif
@ eListenerNotif
@ eReadCounter
@ eReadExpiration
const unsigned kNetScheduleMaxOverflowSize
Definition: ns_types.hpp:118
const unsigned kMaxQueueNameSize
Definition: ns_types.hpp:108
Defines CRequestContext class for NCBI C++ diagnostic API.
Meaningful information encoded in the NetSchedule key.
bool x_GetOrderFirst(const string &val)
vector< TJobStatus > job_statuses
void AssignValues(TNSProtoParams &params, const string &command, bool need_to_generate, CSocket &peer_socket, CCompoundIDPool::TInstance id_pool)
string x_NormalizeErrorMessage(const string &val)
TDumpFields x_GetDumpFields(const string &val)
void x_CheckGroupList(const string &val)
bool x_GetBooleanValue(const string &val, const string &key)
void x_CheckQueueName(const string &val, const string &key)
void x_CheckAffinityList(const string &val)
Modified on Fri Sep 20 14:58:02 2024 by modify_doxy.py rev. 669887