void log_init(int restart) { if (log_initialised) { if (!restart) return; if (strcmp(logfile_name, lp_log_file(module_id)) != 0) { if (logfile_fp) { fclose(logfile_fp); logfile_fp = NULL; } else closelog(); logfile_name = NULL; } else if (*logfile_name) return; /* unchanged, non-empty "log file" names */ else if (lp_syslog_facility(-1) != lp_syslog_facility(module_id)) closelog(); else return; /* unchanged syslog settings */ } else log_initialised = 1; /* This looks pointless, but it is needed in order for the * C library on some systems to fetch the timezone info * before the chroot. */ timestring(time(NULL)); /* Optionally use a log file instead of syslog. (Non-daemon * rsyncs will have already set logfile_name, as needed.) */ if (am_daemon && !logfile_name) logfile_name = lp_log_file(module_id); if (logfile_name && *logfile_name) logfile_open(); else syslog_init(); }
void logfile_reopen(void) { if (logfile_was_closed) { logfile_was_closed = 0; logfile_open(); } }
static void logfile_param_changed(cvar_t *self) { if (logfile_enable->integer) { logfile_close(); logfile_open(); } }
static void logfile_enable_changed(cvar_t *self) { logfile_close(); if (self->integer) { logfile_open(); } }
int server_init(server_t *server) { assert(server!= NULL); pthread_mutex_init(&server->send_pending_lock, NULL); pthread_cond_init(&server->send_pending_cond, NULL); UNUSED int r; get_instance_parent_full_path(server->root_dir, NAME_MAX); sprintf(server->storage.storage_dir, "%s/data/storage", server->root_dir); if ( mkdir_if_not_exist(server->storage.storage_dir) != 0 ){ error_log("mkdir %s failed.", server->storage.storage_dir); return -1; } char log_dir[NAME_MAX]; sprintf(log_dir, "%s/data/log", server->root_dir); if ( mkdir_if_not_exist(log_dir) != 0 ) { error_log("mkdir %s failed.", log_dir); return -1; } /*r = storage_init(&server->storage);*/ int i; for ( i = 0 ; i < VNODES ; i++ ){ vnode_t *vnode = vnode_new(server->storage.storage_dir, i); if ( vnode == NULL ){ error_log("vnode_init() failed. id:%d", i); return -1; } server->vnodes[i] = vnode; } /* logfile */ for ( i = 0 ; i < LOGFILES ; i++ ) { char logfile_name[NAME_MAX]; sprintf(logfile_name, "%s/%02d.log", log_dir, i); logfile_t *logfile = logfile_new(i, logfile_name); if ( logfile_open(logfile, 1) != 0 ) { error_log("logfile_open(%d) failed.", i); return -1; } server->logfiles[i] = logfile; } /* FIXME */ r = init_server_work_queue(server); if ( r != 0 ){ error_log("init_server_work_queue() failed."); return -1; } return 0; }
/* * open the csv log file - we do this opportunistically, because * we don't know if CSV logging will be wanted. */ static void open_cvs_logfile(void) { char* filename; filename = logfile_getname(time(NULL), ".csv"); cvs_logfile = logfile_open(filename, "a", false); pfree(filename); }
bool logfile_stat(const char *fname) { struct stat st; int fd = open(fname, O_RDONLY); if (fd == -1 || fstat(fd, &st) < 0) { if (fd != -1) close(fd); fclose(logf); logf = NULL; if (!logfile_open()) return 0; } return 1; }
//set last int logger_write(logger_t * logger, int loglv, const char* fmt, ...) { if (logger == nullptr){ logger = G_LOGGER; } if (loglv < logger->conf.lv){ return 0; } logger_lock(logger); va_list ap; va_start(ap, fmt); int n = 0; logger->last_err = errno; char * msg_start = (char*)logger->last_msg.data(); n = vsnprintf(msg_start, logger->last_msg.capacity() - 1, fmt, ap); va_end(ap); int available_size = logger->last_msg.capacity() - (n + 2); char errorno_msg_buff[128]; if (loglv >= LOG_LVL_WARNING && available_size > 16){ if (msg_start[n-1] == '\n'){ --n; } snprintf(&msg_start[n], available_size, " [system errno:%d(%s)]\n", errno, strerror_r(errno, errorno_msg_buff, sizeof(errorno_msg_buff)-1)); } if (logger->pf){ fputs(msg_start, logger->pf); if (ftell(logger->pf) >= logger->conf.max_file_size){ //shift file <> fflush(logger->pf); fclose(logger->pf); string nextfile = logger->logfile + "." + std::to_string(logger->next_rollid); rename(logger->logfile.c_str(), nextfile.c_str()); int nextrollid = (logger->next_rollid + 1) % logger->conf.max_roll; if (nextrollid == 0) nextrollid = 3; if ((logger->pf = logfile_open(logger->logfile.c_str(), nextrollid))){ logger->next_rollid = nextrollid; } } } else{ fputs(logger->last_msg.c_str(), stderr); } logger_unlock(logger); return n; }
logger_t * logger_create(const logger_config_t & conf){ FILE * pf = nullptr; int nextrollid = 0; string filepath = conf.dir + "/" + conf.pattern; if (filepath.length() > 1){ pf = logfile_open(filepath.c_str(), nextrollid); } logger_t * em = new logger_t(); if (!em) return nullptr; em->last_msg.reserve(conf.max_msg_size); em->conf = conf; em->inited = true; em->next_rollid = nextrollid; em->logfile = filepath; em->pf = pf; return em; }
void logfile(int type, const char *msg) { if (!logf && !logfile_open()) return; if (!logfile_stat(".l")) return; if (!egg_strncasecmp(msg, log_last, sizeof(log_last))) { repeats++; return; } if (repeats) { fprintf(logf, "Last message repeated %d times.\n", repeats); repeats = 0; } strlcpy(log_last, msg, sizeof(log_last)); fprintf(logf, "%s\n", msg); if (flush_log) fflush(logf); }
/* * Postmaster subroutine to start a syslogger subprocess. */ int SysLogger_Start(void) { pid_t sysloggerPid; char *filename; if (!Logging_collector) return 0; /* * If first time through, create the pipe which will receive stderr * output. * * If the syslogger crashes and needs to be restarted, we continue to use * the same pipe (indeed must do so, since extant backends will be writing * into that pipe). * * This means the postmaster must continue to hold the read end of the * pipe open, so we can pass it down to the reincarnated syslogger. This * is a bit klugy but we have little choice. */ #ifndef WIN32 if (syslogPipe[0] < 0) { if (pipe(syslogPipe) < 0) ereport(FATAL, (errcode_for_socket_access(), (errmsg("could not create pipe for syslog: %m")))); } #else if (!syslogPipe[0]) { SECURITY_ATTRIBUTES sa; memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES)); sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = TRUE; if (!CreatePipe(&syslogPipe[0], &syslogPipe[1], &sa, 32768)) ereport(FATAL, (errcode_for_file_access(), (errmsg("could not create pipe for syslog: %m")))); } #endif /* * Create log directory if not present; ignore errors */ mkdir(Log_directory, S_IRWXU); /* * The initial logfile is created right in the postmaster, to verify that * the Log_directory is writable. We save the reference time so that the * syslogger child process can recompute this file name. * * It might look a bit strange to re-do this during a syslogger restart, * but we must do so since the postmaster closed syslogFile after the * previous fork (and remembering that old file wouldn't be right anyway). * Note we always append here, we won't overwrite any existing file. This * is consistent with the normal rules, because by definition this is not * a time-based rotation. */ first_syslogger_file_time = time(NULL); filename = logfile_getname(first_syslogger_file_time, NULL); syslogFile = logfile_open(filename, "a", false); pfree(filename); #ifdef EXEC_BACKEND switch ((sysloggerPid = syslogger_forkexec())) #else switch ((sysloggerPid = fork_process())) #endif { case -1: ereport(LOG, (errmsg("could not fork system logger: %m"))); return 0; #ifndef EXEC_BACKEND case 0: /* in postmaster child ... */ /* Close the postmaster's sockets */ ClosePostmasterPorts(true); /* Lose the postmaster's on-exit routines */ on_exit_reset(); /* Drop our connection to postmaster's shared memory, as well */ PGSharedMemoryDetach(); /* do the work */ SysLoggerMain(0, NULL); break; #endif default: /* success, in postmaster */ /* now we redirect stderr, if not done already */ if (!redirection_done) { #ifndef WIN32 fflush(stdout); if (dup2(syslogPipe[1], fileno(stdout)) < 0) ereport(FATAL, (errcode_for_file_access(), errmsg("could not redirect stdout: %m"))); fflush(stderr); if (dup2(syslogPipe[1], fileno(stderr)) < 0) ereport(FATAL, (errcode_for_file_access(), errmsg("could not redirect stderr: %m"))); /* Now we are done with the write end of the pipe. */ close(syslogPipe[1]); syslogPipe[1] = -1; #else int fd; /* * open the pipe in binary mode and make sure stderr is binary * after it's been dup'ed into, to avoid disturbing the pipe * chunking protocol. */ fflush(stderr); fd = _open_osfhandle((intptr_t) syslogPipe[1], _O_APPEND | _O_BINARY); if (dup2(fd, _fileno(stderr)) < 0) ereport(FATAL, (errcode_for_file_access(), errmsg("could not redirect stderr: %m"))); close(fd); _setmode(_fileno(stderr), _O_BINARY); /* * Now we are done with the write end of the pipe. * CloseHandle() must not be called because the preceding * close() closes the underlying handle. */ syslogPipe[1] = 0; #endif redirection_done = true; } /* postmaster will never write the file; close it */ fclose(syslogFile); syslogFile = NULL; return (int) sysloggerPid; } /* we should never reach here */ return 0; }
/* * Postmaster subroutine to start a syslogger subprocess. */ int syslog_start(void) { pid_t pid; char *filename; if (!log_collector) return 0; /* * If first time through, create the pipe which will receive stderr * output. If syslog crashes and needs to be restarted, we continue to * use the same pipe. Indeed must do so, since extant backends will be * writing into that pipe. * * This means the postmaster must continue to hold the read end of the * pipe open, so we can pass it down to the reincarnated syslogger. This * is a bit klugy but we have little choice. */ #ifndef WIN32 if (syslog_pipe[0] < 0) { if (pgpipe(syslog_pipe) < 0) ereport(FATAL, ( errcode_sock_access(), errmsg("could not create pipe for syslog: %m"))); } #else if (!syslog_pipe[0]) { SECURITY_ATTRIBUTES sa; memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES)); sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = TRUE; if (!CreatePipe(&syslog_pipe[0], &syslog_pipe[1], &sa, 32768)) ereport(FATAL, ( errcode_file_access(), errmsg("could not create pipe for syslog: %m"))); } #endif /* * Create log directory if not present; ignore errors */ mkdir(log_directory, S_IRWXU); /* * The initial logfile is created right in the postmaster, to verify i * that the log_directory is writable. */ filename = logfile_getname(time(NULL), NULL); syslog_file = logfile_open(filename, "a", false); pfree(filename); #ifdef EXEC_BACKEND switch ((pid = syslog_forkexec())) { #else switch ((pid = fork_process())) { #endif case -1: ereport(LOG, (errmsg("could not fork system logger: %m"))); return 0; #ifndef EXEC_BACKEND case 0: /* in postmaster child ... */ /* Close the postmaster's sockets */ close_ports(true); /* Lose the postmaster's on-exit routines */ on_exit_reset(); /* Drop our connection to postmaster's shared memory */ shm_child_detach(); /* do the work */ syslog_main(0, NULL); break; #endif default: /* success, in postmaster */ /* now we redirect stderr, if not done already */ if (!redirection_done) { #ifndef WIN32 fflush(stdout); if (dup2(syslog_pipe[1], fileno(stdout)) < 0) { ereport(FATAL, ( errcode_file_access(), errmsg("could not redirect stdout: %m"))); } fflush(stderr); if (dup2(syslog_pipe[1], fileno(stderr)) < 0) { ereport(FATAL, ( errcode_file_access(), errmsg("could not redirect stderr: %m"))); } /* Now we are done with the write end of pipe */ close(syslog_pipe[1]); syslog_pipe[1] = -1; #else int fd; /* * open the pipe in binary mode and make sure stderr is binary * after it's been dup'ed into, to avoid disturbing the pipe * chunking protocol. */ fflush(stderr); fd = _open_osfhandle((intptr_t) syslog_pipe[1], _O_APPEND | _O_BINARY); if (dup2(fd, _fileno(stderr)) < 0) ereport(FATAL, ( errcode_file_access(), errmsg("could not redirect stderr: %m"))); close(fd); _setmode(_fileno(stderr), _O_BINARY); /* Now we are done with the write end of the pipe. */ CloseHandle(syslog_pipe[1]); syslog_pipe[1] = 0; #endif redirection_done = true; } /* postmaster will never write the file; close it */ fclose(syslog_file); syslog_file = NULL; return (int) pid; } /* we should never reach here */ return 0; } #ifdef EXEC_BACKEND /* * syslog_forkexec() - * * Format up the arglist for, then fork and exec, a syslogger process */ static pid_t syslog_forkexec(void) { char *av[10]; int ac = 0; char filenobuf[32]; av[ac++] = "postgres"; av[ac++] = "--forklog"; av[ac++] = NULL; /* filled in by master_forkexec */ /* static variables (those not passed by write_backend_variables) */ #ifndef WIN32 if (syslog_file != NULL) snprintf(filenobuf, sizeof(filenobuf), "%d", fileno(syslog_file)); else strcpy(filenobuf, "-1"); #else /* WIN32 */ if (syslog_file != NULL) snprintf(filenobuf, sizeof(filenobuf), "%ld", (long) _get_osfhandle(_fileno(syslog_file))); else strcpy(filenobuf, "0"); #endif /* WIN32 */ av[ac++] = filenobuf; av[ac] = NULL; ASSERT(ac < lengthof(av)); return master_forkexec(ac, av); }
/* * perform logfile rotation */ static void logfile_rotate(bool time_based_rotation, int size_rotation_for) { char* filename; char* csv_filename = NULL; pg_time_t fntime; FILE* fh; rotation_requested = false; /* * When doing a time-based rotation, invent the new logfile name based on * the planned rotation time, not current time, to avoid "slippage" in the * file name when we don't do the rotation immediately. */ if (time_based_rotation) fntime = next_rotation_time; else fntime = time(NULL); filename = logfile_getname(fntime, NULL); if (cvs_logfile != NULL) csv_filename = logfile_getname(fntime, ".csv"); /* * Decide whether to overwrite or append. We can overwrite if (a) * log_truncate_on_rotation is set, (b) the rotation was triggered by * elapsed time and not something else, and (c) the computed file name is * different from what we were previously logging into. * * Note: during the first rotation after forking off from the postmaster, * last_file_name will be NULL. (We don't bother to set it in the * postmaster because it ain't gonna work in the EXEC_BACKEND case.) So we * will always append in that situation, even though truncating would * usually be safe. * * For consistency, we treat CSV logs the same even though they aren't * opened in the postmaster. */ if (time_based_rotation || (size_rotation_for & DEST_STDERR)) { if (log_truncate_on_rotation && time_based_rotation && last_file_name != NULL && strcmp(filename, last_file_name) != 0) fh = logfile_open(filename, "w", true); else fh = logfile_open(filename, "a", true); if (!fh) { /* * ENFILE/EMFILE are not too surprising on a busy system; just * keep using the old file till we manage to get a new one. * Otherwise, assume something's wrong with log_directory and stop * trying to create files. */ if (errno != ENFILE && errno != EMFILE) { ereport(LOG, ( errmsg("disabling automatic rotation (use SIGHUP to re-enable)"))); log_rotation_age = 0; log_rotation_size = 0; } if (filename) pfree(filename); if (csv_filename) pfree(csv_filename); return; } fclose(syslog_file); syslog_file = fh; /* instead of pfree'ing filename, remember it for next time */ if (last_file_name != NULL) pfree(last_file_name); last_file_name = filename; filename = NULL; } /* Same as above, but for csv file. */ if (cvs_logfile != NULL && (time_based_rotation || (size_rotation_for & DEST_CSVLOG))) { if (log_truncate_on_rotation && time_based_rotation && last_csv_file_name != NULL && strcmp(csv_filename, last_csv_file_name) != 0) fh = logfile_open(csv_filename, "w", true); else fh = logfile_open(csv_filename, "a", true); if (!fh) { /* * ENFILE/EMFILE are not too surprising on a busy system; just * keep using the old file till we manage to get a new one. * Otherwise, assume something's wrong with log_directory and stop * trying to create files. */ if (errno != ENFILE && errno != EMFILE) { ereport(LOG, ( errmsg("disabling automatic rotation (use SIGHUP to re-enable)"))); log_rotation_age = 0; log_rotation_size = 0; } if (filename) pfree(filename); if (csv_filename) pfree(csv_filename); return; } fclose(cvs_logfile); cvs_logfile = fh; /* instead of pfree'ing filename, remember it for next time */ if (last_csv_file_name != NULL) pfree(last_csv_file_name); last_csv_file_name = csv_filename; csv_filename = NULL; } if (filename) pfree(filename); if (csv_filename) pfree(csv_filename); set_next_rotation_time(); }