Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: rubinius/rubinius
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 1805aaae0796
Choose a base ref
...
head repository: rubinius/rubinius
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 5c5905c55103
Choose a head ref
  • 3 commits
  • 5 files changed
  • 1 contributor

Commits on Sep 30, 2015

  1. Copy the full SHA
    d597e70 View commit details
  2. Copy the full SHA
    dd5d806 View commit details
  3. Copy the full SHA
    5c5905c View commit details
Showing with 125 additions and 74 deletions.
  1. +22 −1 kernel/common/io.rb
  2. +1 −0 kernel/platform/posix.rb
  3. +16 −0 rakelib/platform.rake
  4. +9 −0 spec/default.mspec
  5. +77 −73 spec/ruby/core/io/advise_spec.rb
23 changes: 22 additions & 1 deletion kernel/common/io.rb
Original file line number Diff line number Diff line change
@@ -30,6 +30,15 @@ class EAGAINWaitWritable < Errno::EAGAIN
F_SETFD = Rubinius::Config['rbx.platform.fcntl.F_SETFD']
FD_CLOEXEC = Rubinius::Config['rbx.platform.fcntl.FD_CLOEXEC']
O_CLOEXEC = Rubinius::Config['rbx.platform.file.O_CLOEXEC']

# Not available on all platforms, so these constants may be nil
POSIX_FADV_NORMAL = Rubinius::Config['rbx.platform.advise.POSIX_FADV_NORMAL']
POSIX_FADV_SEQUENTIAL = Rubinius::Config['rbx.platform.advise.POSIX_FADV_SEQUENTIAL']
POSIX_FADV_RANDOM = Rubinius::Config['rbx.platform.advise.POSIX_FADV_RANDOM']
POSIX_FADV_WILLNEED = Rubinius::Config['rbx.platform.advise.POSIX_FADV_WILLNEED']
POSIX_FADV_DONTNEED = Rubinius::Config['rbx.platform.advise.POSIX_FADV_DONTNEED']
POSIX_FADV_NOREUSE = Rubinius::Config['rbx.platform.advise.POSIX_FADV_NOREUSE']


Stat = Rubinius::Stat

@@ -1549,11 +1558,23 @@ def advise(advice, offset = 0, len = 0)
unless [:normal, :sequential, :random, :noreuse, :dontneed, :willneed].include? advice
raise NotImplementedError, "Unsupported advice: #{advice}"
end

advice = case advice
when :normal; POSIX_FADV_NORMAL
when :sequential; POSIX_FADV_SEQUENTIAL
when :random; POSIX_FADV_RANDOM
when :willneed; POSIX_FADV_WILLNEED
when :dontneed; POSIX_FADV_DONTNEED
when :noreuse; POSIX_FADV_NOREUSE
end

offset = Rubinius::Type.coerce_to offset, Integer, :to_int
len = Rubinius::Type.coerce_to len, Integer, :to_int

Rubinius.primitive :io_advise
if FFI.call_failed?(FFI::Platform::POSIX.posix_fadvise(descriptor, offset, len, advice))
Errno.handle("posix_fadvise(2) failed")
end

nil
end

1 change: 1 addition & 0 deletions kernel/platform/posix.rb
Original file line number Diff line number Diff line change
@@ -60,6 +60,7 @@ module FFI::Platform::POSIX
attach_function :munmap, [:pointer, :size_t], :int
attach_function :getpagesize, [], :int
attach_function :shutdown, [:int, :int], :int
attach_function :posix_fadvise, [:int, :off_t, :off_t, :int], :int

# inspecting
attach_function :isatty, [:int], :int
16 changes: 16 additions & 0 deletions rakelib/platform.rake
Original file line number Diff line number Diff line change
@@ -241,6 +241,22 @@ file 'runtime/platform.conf' => deps do |task|
io_constants.each { |c| cg.const c }
end.write_constants(f)

# Not available on all platforms. Try to load these constants anyway.
Rubinius::FFI::Generators::Constants.new 'rbx.platform.advise' do |cg|
cg.include 'fcntl.h'

advise_constants = %w[
POSIX_FADV_NORMAL
POSIX_FADV_SEQUENTIAL
POSIX_FADV_RANDOM
POSIX_FADV_WILLNEED
POSIX_FADV_DONTNEED
POSIX_FADV_NOREUSE
]

advise_constants.each { |c| cg.const c }
end.write_constants(f)

