-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
buf_file: handle "Too many open files" error to keep buffer and metadata pair #1468
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -106,10 +106,41 @@ def enqueued! | |
|
||
write_metadata(update: false) # re-write metadata w/ finalized records | ||
|
||
file_rename(@chunk, @path, new_chunk_path, ->(new_io){ @chunk = new_io }) | ||
@path = new_chunk_path | ||
begin | ||
file_rename(@chunk, @path, new_chunk_path, ->(new_io) { @chunk = new_io }) | ||
rescue => e | ||
begin | ||
file_rename(@chunk, new_chunk_path, @path, ->(new_io) { @chunk = new_io }) if File.exist?(new_chunk_path) | ||
rescue => re | ||
# In this point, restore buffer state is hard because previous `file_rename` failed by resource problem. | ||
# Retry is one possible approach but it may cause livelock under limited resources or high load environment. | ||
# So we ignore such errors for now and log better message instead. | ||
# "Too many open files" should be fixed by proper buffer configuration and system setting. | ||
end | ||
if re | ||
raise "can't enqueue buffer file. This may causes inconsistent state: path = #{@path}, error = '#{e}', retry error = '#{re}'" | ||
else | ||
raise "can't enqueue buffer file: path = #{@path}, error = '#{e}'" | ||
end | ||
end | ||
|
||
begin | ||
file_rename(@meta, @meta_path, new_meta_path, ->(new_io) { @meta = new_io }) | ||
rescue => e | ||
begin | ||
file_rename(@chunk, new_chunk_path, @path, ->(new_io) { @chunk = new_io }) if File.exist?(new_chunk_path) | ||
file_rename(@meta, new_meta_path, @meta_path, ->(new_io) { @meta = new_io }) if File.exist?(new_meta_path) | ||
rescue => re | ||
# See above | ||
end | ||
if re | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto |
||
raise "can't enqueue buffer metadata. This may causes inconsistent state: path = #{@meta_path}, error = '#{e}', retry error = '#{re}'" | ||
else | ||
raise "can't enqueue buffer metadata: path = #{@meta_path}, error = '#{e}'" | ||
end | ||
end | ||
|
||
file_rename(@meta, @meta_path, new_meta_path, ->(new_io){ @meta = new_io }) | ||
@path = new_chunk_path | ||
@meta_path = new_meta_path | ||
|
||
super | ||
|
@@ -242,14 +273,24 @@ def file_rename(file, old_path, new_path, callback=nil) | |
def create_new_chunk(path, perm) | ||
@path = self.class.generate_stage_chunk_path(path, @unique_id) | ||
@meta_path = @path + '.meta' | ||
@chunk = File.open(@path, 'wb+', perm) | ||
@chunk.set_encoding(Encoding::ASCII_8BIT) | ||
@chunk.sync = true | ||
@chunk.binmode | ||
@meta = File.open(@meta_path, 'wb', perm) | ||
@meta.set_encoding(Encoding::ASCII_8BIT) | ||
@meta.sync = true | ||
@meta.binmode | ||
begin | ||
@chunk = File.open(@path, 'wb+', perm) | ||
@chunk.set_encoding(Encoding::ASCII_8BIT) | ||
@chunk.sync = true | ||
@chunk.binmode | ||
rescue => e | ||
raise BufferOverflowError, "can't create buffer file for #{path}. Stop creating buffer files: error = #{e}" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this statement expect "too many open files" or exceptions like that? |
||
end | ||
begin | ||
@meta = File.open(@meta_path, 'wb', perm) | ||
@meta.set_encoding(Encoding::ASCII_8BIT) | ||
@meta.sync = true | ||
@meta.binmode | ||
rescue => e | ||
@chunk.close | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this requires |
||
File.unlink(@path) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto. |
||
raise BufferOverflowError, "can't create buffer metadata for #{path}. Stop creating buffer files: error = #{e}" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same comment required above. |
||
end | ||
|
||
@state = :unstaged | ||
@bytesize = 0 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's better to use else clause to simplify code.