1 /* |
1 /* |
2 * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. |
7 * published by the Free Software Foundation. |
43 char LogFileOutput::_vm_start_time_str[StartTimeBufferSize]; |
43 char LogFileOutput::_vm_start_time_str[StartTimeBufferSize]; |
44 |
44 |
45 LogFileOutput::LogFileOutput(const char* name) |
45 LogFileOutput::LogFileOutput(const char* name) |
46 : LogFileStreamOutput(NULL), _name(os::strdup_check_oom(name, mtLogging)), |
46 : LogFileStreamOutput(NULL), _name(os::strdup_check_oom(name, mtLogging)), |
47 _file_name(NULL), _archive_name(NULL), _current_file(0), |
47 _file_name(NULL), _archive_name(NULL), _current_file(0), |
48 _file_count(DefaultFileCount), _archive_name_len(0), |
48 _file_count(DefaultFileCount), _is_default_file_count(true), _archive_name_len(0), |
49 _rotate_size(DefaultFileSize), _current_size(0), _rotation_semaphore(1) { |
49 _rotate_size(DefaultFileSize), _current_size(0), _rotation_semaphore(1) { |
50 assert(strstr(name, Prefix) == name, "invalid output name '%s': missing prefix: %s", name, Prefix); |
50 assert(strstr(name, Prefix) == name, "invalid output name '%s': missing prefix: %s", name, Prefix); |
51 _file_name = make_file_name(name + strlen(Prefix), _pid_str, _vm_start_time_str); |
51 _file_name = make_file_name(name + strlen(Prefix), _pid_str, _vm_start_time_str); |
52 } |
52 } |
53 |
53 |
97 int ret = os::stat(filename, &st); |
97 int ret = os::stat(filename, &st); |
98 if (ret != 0) { |
98 if (ret != 0) { |
99 return false; |
99 return false; |
100 } |
100 } |
101 return (st.st_mode & S_IFMT) == S_IFREG; |
101 return (st.st_mode & S_IFMT) == S_IFREG; |
|
102 } |
|
103 |
|
104 static bool is_fifo_file(const char* filename) { |
|
105 struct stat st; |
|
106 int ret = os::stat(filename, &st); |
|
107 if (ret != 0) { |
|
108 return false; |
|
109 } |
|
110 return S_ISFIFO(st.st_mode); |
102 } |
111 } |
103 |
112 |
104 // Try to find the next number that should be used for file rotation. |
113 // Try to find the next number that should be used for file rotation. |
105 // Return UINT_MAX on error. |
114 // Return UINT_MAX on error. |
106 static uint next_file_number(const char* filename, |
115 static uint next_file_number(const char* filename, |
185 MaxRotationFileCount); |
194 MaxRotationFileCount); |
186 success = false; |
195 success = false; |
187 break; |
196 break; |
188 } |
197 } |
189 _file_count = static_cast<uint>(value); |
198 _file_count = static_cast<uint>(value); |
|
199 _is_default_file_count = false; |
190 } else if (strcmp(FileSizeOptionKey, key) == 0) { |
200 } else if (strcmp(FileSizeOptionKey, key) == 0) { |
191 julong value; |
201 julong value; |
192 success = Arguments::atojulong(value_str, &value); |
202 success = Arguments::atojulong(value_str, &value); |
193 if (!success || (value > SIZE_MAX)) { |
203 if (!success || (value > SIZE_MAX)) { |
194 errstream->print_cr("Invalid option: %s must be in range [0, " |
204 errstream->print_cr("Invalid option: %s must be in range [0, " |
212 bool LogFileOutput::initialize(const char* options, outputStream* errstream) { |
222 bool LogFileOutput::initialize(const char* options, outputStream* errstream) { |
213 if (!parse_options(options, errstream)) { |
223 if (!parse_options(options, errstream)) { |
214 return false; |
224 return false; |
215 } |
225 } |
216 |
226 |
|
227 bool file_exist = file_exists(_file_name); |
|
228 if (file_exist && _is_default_file_count && is_fifo_file(_file_name)) { |
|
229 _file_count = 0; // Prevent file rotation for fifo's such as named pipes. |
|
230 } |
|
231 |
217 if (_file_count > 0) { |
232 if (_file_count > 0) { |
218 // compute digits with filecount - 1 since numbers will start from 0 |
233 // compute digits with filecount - 1 since numbers will start from 0 |
219 _file_count_max_digits = number_of_digits(_file_count - 1); |
234 _file_count_max_digits = number_of_digits(_file_count - 1); |
220 _archive_name_len = 2 + strlen(_file_name) + _file_count_max_digits; |
235 _archive_name_len = 2 + strlen(_file_name) + _file_count_max_digits; |
221 _archive_name = NEW_C_HEAP_ARRAY(char, _archive_name_len, mtLogging); |
236 _archive_name = NEW_C_HEAP_ARRAY(char, _archive_name_len, mtLogging); |
223 |
238 |
224 log_trace(logging)("Initializing logging to file '%s' (filecount: %u" |
239 log_trace(logging)("Initializing logging to file '%s' (filecount: %u" |
225 ", filesize: " SIZE_FORMAT " KiB).", |
240 ", filesize: " SIZE_FORMAT " KiB).", |
226 _file_name, _file_count, _rotate_size / K); |
241 _file_name, _file_count, _rotate_size / K); |
227 |
242 |
228 if (_file_count > 0 && file_exists(_file_name)) { |
243 if (_file_count > 0 && file_exist) { |
229 if (!is_regular_file(_file_name)) { |
244 if (!is_regular_file(_file_name)) { |
230 errstream->print_cr("Unable to log to file %s with log file rotation: " |
245 errstream->print_cr("Unable to log to file %s with log file rotation: " |
231 "%s is not a regular file", |
246 "%s is not a regular file", |
232 _file_name, _file_name); |
247 _file_name, _file_name); |
233 return false; |
248 return false; |