Skip to content

Commit 10f6745

Browse files
committed
fix broken gzip file produced sometimes
1 parent 0c34403 commit 10f6745

File tree

1 file changed

+72
-20
lines changed

1 file changed

+72
-20
lines changed

Diff for: lib/logstash/outputs/file.rb

+72-20
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ class LogStash::Outputs::File < LogStash::Outputs::Base
7777
default :codec, "json_lines"
7878

7979
def register
80+
81+
8082
require "fileutils" # For mkdir_p
8183

8284
@files = {}
@@ -119,24 +121,49 @@ def multi_receive_encoded(events_and_encoded)
119121
fd.write(chunks.last)
120122
else
121123
# append to the file
122-
chunks.each {|chunk| fd.write(chunk) }
124+
chunks.each {|chunk|
125+
fd.write(chunk)
126+
}
123127
end
124-
fd.flush unless @flusher && @flusher.alive?
128+
onflush(fd, path) unless @flusher && @flusher.alive?
125129
end
126-
127130
close_stale_files
128131
end
129132
end
130133

134+
def onflush(fd, path)
135+
fd.flush
136+
if @files[path][:isTempFile]
137+
copy_to_gzip(fd, path)
138+
end
139+
end
140+
141+
def copy_to_gzip(fd, path)
142+
zipfd = getFile(path)
143+
zipfd = Zlib::GzipWriter.new(zipfd)
144+
fd.seek(0, IO::SEEK_SET)
145+
data = fd.read
146+
fd.truncate(0)
147+
fd.seek(0, IO::SEEK_SET)
148+
if @write_behavior == "overwrite"
149+
zipfd.truncate(0)
150+
zipfd.seek(0, IO::SEEK_SET)
151+
end
152+
zipfd.write(data)
153+
zipfd.flush
154+
zipfd.to_io.flush
155+
zipfd.close
156+
end
157+
131158
def close
132159
@flusher.stop unless @flusher.nil?
133160
@io_mutex.synchronize do
134161
@logger.debug("Close: closing files")
135162

136-
@files.each do |path, fd|
163+
@files.each do |path, fileObj|
137164
begin
138-
fd.close
139-
@logger.debug("Closed file #{path}", :fd => fd)
165+
fileObj[:fd].close
166+
@logger.debug("Closed file #{fileObj[:fd]}", :fd => fileObj[:fd])
140167
rescue Exception => e
141168
@logger.error("Exception while flushing and closing files.", :exception => e)
142169
end
@@ -199,9 +226,12 @@ def flush_pending_files
199226
@io_mutex.synchronize do
200227
@logger.debug("Starting flush cycle")
201228

202-
@files.each do |path, fd|
203-
@logger.debug("Flushing file", :path => path, :fd => fd)
204-
fd.flush
229+
@files.each do |path, fileObj|
230+
@logger.debug("Flushing file", :path => path, :fd => fileObj[:fd])
231+
fileObj[:fd].flush
232+
if fileObj[:isTempFile]
233+
copy_to_gzip(fileObj[:fd], path)
234+
end
205235
end
206236
end
207237
rescue => e
@@ -215,15 +245,18 @@ def close_stale_files
215245
return unless now - @last_stale_cleanup_cycle >= @stale_cleanup_interval
216246

217247
@logger.debug("Starting stale files cleanup cycle", :files => @files)
218-
inactive_files = @files.select { |path, fd| not fd.active }
248+
inactive_files = @files.select { |path, fileObj| not fileObj[:fd].active }
219249
@logger.debug("%d stale files found" % inactive_files.count, :inactive_files => inactive_files)
220-
inactive_files.each do |path, fd|
250+
inactive_files.each do |path, fileObj|
221251
@logger.info("Closing file %s" % path)
222-
fd.close
252+
fileObj[:fd].close
253+
if fileObj[:isTempFile] && File.exist?(fileObj[:fd].path)
254+
File.delete(fileObj[:fd].path)
255+
end
223256
@files.delete(path)
224257
end
225258
# mark all files as inactive, a call to write will mark them as active again
226-
@files.each { |path, fd| fd.active = false }
259+
@files.each { |path, fileObj| fileObj[:fd].active = false }
227260
@last_stale_cleanup_cycle = now
228261
end
229262

@@ -236,21 +269,41 @@ def deleted?(path)
236269
end
237270

238271
def open(path)
272+
originalPath = path
239273
if !deleted?(path) && cached?(path)
240-
return @files[path]
274+
return @files[path][:fd]
241275
end
242276

243277
if deleted?(path)
244278
if @create_if_deleted
245279
@logger.debug("Required path was deleted, creating the file again", :path => path)
246280
@files.delete(path)
247281
else
248-
return @files[path] if cached?(path)
282+
return @files[path][:fd] if cached?(path)
283+
end
284+
end
285+
286+
#Fix for broken gzip issue.
287+
if gzip
288+
tmpfile = java.io.File.createTempFile("outfile-", "-temp");
289+
path = tmpfile.path
290+
#create file at original path also, so that temp file is not created again
291+
makeDir(originalPath)
292+
gzFile = getFile(originalPath)
293+
#if gzFile is fifo type, file writer object is returned that needs to closed.
294+
if gzFile.class == Java::JavaIo::FileWriter
295+
gzFile.close
249296
end
250297
end
251298

252299
@logger.info("Opening file", :path => path)
300+
makeDir(path)
301+
fd = getFile(path)
302+
@files[originalPath] = {:fd => IOWriter.new(fd), :isTempFile => gzip}
303+
return @files[originalPath][:fd]
304+
end
253305

306+
def makeDir(path)
254307
dir = File.dirname(path)
255308
if !Dir.exist?(dir)
256309
@logger.info("Creating directory", :directory => dir)
@@ -260,7 +313,9 @@ def open(path)
260313
FileUtils.mkdir_p(dir)
261314
end
262315
end
316+
end
263317

318+
def getFile(path)
264319
# work around a bug opening fifos (bug JRUBY-6280)
265320
stat = File.stat(path) rescue nil
266321
if stat && stat.ftype == "fifo"
@@ -272,10 +327,7 @@ def open(path)
272327
fd = File.new(path, "a+")
273328
end
274329
end
275-
if gzip
276-
fd = Zlib::GzipWriter.new(fd)
277-
end
278-
@files[path] = IOWriter.new(fd)
330+
return fd
279331
end
280332

281333
##
@@ -380,4 +432,4 @@ def method_missing(method_name, *args, &block)
380432
super
381433
end
382434
end
383-
end
435+
end

0 commit comments

Comments
 (0)