fluentd 1.15.2-x86-mingw32 → 1.15.3-x86-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +19 -0
- data/lib/fluent/command/fluentd.rb +0 -11
- data/lib/fluent/config/yaml_parser/loader.rb +18 -1
- data/lib/fluent/file_wrapper.rb +137 -0
- data/lib/fluent/oj_options.rb +1 -2
- data/lib/fluent/plugin/in_tail.rb +1 -6
- data/lib/fluent/plugin/out_file.rb +0 -4
- data/lib/fluent/supervisor.rb +30 -11
- data/lib/fluent/version.rb +1 -1
- data/test/command/test_fluentd.rb +31 -16
- data/test/plugin/test_in_tail.rb +105 -103
- data/test/plugin/test_out_file.rb +3 -2
- data/test/test_config.rb +57 -0
- data/test/{plugin/test_file_wrapper.rb → test_file_wrapper.rb} +2 -2
- data/test/test_log.rb +15 -5
- data/test/test_supervisor.rb +37 -15
- metadata +5 -7
- data/.github/workflows/issue-auto-closer.yml +0 -12
- data/.github/workflows/stale-actions.yml +0 -22
- data/lib/fluent/plugin/file_wrapper.rb +0 -131
@@ -5,6 +5,7 @@ require 'fileutils'
|
|
5
5
|
require 'time'
|
6
6
|
require 'timecop'
|
7
7
|
require 'zlib'
|
8
|
+
require 'fluent/file_wrapper'
|
8
9
|
|
9
10
|
class FileOutputTest < Test::Unit::TestCase
|
10
11
|
def setup
|
@@ -1016,7 +1017,7 @@ class FileOutputTest < Test::Unit::TestCase
|
|
1016
1017
|
|
1017
1018
|
test 'returns filepath with index which does not exist yet' do
|
1018
1019
|
5.times do |i|
|
1019
|
-
|
1020
|
+
Fluent::FileWrapper.open(File.join(@tmp, "exist_#{i}.log"), 'a'){|f| } # open(create) and close
|
1020
1021
|
end
|
1021
1022
|
@i.find_filepath_available(File.join(@tmp, "exist_**.log")) do |path|
|
1022
1023
|
assert_equal File.join(@tmp, "exist_5.log"), path
|
@@ -1025,7 +1026,7 @@ class FileOutputTest < Test::Unit::TestCase
|
|
1025
1026
|
|
1026
1027
|
test 'creates lock directory when with_lock is true to exclude operations of other worker process' do
|
1027
1028
|
5.times do |i|
|
1028
|
-
|
1029
|
+
Fluent::FileWrapper.open(File.join(@tmp, "exist_#{i}.log"), 'a')
|
1029
1030
|
end
|
1030
1031
|
Dir.mkdir(File.join(@tmp, "exist_5.log.lock"))
|
1031
1032
|
@i.find_filepath_available(File.join(@tmp, "exist_**.log"), with_lock: true) do |path|
|
data/test/test_config.rb
CHANGED
@@ -237,6 +237,63 @@ class ConfigTest < Test::Unit::TestCase
|
|
237
237
|
])
|
238
238
|
end
|
239
239
|
|
240
|
+
def test_included_glob
|
241
|
+
write_config "#{TMP_DIR}/config.yaml", <<-EOS
|
242
|
+
config:
|
243
|
+
- !include "include/*.yaml"
|
244
|
+
EOS
|
245
|
+
write_config "#{TMP_DIR}/include/02_source2.yaml", <<-EOS
|
246
|
+
- source:
|
247
|
+
$type: dummy
|
248
|
+
tag: tag.dummy
|
249
|
+
EOS
|
250
|
+
write_config "#{TMP_DIR}/include/01_source1.yaml", <<-EOS
|
251
|
+
- source:
|
252
|
+
$type: tcp
|
253
|
+
tag: tag.tcp
|
254
|
+
parse:
|
255
|
+
$arg:
|
256
|
+
- why.parse.section.doesnot.have.arg
|
257
|
+
- huh
|
258
|
+
$type: none
|
259
|
+
EOS
|
260
|
+
write_config "#{TMP_DIR}/include/03_match1.yaml", <<-EOS
|
261
|
+
- match:
|
262
|
+
$tag: tag.*
|
263
|
+
$type: stdout
|
264
|
+
buffer:
|
265
|
+
$type: memory
|
266
|
+
flush_interval: 1s
|
267
|
+
EOS
|
268
|
+
root_conf = read_config("#{TMP_DIR}/config.yaml", use_yaml: true)
|
269
|
+
tcp_source_conf = root_conf.elements.first
|
270
|
+
dummy_source_conf = root_conf.elements[1]
|
271
|
+
parse_tcp_conf = tcp_source_conf.elements.first
|
272
|
+
match_conf = root_conf.elements[2]
|
273
|
+
|
274
|
+
assert_equal(
|
275
|
+
[
|
276
|
+
'tcp',
|
277
|
+
'tag.tcp',
|
278
|
+
'none',
|
279
|
+
'why.parse.section.doesnot.have.arg,huh',
|
280
|
+
'dummy',
|
281
|
+
'tag.dummy',
|
282
|
+
'stdout',
|
283
|
+
'tag.*',
|
284
|
+
],
|
285
|
+
[
|
286
|
+
tcp_source_conf['@type'],
|
287
|
+
tcp_source_conf['tag'],
|
288
|
+
parse_tcp_conf['@type'],
|
289
|
+
parse_tcp_conf.arg,
|
290
|
+
dummy_source_conf['@type'],
|
291
|
+
dummy_source_conf['tag'],
|
292
|
+
match_conf['@type'],
|
293
|
+
match_conf.arg,
|
294
|
+
])
|
295
|
+
end
|
296
|
+
|
240
297
|
def test_check_not_fetchd
|
241
298
|
write_config "#{TMP_DIR}/config_test_not_fetched.yaml", <<-EOS
|
242
299
|
config:
|
data/test/test_log.rb
CHANGED
@@ -4,13 +4,16 @@ require 'fluent/engine'
|
|
4
4
|
require 'fluent/log'
|
5
5
|
require 'timecop'
|
6
6
|
require 'logger'
|
7
|
+
require 'securerandom'
|
7
8
|
|
8
9
|
class LogTest < Test::Unit::TestCase
|
9
|
-
|
10
|
+
def tmp_dir
|
11
|
+
File.join(File.dirname(__FILE__), "tmp", "log", "#{ENV['TEST_ENV_NUMBER']}", SecureRandom.hex(10))
|
12
|
+
end
|
10
13
|
|
11
14
|
def setup
|
12
|
-
|
13
|
-
FileUtils.mkdir_p(
|
15
|
+
@tmp_dir = tmp_dir
|
16
|
+
FileUtils.mkdir_p(@tmp_dir)
|
14
17
|
@log_device = Fluent::Test::DummyLogDevice.new
|
15
18
|
@timestamp = Time.parse("2016-04-21 02:58:41 +0000")
|
16
19
|
@timestamp_str = @timestamp.strftime("%Y-%m-%d %H:%M:%S %z")
|
@@ -21,6 +24,13 @@ class LogTest < Test::Unit::TestCase
|
|
21
24
|
@log_device.reset
|
22
25
|
Timecop.return
|
23
26
|
Thread.current[:last_repeated_stacktrace] = nil
|
27
|
+
begin
|
28
|
+
FileUtils.rm_rf(@tmp_dir)
|
29
|
+
rescue Errno::EACCES
|
30
|
+
# It may occur on Windows because of delete pending state due to delayed GC.
|
31
|
+
# Ruby 3.2 or later doesn't ignore Errno::EACCES:
|
32
|
+
# https://github.com/ruby/ruby/commit/983115cf3c8f75b1afbe3274f02c1529e1ce3a81
|
33
|
+
end
|
24
34
|
end
|
25
35
|
|
26
36
|
sub_test_case "log level" do
|
@@ -560,7 +570,7 @@ class LogTest < Test::Unit::TestCase
|
|
560
570
|
Timecop.freeze(@timestamp)
|
561
571
|
|
562
572
|
rotate_age, rotate_size, travel_term = expected
|
563
|
-
path = "#{
|
573
|
+
path = "#{@tmp_dir}/log-dev-io-#{rotate_size}-#{rotate_age}"
|
564
574
|
|
565
575
|
logdev = Fluent::LogDeviceIO.new(path, shift_age: rotate_age, shift_size: rotate_size)
|
566
576
|
logger = ServerEngine::DaemonLogger.new(logdev)
|
@@ -585,7 +595,7 @@ class LogTest < Test::Unit::TestCase
|
|
585
595
|
with_timezone('utc') do
|
586
596
|
rotate_age = 2
|
587
597
|
rotate_size = 100
|
588
|
-
path = "#{
|
598
|
+
path = "#{@tmp_dir}/log-dev-io-#{rotate_size}-#{rotate_age}"
|
589
599
|
path0 = path + '.0'
|
590
600
|
path1 = path + '.1'
|
591
601
|
|
data/test/test_supervisor.rb
CHANGED
@@ -2,12 +2,14 @@ require_relative 'helper'
|
|
2
2
|
require 'fluent/event_router'
|
3
3
|
require 'fluent/system_config'
|
4
4
|
require 'fluent/supervisor'
|
5
|
+
require 'fluent/file_wrapper'
|
5
6
|
require_relative 'test_plugin_classes'
|
6
7
|
|
7
8
|
require 'net/http'
|
8
9
|
require 'uri'
|
9
10
|
require 'fileutils'
|
10
11
|
require 'tempfile'
|
12
|
+
require 'securerandom'
|
11
13
|
|
12
14
|
if Fluent.windows?
|
13
15
|
require 'win32/event'
|
@@ -22,17 +24,29 @@ class SupervisorTest < ::Test::Unit::TestCase
|
|
22
24
|
end
|
23
25
|
end
|
24
26
|
|
25
|
-
|
26
|
-
|
27
|
+
def tmp_dir
|
28
|
+
File.join(File.dirname(__FILE__), "tmp", "supervisor#{ENV['TEST_ENV_NUMBER']}", SecureRandom.hex(10))
|
29
|
+
end
|
27
30
|
|
28
31
|
def setup
|
29
|
-
|
30
|
-
|
32
|
+
@tmp_dir = tmp_dir
|
33
|
+
@tmp_root_dir = File.join(@tmp_dir, 'root')
|
34
|
+
FileUtils.mkdir_p(@tmp_dir)
|
35
|
+
end
|
36
|
+
|
37
|
+
def teardown
|
38
|
+
begin
|
39
|
+
FileUtils.rm_rf(@tmp_dir)
|
40
|
+
rescue Errno::EACCES
|
41
|
+
# It may occur on Windows because of delete pending state due to delayed GC.
|
42
|
+
# Ruby 3.2 or later doesn't ignore Errno::EACCES:
|
43
|
+
# https://github.com/ruby/ruby/commit/983115cf3c8f75b1afbe3274f02c1529e1ce3a81
|
44
|
+
end
|
31
45
|
end
|
32
46
|
|
33
47
|
def write_config(path, data)
|
34
48
|
FileUtils.mkdir_p(File.dirname(path))
|
35
|
-
|
49
|
+
Fluent::FileWrapper.open(path, "w") {|f| f.write data }
|
36
50
|
end
|
37
51
|
|
38
52
|
|
@@ -48,7 +62,7 @@ class SupervisorTest < ::Test::Unit::TestCase
|
|
48
62
|
enable_get_dump true
|
49
63
|
process_name "process_name"
|
50
64
|
log_level info
|
51
|
-
root_dir #{
|
65
|
+
root_dir #{@tmp_root_dir}
|
52
66
|
<log>
|
53
67
|
format json
|
54
68
|
time_format %Y
|
@@ -76,7 +90,7 @@ class SupervisorTest < ::Test::Unit::TestCase
|
|
76
90
|
assert_equal true, sys_conf.enable_get_dump
|
77
91
|
assert_equal "process_name", sys_conf.process_name
|
78
92
|
assert_equal 2, sys_conf.log_level
|
79
|
-
assert_equal
|
93
|
+
assert_equal @tmp_root_dir, sys_conf.root_dir
|
80
94
|
assert_equal :json, sys_conf.log.format
|
81
95
|
assert_equal '%Y', sys_conf.log.time_format
|
82
96
|
counter_server = sys_conf.counter_server
|
@@ -116,7 +130,7 @@ class SupervisorTest < ::Test::Unit::TestCase
|
|
116
130
|
enable_get_dump: true
|
117
131
|
process_name: "process_name"
|
118
132
|
log_level: info
|
119
|
-
root_dir: !fluent/s "#{
|
133
|
+
root_dir: !fluent/s "#{@tmp_root_dir}"
|
120
134
|
log:
|
121
135
|
format: json
|
122
136
|
time_format: "%Y"
|
@@ -144,7 +158,7 @@ class SupervisorTest < ::Test::Unit::TestCase
|
|
144
158
|
true,
|
145
159
|
"process_name",
|
146
160
|
2,
|
147
|
-
|
161
|
+
@tmp_root_dir,
|
148
162
|
:json,
|
149
163
|
'%Y',
|
150
164
|
'127.0.0.1',
|
@@ -449,7 +463,7 @@ class SupervisorTest < ::Test::Unit::TestCase
|
|
449
463
|
end
|
450
464
|
|
451
465
|
def test_load_config
|
452
|
-
tmp_dir = "#{
|
466
|
+
tmp_dir = "#{@tmp_dir}/dir/test_load_config.conf"
|
453
467
|
conf_info_str = %[
|
454
468
|
<system>
|
455
469
|
log_level info
|
@@ -520,7 +534,7 @@ class SupervisorTest < ::Test::Unit::TestCase
|
|
520
534
|
end
|
521
535
|
|
522
536
|
def test_load_config_for_logger
|
523
|
-
tmp_dir = "#{
|
537
|
+
tmp_dir = "#{@tmp_dir}/dir/test_load_config_log.conf"
|
524
538
|
conf_info_str = %[
|
525
539
|
<system>
|
526
540
|
<log>
|
@@ -547,7 +561,7 @@ class SupervisorTest < ::Test::Unit::TestCase
|
|
547
561
|
end
|
548
562
|
|
549
563
|
def test_load_config_for_daemonize
|
550
|
-
tmp_dir = "#{
|
564
|
+
tmp_dir = "#{@tmp_dir}/dir/test_load_config.conf"
|
551
565
|
conf_info_str = %[
|
552
566
|
<system>
|
553
567
|
log_level info
|
@@ -644,7 +658,7 @@ class SupervisorTest < ::Test::Unit::TestCase
|
|
644
658
|
)
|
645
659
|
def test_logger_with_rotate_age_and_rotate_size(rotate_age)
|
646
660
|
opts = Fluent::Supervisor.default_options.merge(
|
647
|
-
log_path: "#{
|
661
|
+
log_path: "#{@tmp_dir}/test", log_rotate_age: rotate_age, log_rotate_size: 10
|
648
662
|
)
|
649
663
|
sv = Fluent::Supervisor.new(opts)
|
650
664
|
log = sv.instance_variable_get(:@log)
|
@@ -674,7 +688,7 @@ class SupervisorTest < ::Test::Unit::TestCase
|
|
674
688
|
file.puts(config)
|
675
689
|
file.flush
|
676
690
|
opts = Fluent::Supervisor.default_options.merge(
|
677
|
-
log_path: "#{
|
691
|
+
log_path: "#{@tmp_dir}/test.log", config_path: file.path
|
678
692
|
)
|
679
693
|
sv = Fluent::Supervisor.new(opts)
|
680
694
|
|
@@ -699,7 +713,7 @@ class SupervisorTest < ::Test::Unit::TestCase
|
|
699
713
|
file.puts(config)
|
700
714
|
file.flush
|
701
715
|
opts = Fluent::Supervisor.default_options.merge(
|
702
|
-
log_path: "#{
|
716
|
+
log_path: "#{@tmp_dir}/test.log", config_path: file.path, config_file_type: :yaml,
|
703
717
|
)
|
704
718
|
sv = Fluent::Supervisor.new(opts)
|
705
719
|
|
@@ -773,6 +787,14 @@ class SupervisorTest < ::Test::Unit::TestCase
|
|
773
787
|
end
|
774
788
|
end
|
775
789
|
|
790
|
+
def test_per_process_path
|
791
|
+
path = Fluent::Supervisor::LoggerInitializer.per_process_path("C:/tmp/test.log", :supervisor, 0)
|
792
|
+
assert_equal(path, "C:/tmp/test-supervisor-0.log")
|
793
|
+
|
794
|
+
path = Fluent::Supervisor::LoggerInitializer.per_process_path("C:/tmp/test.log", :worker, 1)
|
795
|
+
assert_equal(path, "C:/tmp/test-1.log")
|
796
|
+
end
|
797
|
+
|
776
798
|
def create_debug_dummy_logger
|
777
799
|
dl_opts = {}
|
778
800
|
dl_opts[:log_level] = ServerEngine::DaemonLogger::DEBUG
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluentd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.15.
|
4
|
+
version: 1.15.3
|
5
5
|
platform: x86-mingw32
|
6
6
|
authors:
|
7
7
|
- Sadayuki Furuhashi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-11-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -447,10 +447,8 @@ files:
|
|
447
447
|
- ".github/ISSUE_TEMPLATE/config.yml"
|
448
448
|
- ".github/ISSUE_TEMPLATE/feature_request.yaml"
|
449
449
|
- ".github/PULL_REQUEST_TEMPLATE.md"
|
450
|
-
- ".github/workflows/issue-auto-closer.yml"
|
451
450
|
- ".github/workflows/linux-test.yaml"
|
452
451
|
- ".github/workflows/macos-test.yaml"
|
453
|
-
- ".github/workflows/stale-actions.yml"
|
454
452
|
- ".github/workflows/windows-test.yaml"
|
455
453
|
- ".gitignore"
|
456
454
|
- ".gitlab-ci.yml"
|
@@ -585,6 +583,7 @@ files:
|
|
585
583
|
- lib/fluent/event.rb
|
586
584
|
- lib/fluent/event_router.rb
|
587
585
|
- lib/fluent/ext_monitor_require.rb
|
586
|
+
- lib/fluent/file_wrapper.rb
|
588
587
|
- lib/fluent/filter.rb
|
589
588
|
- lib/fluent/fluent_log_event_router.rb
|
590
589
|
- lib/fluent/formatter.rb
|
@@ -613,7 +612,6 @@ files:
|
|
613
612
|
- lib/fluent/plugin/compressable.rb
|
614
613
|
- lib/fluent/plugin/exec_util.rb
|
615
614
|
- lib/fluent/plugin/file_util.rb
|
616
|
-
- lib/fluent/plugin/file_wrapper.rb
|
617
615
|
- lib/fluent/plugin/filter.rb
|
618
616
|
- lib/fluent/plugin/filter_grep.rb
|
619
617
|
- lib/fluent/plugin/filter_parser.rb
|
@@ -846,7 +844,6 @@ files:
|
|
846
844
|
- test/plugin/test_buffer_memory_chunk.rb
|
847
845
|
- test/plugin/test_compressable.rb
|
848
846
|
- test/plugin/test_file_util.rb
|
849
|
-
- test/plugin/test_file_wrapper.rb
|
850
847
|
- test/plugin/test_filter.rb
|
851
848
|
- test/plugin/test_filter_grep.rb
|
852
849
|
- test/plugin/test_filter_parser.rb
|
@@ -978,6 +975,7 @@ files:
|
|
978
975
|
- test/test_event.rb
|
979
976
|
- test/test_event_router.rb
|
980
977
|
- test/test_event_time.rb
|
978
|
+
- test/test_file_wrapper.rb
|
981
979
|
- test/test_filter.rb
|
982
980
|
- test/test_fluent_log_event_router.rb
|
983
981
|
- test/test_formatter.rb
|
@@ -1089,7 +1087,6 @@ test_files:
|
|
1089
1087
|
- test/plugin/test_buffer_memory_chunk.rb
|
1090
1088
|
- test/plugin/test_compressable.rb
|
1091
1089
|
- test/plugin/test_file_util.rb
|
1092
|
-
- test/plugin/test_file_wrapper.rb
|
1093
1090
|
- test/plugin/test_filter.rb
|
1094
1091
|
- test/plugin/test_filter_grep.rb
|
1095
1092
|
- test/plugin/test_filter_parser.rb
|
@@ -1221,6 +1218,7 @@ test_files:
|
|
1221
1218
|
- test/test_event.rb
|
1222
1219
|
- test/test_event_router.rb
|
1223
1220
|
- test/test_event_time.rb
|
1221
|
+
- test/test_file_wrapper.rb
|
1224
1222
|
- test/test_filter.rb
|
1225
1223
|
- test/test_fluent_log_event_router.rb
|
1226
1224
|
- test/test_formatter.rb
|
@@ -1,12 +0,0 @@
|
|
1
|
-
name: Autocloser
|
2
|
-
on: [issues]
|
3
|
-
jobs:
|
4
|
-
autoclose:
|
5
|
-
runs-on: ubuntu-latest
|
6
|
-
steps:
|
7
|
-
- name: Autoclose issues that did not follow issue template
|
8
|
-
uses: roots/issue-closer-action@v1.1
|
9
|
-
with:
|
10
|
-
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
11
|
-
issue-close-message: "@${issue.user.login} this issue was automatically closed because it did not follow the issue template"
|
12
|
-
issue-pattern: "(.*Describe the bug.*)|(.*Is your feature request related to a problem.*)"
|
@@ -1,22 +0,0 @@
|
|
1
|
-
name: "Mark or close stale issues and PRs"
|
2
|
-
on:
|
3
|
-
schedule:
|
4
|
-
- cron: "00 10 * * *"
|
5
|
-
|
6
|
-
jobs:
|
7
|
-
stale:
|
8
|
-
runs-on: ubuntu-latest
|
9
|
-
steps:
|
10
|
-
- uses: actions/stale@v3
|
11
|
-
with:
|
12
|
-
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
13
|
-
days-before-stale: 90
|
14
|
-
days-before-close: 30
|
15
|
-
stale-issue-message: "This issue has been automatically marked as stale because it has been open 90 days with no activity. Remove stale label or comment or this issue will be closed in 30 days"
|
16
|
-
stale-pr-message: "This PR has been automatically marked as stale because it has been open 90 days with no activity. Remove stale label or comment or this PR will be closed in 30 days"
|
17
|
-
close-issue-message: "This issue was automatically closed because of stale in 30 days"
|
18
|
-
close-pr-message: "This PR was automatically closed because of stale in 30 days"
|
19
|
-
stale-pr-label: "stale"
|
20
|
-
stale-issue-label: "stale"
|
21
|
-
exempt-issue-labels: "bug,enhancement,feature request,pending,work_in_progress,v1,v2"
|
22
|
-
exempt-pr-labels: "bug,enhancement,feature request,pending,work_in_progress,v1,v2"
|
@@ -1,131 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Fluentd
|
3
|
-
#
|
4
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
-
# you may not use this file except in compliance with the License.
|
6
|
-
# You may obtain a copy of the License at
|
7
|
-
#
|
8
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
-
#
|
10
|
-
# Unless required by applicable law or agreed to in writing, software
|
11
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
-
# See the License for the specific language governing permissions and
|
14
|
-
# limitations under the License.
|
15
|
-
#
|
16
|
-
|
17
|
-
require 'fluent/win32api'
|
18
|
-
|
19
|
-
module Fluent
|
20
|
-
module FileWrapper
|
21
|
-
def self.open(path, mode='r')
|
22
|
-
io = WindowsFile.new(path, mode).io
|
23
|
-
if block_given?
|
24
|
-
v = yield io
|
25
|
-
io.close
|
26
|
-
v
|
27
|
-
else
|
28
|
-
io
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def self.stat(path)
|
33
|
-
f = WindowsFile.new(path)
|
34
|
-
s = f.stat
|
35
|
-
f.close
|
36
|
-
s
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
class WindowsFile
|
41
|
-
include File::Constants
|
42
|
-
|
43
|
-
attr_reader :io
|
44
|
-
|
45
|
-
INVALID_HANDLE_VALUE = -1
|
46
|
-
|
47
|
-
def initialize(path, mode='r')
|
48
|
-
@path = path
|
49
|
-
@io = File.open(path, mode2flags(mode))
|
50
|
-
@file_handle = Win32API._get_osfhandle(@io.to_i)
|
51
|
-
@io.instance_variable_set(:@file_index, self.ino)
|
52
|
-
def @io.ino
|
53
|
-
@file_index
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
def close
|
58
|
-
@io.close
|
59
|
-
@file_handle = INVALID_HANDLE_VALUE
|
60
|
-
end
|
61
|
-
|
62
|
-
# To keep backward compatibility, we continue to use GetFileInformationByHandle()
|
63
|
-
# to get file id.
|
64
|
-
# Note that Ruby's File.stat uses GetFileInformationByHandleEx() with FileIdInfo
|
65
|
-
# and returned value is different with above one, former one is 64 bit while
|
66
|
-
# later one is 128bit.
|
67
|
-
def ino
|
68
|
-
by_handle_file_information = '\0'*(4+8+8+8+4+4+4+4+4+4) #72bytes
|
69
|
-
|
70
|
-
unless Win32API.GetFileInformationByHandle(@file_handle, by_handle_file_information)
|
71
|
-
return 0
|
72
|
-
end
|
73
|
-
|
74
|
-
by_handle_file_information.unpack("I11Q1")[11] # fileindex
|
75
|
-
end
|
76
|
-
|
77
|
-
def stat
|
78
|
-
raise Errno::ENOENT if delete_pending
|
79
|
-
s = File.stat(@path)
|
80
|
-
s.instance_variable_set :@ino, self.ino
|
81
|
-
def s.ino; @ino; end
|
82
|
-
s
|
83
|
-
end
|
84
|
-
|
85
|
-
private
|
86
|
-
|
87
|
-
def mode2flags(mode)
|
88
|
-
# Always inject File::Constants::SHARE_DELETE
|
89
|
-
# https://github.com/fluent/fluentd/pull/3585#issuecomment-1101502617
|
90
|
-
# To enable SHARE_DELETE, BINARY is also required.
|
91
|
-
# https://bugs.ruby-lang.org/issues/11218
|
92
|
-
# https://github.com/ruby/ruby/blob/d6684f063bc53e3cab025bd39526eca3b480b5e7/win32/win32.c#L6332-L6345
|
93
|
-
flags = BINARY | SHARE_DELETE
|
94
|
-
case mode.delete("b")
|
95
|
-
when "r"
|
96
|
-
flags |= RDONLY
|
97
|
-
when "r+"
|
98
|
-
flags |= RDWR
|
99
|
-
when "w"
|
100
|
-
flags |= WRONLY | CREAT | TRUNC
|
101
|
-
when "w+"
|
102
|
-
flags |= RDWR | CREAT | TRUNC
|
103
|
-
when "a"
|
104
|
-
flags |= WRONLY | CREAT | APPEND
|
105
|
-
when "a+"
|
106
|
-
flags |= RDWR | CREAT | APPEND
|
107
|
-
else
|
108
|
-
raise Errno::EINVAL.new("Unsupported mode by Fluent::FileWrapper: #{mode}")
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
# DeletePending is a Windows-specific file state that roughly means
|
113
|
-
# "this file is queued for deletion, so close any open handlers"
|
114
|
-
#
|
115
|
-
# This flag can be retrieved via GetFileInformationByHandleEx().
|
116
|
-
#
|
117
|
-
# https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getfileinformationbyhandleex
|
118
|
-
#
|
119
|
-
def delete_pending
|
120
|
-
file_standard_info = 0x01
|
121
|
-
bufsize = 1024
|
122
|
-
buf = '\0' * bufsize
|
123
|
-
|
124
|
-
unless Win32API.GetFileInformationByHandleEx(@file_handle, file_standard_info, buf, bufsize)
|
125
|
-
return false
|
126
|
-
end
|
127
|
-
|
128
|
-
return buf.unpack("QQICC")[3] != 0
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end if Fluent.windows?
|