irods  4.2.8
About: iRODS (the integrated Rule Oriented Data System) is a distributed data-management system for creating data grids, digital libraries, persistent archives, and real-time data systems.
  Fossies Dox: irods-4.2.8.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

rodsLog.cpp
Go to the documentation of this file.
1 
4 //Creates irods_error_map
5 #define MAKE_IRODS_ERROR_MAP
6 #include "rodsErrorTable.h"
7 const static std::map<const int, const std::string> irods_error_map = irods_error_map_construction::irods_error_map;
8 
9 #include "rods.h"
11 
12 #ifdef SYSLOG
13 #ifndef windows_platform
14 #include <syslog.h>
15 #endif
16 #endif
17 
18 #include "rodsLog.h"
19 #include "rcGlobalExtern.h"
20 #include "rcMisc.h"
21 #include <time.h>
22 #include <map>
23 #include <string>
24 #include <sys/time.h>
25 #include "irods_exception.hpp"
26 
27 #ifndef windows_platform
28 #include <unistd.h>
29 #endif
30 
31 #ifdef windows_platform
32 #include "irodsntutil.hpp"
33 #endif
34 
35 #define BIG_STRING_LEN MAX_NAME_LEN+300
36 #include <stdarg.h>
37 
38 
39 
41 static int sqlVerbosityLevel = 0;
42 pid_t myPid = 0;
43 
44 #ifdef windows_platform
45 static void rodsNtElog( char *msg );
46 #endif
47 
48 std::string create_log_error_prefix() {
49  std::string ret("remote addresses: ");
50  try {
51  std::vector<int> fds = get_open_socket_file_descriptors();
52  std::vector<std::string> remote_addresses;
53  remote_addresses.reserve(fds.size());
54  for (const auto fd : fds) {
55  std::string remote_address = socket_fd_to_remote_address(fd);
56  if (remote_address != "") {
57  remote_addresses.push_back(std::move(remote_address));
58  }
59  }
60  if (remote_addresses.size() == 0) {
61  ret = "";
62  return ret;
63  }
64  std::sort(remote_addresses.begin(), remote_addresses.end());
65  auto new_end = std::unique(remote_addresses.begin(), remote_addresses.end());
66  remote_addresses.erase(new_end, remote_addresses.end());
67  for (size_t i=0; i<remote_addresses.size()-1; ++i) {
68  ret += remote_addresses[i];
69  ret += ", ";
70  }
71  ret += remote_addresses.back();
72  } catch (const irods::exception& e) {
73  ret = "";
74  return ret;
75  }
76 
77  return ret;
78 }
79 
80 /*
81  Log or display a message. The level argument indicates how severe
82  the message is, and depending on the verbosityLevel may or may not be
83  recorded. This is used by both client and server code.
84  */
85 void
86 rodsLog( int level, const char *formatStr, ... ) {
87  time_t timeValue;
88  FILE *errOrOut;
89  va_list ap;
90 
91 #ifdef SYSLOG
92  char *myZone = getenv( "spProxyRodsZone" );
93 #endif
94  int okToLog = 0;
95 
96  char extraInfo[100];
97 #ifdef windows_platform
98  char nt_log_msg[2048];
99 #endif
100 
101  if ( level <= verbosityLevel ) {
102  okToLog = 1;
103  }
104 
105  if ( level == LOG_SQL ) {
106  okToLog = 1;
107  }
108 
109  if ( !okToLog ) {
110  return;
111  }
112 
113  va_start( ap, formatStr );
114  char * message = ( char * )malloc( sizeof( char ) * BIG_STRING_LEN );
115  int len = vsnprintf( message, BIG_STRING_LEN, formatStr, ap );
116  if ( len + 1 > BIG_STRING_LEN ) {
117  va_end( ap );
118  va_start( ap, formatStr );
119  free( message );
120  message = ( char * )malloc( sizeof( char ) * ( len + 1 ) );
121  vsnprintf( message, len + 1, formatStr, ap );
122  }
123  va_end( ap );
124 
125  extraInfo[0] = '\0';
126 #ifndef windows_platform
127  errOrOut = stdout;
128 #endif
129  if ( ProcessType == SERVER_PT || ProcessType == AGENT_PT ||
131  char timeBuf[100];
132  time( &timeValue );
133  rstrcpy( timeBuf, ctime( &timeValue ), 90 );
134  timeBuf[19] = '\0';
135  myPid = getpid();
136  snprintf( extraInfo, 100 - 1, "%s pid:%d ", timeBuf + 4, myPid );
137  }
138  else {
139 #ifndef windows_platform
140  if ( level <= LOG_ERROR || level == LOG_SQL ) {
141  errOrOut = stderr;
142  }
143 #endif
144  }
145 
146  std::string prefix = "";
147  if ( level == LOG_SQL ) {
148  prefix = "LOG_SQL";
149  }
150  if ( level == LOG_SYS_FATAL ) {
151  prefix = "SYSTEM FATAL";
152  }
153  if ( level == LOG_SYS_WARNING ) {
154  prefix = "SYSTEM WARNING";
155  }
156  if ( level == LOG_ERROR ) {
157  prefix = create_log_error_prefix();
158  prefix += " ERROR";
159  }
160  if ( level == LOG_NOTICE ) {
161  prefix = "NOTICE";
162  }
163  if ( level == LOG_WARNING ) {
164  prefix = "WARNING";
165  }
166 #ifdef SYSLOG
167  if ( level == LOG_DEBUG ) {
168  prefix = "DEBUG";
169  }
170  if ( level == LOG_DEBUG10 ) {
171  prefix = "DEBUG1";
172  }
173  if ( level == LOG_DEBUG9 ) {
174  prefix = "DEBUG2";
175  }
176  if ( level == LOG_DEBUG8 ) {
177  prefix = "DEBUG3";
178  }
179  if ( ProcessType == SERVER_PT || ProcessType == AGENT_PT ||
181 #else
182  if ( level == LOG_DEBUG ) {
183  prefix = "DEBUG";
184  }
185  if ( level == LOG_DEBUG10 ) {
186  prefix = "DEBUG1";
187  }
188  if ( level == LOG_DEBUG9 ) {
189  prefix = "DEBUG2";
190  }
191  if ( level == LOG_DEBUG8 ) {
192  prefix = "DEBUG3";
193  }
194  if ( message[strlen( message ) - 1] == '\n' )
195 #endif
196  {
197 #ifdef SYSLOG
198 #ifdef SYSLOG_FACILITY_CODE
199  syslog( SYSLOG_FACILITY_CODE | LOG_NOTICE, "%s - %s: %s", myZone, prefix.c_str(), message );
200 #else
201  syslog( LOG_DAEMON | LOG_NOTICE, "%s - %s: %s", myZone, prefix.c_str(), message );
202 #endif
203 #else
204 #ifndef windows_platform
205  fprintf( errOrOut, "%s%s: %s", extraInfo, prefix.c_str(), message );
206 #else
207  sprintf( nt_log_msg, "%s%s: %s", extraInfo, prefix.c_str(), message );
208  rodsNtElog( nt_log_msg );
209 #endif
210 #endif
211  }
212  else {
213 #ifndef windows_platform
214  fprintf( errOrOut, "%s%s: %s\n", extraInfo, prefix.c_str(), message );
215 #else
216  sprintf( nt_log_msg, "%s%s: %s\n", extraInfo, prefix.c_str(), message );
217  rodsNtElog( nt_log_msg );
218 #endif
219  }
220 #ifndef windows_platform
221  fflush( errOrOut );
222 #endif
223  free( message );
224 }
225 
226 /* same as rodsLog plus putting the msg in myError too. Need to merge with
227  * rodsLog
228  */
229 
230 void
231 rodsLogAndErrorMsg( int level, rError_t *myError, int status,
232  const char *formatStr, ... ) {
233  char *prefix;
234  time_t timeValue;
235  FILE *errOrOut;
236  va_list ap;
237  char errMsg[ERR_MSG_LEN];
238 
239  char extraInfo[100];
240 #ifdef windows_platform
241  char nt_log_msg[2048];
242 #endif
243 
244  if ( level > verbosityLevel ) {
245  return;
246  }
247 
248 
249  va_start( ap, formatStr );
250  char * message = ( char * )malloc( sizeof( char ) * BIG_STRING_LEN );
251  int len = vsnprintf( message, BIG_STRING_LEN, formatStr, ap );
252  if ( len + 1 > BIG_STRING_LEN ) {
253  va_end( ap );
254  va_start( ap, formatStr );
255  free( message );
256  message = ( char * )malloc( sizeof( char ) * ( len + 1 ) );
257  vsnprintf( message, len + 1, formatStr, ap );
258  }
259  va_end( ap );
260 
261  extraInfo[0] = '\0';
262  errOrOut = stdout;
263  if ( ProcessType == SERVER_PT || ProcessType == AGENT_PT ||
265  char timeBuf[100];
266  time( &timeValue );
267  rstrcpy( timeBuf, ctime( &timeValue ), 90 );
268  timeBuf[19] = '\0';
269  myPid = getpid();
270  snprintf( extraInfo, 100 - 1, "%s pid:%d ", timeBuf + 4, myPid );
271  }
272  else {
273  if ( level <= LOG_ERROR || level == LOG_SQL ) {
274  errOrOut = stderr;
275  }
276  }
277 
278  prefix = "";
279  if ( level == LOG_SQL ) {
280  prefix = "LOG_SQL";
281  }
282  if ( level == LOG_SYS_FATAL ) {
283  prefix = "SYSTEM FATAL";
284  }
285  if ( level == LOG_SYS_WARNING ) {
286  prefix = "SYSTEM WARNING";
287  }
288  if ( level == LOG_ERROR ) {
289  prefix = "ERROR";
290  }
291  if ( level == LOG_NOTICE ) {
292  prefix = "NOTICE";
293  }
294  if ( level == LOG_WARNING ) {
295  prefix = "WARNING";
296  }
297  if ( level <= LOG_DEBUG ) {
298  prefix = "DEBUG";
299  }
300  const size_t message_len = strlen( message );
301  if ( message_len > 0 && message[message_len - 1] == '\n' ) {
302 #ifndef windows_platform
303  fprintf( errOrOut, "%s%s: %s", extraInfo, prefix, message );
304  if ( myError != NULL ) {
305  snprintf( errMsg, ERR_MSG_LEN,
306  "%s: %s", prefix, message );
307  addRErrorMsg( myError, status, errMsg );
308  }
309 #else
310  sprintf( nt_log_msg, "%s%s: %s", extraInfo, prefix, message );
311  rodsNtElog( nt_log_msg );
312 #endif
313  }
314  else {
315 #ifndef windows_platform
316  fprintf( errOrOut, "%s%s: %s\n", extraInfo, prefix, message );
317  if ( myError != NULL ) {
318  snprintf( errMsg, ERR_MSG_LEN,
319  "%s: %s\n", prefix, message );
320  addRErrorMsg( myError, status, errMsg );
321  }
322 #else
323  sprintf( nt_log_msg, "%s%s: %s\n", extraInfo, prefix, message );
324  rodsNtElog( nt_log_msg );
325 #endif
326  }
327 
328 #ifndef windows_platform
329  fflush( errOrOut );
330 #endif
331  free( message );
332 }
333 
334 /*
335  Change the verbosityLevel of reporting.
336  The input value is the new minimum level of message to report.
337  */
338 void
339 rodsLogLevel( int level ) {
340  verbosityLevel = level;
341 }
342 
343 int
345  return ( verbosityLevel );
346 }
347 
348 /*
349  Request sql logging.
350  */
351 void
352 rodsLogSqlReq( int onOrOff ) {
353  sqlVerbosityLevel = onOrOff;
354 }
355 
356 void
357 rodsLogSql( const char *sql ) {
358  myPid = getpid();
359  if ( sqlVerbosityLevel ) rodsLog( LOG_SQL, "pid: %d sql: %s",
360  myPid, sql );
361 }
362 void
363 rodsLogSqlResult( char *stat ) {
364  myPid = getpid();
365  if ( sqlVerbosityLevel ) rodsLog( LOG_SQL, "pid: %d result: %s",
366  myPid, stat );
367 }
368 
369 /*
370 Convert an iRODS error code to the corresponding name.
371  */
372 const char *
373 rodsErrorName( int errorValue, char **subName ) {
374  int testVal = errorValue / 1000;
375 
376  if ( subName ) {
377  int subCode = errorValue - ( testVal * 1000 );
378  *subName = subCode && errorValue < 0 ?
379  strdup( strerror( -subCode ) ) :
380  strdup( "" );
381  }
382 
383  const std::map<const int, const std::string>::const_iterator search = irods_error_map.find( testVal * 1000 );
384  if ( search == irods_error_map.end() ) {
385  return ( "Unknown iRODS error" );
386  }
387  return search->second.c_str();
388 }
389 
390 /*
391  Convert an error code to a string and log it.
392  This was originally called rodsLogError, but was renamed when we
393  created the new rodsLogError below. This is no longer used (
394  rodsLogError can be called with the same arguments).
395  */
396 void
397 rodsLogErrorOld( int level, int rodsErrorCode, char *textStr ) {
398  char *errSubName = NULL;
399 
400  if ( level < verbosityLevel ) {
401  return;
402  }
403 
404  const char * errName = rodsErrorName( rodsErrorCode, &errSubName );
405  if ( textStr && strlen( textStr ) > 0 ) {
406  rodsLog( level, "%s Error: %d: %s, %s", textStr, rodsErrorCode,
407  errName, errSubName );
408  }
409  else {
410  rodsLog( level, "Error: %d: %s, %s", rodsErrorCode,
411  errName, errSubName );
412  }
413  free( errSubName );
414 }
415 
416 /* Like rodsLogError but with full rodsLog functionality too.
417  Converts the errorcode to a string, and possibly a subcode string,
418  and includes that at the end of a regular log message (with
419  variable arguments).
420  */
421 void
422 rodsLogError( int level, int rodsErrorCode, char *formatStr, ... ) {
423  char *errSubName = NULL;
424  va_list ap;
425 
426  if ( level > verbosityLevel ) {
427  return;
428  }
429 
430 
431  va_start( ap, formatStr );
432  char * message = ( char * )malloc( sizeof( char ) * BIG_STRING_LEN );
433  int len = vsnprintf( message, BIG_STRING_LEN, formatStr, ap );
434  if ( len + 1 > BIG_STRING_LEN ) {
435  va_end( ap );
436  va_start( ap, formatStr );
437  free( message );
438  message = ( char * )malloc( sizeof( char ) * ( len + 1 ) );
439  vsnprintf( message, len + 1, formatStr, ap );
440  }
441  va_end( ap );
442 
443  const char * errName = rodsErrorName( rodsErrorCode, &errSubName );
444  if ( strlen( errSubName ) > 0 ) {
445  rodsLog( level, "%s status = %d %s, %s", message, rodsErrorCode,
446  errName, errSubName );
447  }
448  else {
449  rodsLog( level, "%s status = %d %s", message, rodsErrorCode,
450  errName );
451  }
452  free( message );
453  free( errSubName );
454 }
455 
456 #ifdef windows_platform
457 static void rodsNtElog( char *msg ) {
458  char log_fname[1024];
459  int fd;
460  int t;
461 
462  if ( ProcessType == CLIENT_PT ) {
463  fprintf( stderr, "%s", msg );
464  return;
465  }
466 
467  t = strlen( msg );
468  if ( msg[t - 1] == '\n' ) {
469  msg[t - 1] = '\0';
470  t = t - 1;
471  }
472 
473  if ( iRODSNtServerRunningConsoleMode() ) {
474  t = strlen( msg );
475  if ( msg[t - 1] == '\n' ) {
476  fprintf( stderr, "%s", msg );
477  }
478  else {
479  fprintf( stderr, "%s\n", msg );
480  }
481  return;
482  }
483 
484  t = strlen( msg );
485  if ( msg[t - 1] != '\n' ) {
486  msg[t] = '\n';
487  msg[t + 1] = '\0';
488  t = t + 1;
489  }
490 
491  iRODSNtGetLogFilenameWithPath( log_fname );
492  fd = iRODSNt_open( log_fname, O_APPEND | O_WRONLY, 1 );
493  _write( fd, msg, t );
494  _close( fd );
495 }
496 #endif
497 
498 /*
499  * This function will generate an ISO 8601 formatted
500  * date/time stamp for use in log messages. The format
501  * will be 'YYYYMMDDThhmmss.uuuuuuZ' where:
502  *
503  * YYYY - is the year
504  * MM - is the month (01-12)
505  * DD - is the day (01-31)
506  * hh - is the hour (00-24)
507  * mm - is the minute (00-59)
508  * ss - is the second (00-59)
509  * u+ - are the number of microseconds.
510  *
511  * The date/time stamp is in UTC time.
512  */
513 void
514 generateLogTimestamp( char *ts, int tsLen ) {
515  struct timeval tv;
516  struct tm utc;
517  char timestamp[TIME_LEN];
518 
519  if ( ts == NULL ) {
520  return;
521  }
522 
523  gettimeofday( &tv, NULL );
524  gmtime_r( &tv.tv_sec, &utc );
525  strftime( timestamp, TIME_LEN, "%Y%m%dT%H%M%S", &utc );
526 
527  /* 8 characters of '.uuuuuuZ' + nul */
528  if ( tsLen < ( int )strlen( timestamp ) + 9 ) {
529  return;
530  }
531 
532  snprintf( ts, strlen( timestamp ) + 9, "%s.%06dZ", timestamp, ( int )tv.tv_usec );
533 }
NULL
#define NULL
Definition: rodsDef.h:70
rodsErrorName
const char * rodsErrorName(int errorValue, char **subName)
Definition: rodsLog.cpp:373
getRodsLogLevel
int getRodsLogLevel()
Definition: rodsLog.cpp:344
AGENT_PT
#define AGENT_PT
Definition: rodsDef.h:79
LOG_SYS_FATAL
#define LOG_SYS_FATAL
Definition: rodsLog.h:55
rodsLogSqlResult
void rodsLogSqlResult(char *stat)
Definition: rodsLog.cpp:363
rodsLogAndErrorMsg
void rodsLogAndErrorMsg(int level, rError_t *myError, int status, const char *formatStr,...)
Definition: rodsLog.cpp:231
LOG_WARNING
#define LOG_WARNING
Definition: rodsLog.h:38
irods_exception.hpp
irods_error_map
static const std::map< const int, const std::string > irods_error_map
Definition: rodsLog.cpp:7
rcMisc.h
ctime
long long ctime
Definition: filesystem.cpp:108
LOG_DEBUG8
#define LOG_DEBUG8
Definition: rodsLog.h:21
rcGlobalExtern.h
LOG_ERROR
#define LOG_ERROR
Definition: rodsLog.h:43
generateLogTimestamp
void generateLogTimestamp(char *ts, int tsLen)
Definition: rodsLog.cpp:514
socket_fd_to_remote_address
std::string socket_fd_to_remote_address(const int fd)
Definition: irods_socket_information.cpp:14
ProcessType
int ProcessType
Definition: rcGlobal.cpp:16
create_log_error_prefix
std::string create_log_error_prefix()
Definition: rodsLog.cpp:48
rodsLogSqlReq
void rodsLogSqlReq(int onOrOff)
Definition: rodsLog.cpp:352
rError_t
Definition: rodsError.h:24
get_open_socket_file_descriptors
std::vector< int > get_open_socket_file_descriptors(void)
Definition: irods_socket_information.cpp:37
LOG_DEBUG
#define LOG_DEBUG
Definition: rodsLog.h:23
sqlVerbosityLevel
static int sqlVerbosityLevel
Definition: rodsLog.cpp:41
TIME_LEN
#define TIME_LEN
Definition: rodsDef.h:54
BIG_STRING_LEN
#define BIG_STRING_LEN
Definition: rodsLog.cpp:35
terminate_irods_processes.e
e
Definition: terminate_irods_processes.py:19
rodsLogErrorOld
void rodsLogErrorOld(int level, int rodsErrorCode, char *textStr)
Definition: rodsLog.cpp:397
rodsLog
void rodsLog(int level, const char *formatStr,...)
Definition: rodsLog.cpp:86
rodsLogError
void rodsLogError(int level, int rodsErrorCode, char *formatStr,...)
Definition: rodsLog.cpp:422
addRErrorMsg
int addRErrorMsg(rError_t *myError, int status, const char *msg)
Definition: rcMisc.cpp:121
irods.pypyodbc.status
status
Definition: pypyodbc.py:467
CLIENT_PT
#define CLIENT_PT
Definition: rodsDef.h:77
irods::experimental::filesystem::client::move
auto move(rcComm_t &_comm, const path &_old_p, const path &_new_p) -> void
Definition: filesystem.cpp:881
rodsLog.h
LOG_NOTICE
#define LOG_NOTICE
Definition: rodsLog.h:33
LOG_DEBUG9
#define LOG_DEBUG9
Definition: rodsLog.h:20
verbosityLevel
static int verbosityLevel
Definition: rodsLog.cpp:40
RE_SERVER_PT
#define RE_SERVER_PT
Definition: rodsDef.h:80
SERVER_PT
#define SERVER_PT
Definition: rodsDef.h:78
irods::exception
Definition: irods_exception.hpp:15
LOG_SQL
#define LOG_SQL
Definition: rodsLog.h:9
irods_socket_information.hpp
LOG_DEBUG10
#define LOG_DEBUG10
Definition: rodsLog.h:19
rodsErrorTable.h
LOG_SYS_WARNING
#define LOG_SYS_WARNING
Definition: rodsLog.h:48
rstrcpy
char * rstrcpy(char *dest, const char *src, int maxLen)
Definition: stringOpr.cpp:51
rodsLogLevel
void rodsLogLevel(int level)
Definition: rodsLog.cpp:339
rods.h
myPid
pid_t myPid
Definition: rodsLog.cpp:42
ERR_MSG_LEN
#define ERR_MSG_LEN
Definition: rodsError.h:16
rodsLogSql
void rodsLogSql(const char *sql)
Definition: rodsLog.cpp:357