# Only constants needed by core are added here
Rubinius::FFI::Generators::Constants.new 'rbx.platform.fcntl' do |cg|
cg.include 'fcntl.h'
9 changes: 9 additions & 0 deletions spec/default.mspec
Original file line number Diff line number Diff line change
@@ -46,4 +46,13 @@ class MSpecScript
MSpec.enable_feature :generator
end
end

if IO.const_defined?(:POSIX_FADVISE_NORMAL) && IO.const_defined?(:POSIX_FADVISE_DONTNEED)
# Next, check to make sure both those values aren't zero; if they are, then this OS doesn't
# support it. This is a hack and should probably be improved as platform and feature
# detection changes in the build process
unless IO::POSIX_FADVISE_NORMAL.zero? && IO::POSIX_FADVISE_DONTNEED.zero?
MSpec.enable_feature :posix_fadvise
end
end
end
150 changes: 77 additions & 73 deletions spec/ruby/core/io/advise_spec.rb
Original file line number Diff line number Diff line change
@@ -2,79 +2,83 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)

describe "IO#advise" do
before :each do
@kcode, $KCODE = $KCODE, "utf-8"
@io = IOSpecs.io_fixture "lines.txt"
end

after :each do
@io.close unless @io.closed?
$KCODE = @kcode
end

it "raises a TypeError if advise is not a Symbol" do
lambda {
@io.advise("normal")
}.should raise_error(TypeError)
end

it "raises a TypeError if offsert cannot be coerced to an Integer" do
lambda {
@io.advise(:normal, "wat")
}.should raise_error(TypeError)
end

it "raises a TypeError if len cannot be coerced to an Integer" do
lambda {
@io.advise(:normal, 0, "wat")
}.should raise_error(TypeError)
end

it "raises a RangeError if offset is too big" do
lambda {
@io.advise(:normal, 10 ** 32)
}.should raise_error(RangeError)
end

it "raises a RangeError if len is too big" do
lambda {
@io.advise(:normal, 0, 10 ** 32)
}.should raise_error(RangeError)
end
with_feature :posix_fadvise do

it "raises a NotImplementedError if advise is not recognized" do
lambda{
@io.advise(:foo)
}.should raise_error(NotImplementedError)
describe "IO#advise" do
before :each do
@kcode, $KCODE = $KCODE, "utf-8"
@io = IOSpecs.io_fixture "lines.txt"
end

after :each do
@io.close unless @io.closed?
$KCODE = @kcode
end

it "raises a TypeError if advise is not a Symbol" do
lambda {
@io.advise("normal")
}.should raise_error(TypeError)
end

it "raises a TypeError if offsert cannot be coerced to an Integer" do
lambda {
@io.advise(:normal, "wat")
}.should raise_error(TypeError)
end

it "raises a TypeError if len cannot be coerced to an Integer" do
lambda {
@io.advise(:normal, 0, "wat")
}.should raise_error(TypeError)
end

it "raises a RangeError if offset is too big" do
lambda {
@io.advise(:normal, 10 ** 32)
}.should raise_error(RangeError)
end

it "raises a RangeError if len is too big" do
lambda {
@io.advise(:normal, 0, 10 ** 32)
}.should raise_error(RangeError)
end

it "raises a NotImplementedError if advise is not recognized" do
lambda{
@io.advise(:foo)
}.should raise_error(NotImplementedError)
end

it "supports the normal advice type" do
@io.advise(:normal).should be_nil
end

it "supports the sequential advice type" do
@io.advise(:sequential).should be_nil
end

it "supports the random advice type" do
@io.advise(:random).should be_nil
end

it "supports the dontneed advice type" do
@io.advise(:dontneed).should be_nil
end

it "supports the noreuse advice type" do
@io.advise(:noreuse).should be_nil
end

it "supports the willneed advice type" do
@io.advise(:willneed).should be_nil
end

it "raises an IOError if the stream is closed" do
@io.close
lambda { @io.advise(:normal) }.should raise_error(IOError)
end
end

it "supports the normal advice type" do
@io.advise(:normal).should be_nil
end

it "supports the sequential advice type" do
@io.advise(:sequential).should be_nil
end

it "supports the random advice type" do
@io.advise(:random).should be_nil
end

it "supports the dontneed advice type" do
@io.advise(:dontneed).should be_nil
end

it "supports the noreuse advice type" do
@io.advise(:noreuse).should be_nil
end

it "supports the willneed advice type" do
@io.advise(:willneed).should be_nil
end

it "raises an IOError if the stream is closed" do
@io.close
lambda { @io.advise(:normal) }.should raise_error(IOError)
end
end
end