libgfapi-ruby 0.0.8 → 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f2cf4e28e5936b345b94a5b64495a3aee76b48e6
4
- data.tar.gz: 52d88565ff4b52182ec47e0d7495b4eca46df4ca
3
+ metadata.gz: 4e77e350dc931b821a46330717902e9dcc53b145
4
+ data.tar.gz: 2edc86242e04fbc8c33e7b5182f35400f9b27cf0
5
5
  SHA512:
6
- metadata.gz: 64da0439a3d8bedf46943b3a98dba14ad1b1938a53871f6489f47df036cb711b165a318513689b030ce15bf5eea59aa0e9569c2d9307e1cd3abbca4ce8c432b8
7
- data.tar.gz: d85a6a1eea2c1fc5609a17c8217a0f41cb52598284bbde20db89aabbc21d6c49e67be55b96574b20f4a066bd1fff2d12d53df67abccb810d9bbda049dbb2f636
6
+ metadata.gz: db150aa3a1b1b3019aeba9ec219f74b94015d877ec47e024ff3306045a323050a19f523a24591600f0ef00edec53f842a2672da6f0d7e444ff2d96dfe04e19b0
7
+ data.tar.gz: dcb362fa8d89b90100015cbd45fdbbc4068b07eb19a0347980a43a6b62deb443d7296304997a69c64fece012a68cd43fd9cd11d67e3c4ca93f937c7f295bf742
@@ -338,6 +338,11 @@ module GlusterFS
338
338
  =end
339
339
  attach_function :lstat, :glfs_lstat, [:pointer, :string, :pointer], :int
340
340
 
341
+ =begin
342
+ int glfs_fsync (glfs_fd_t *fd) __THROW;
343
+ =end
344
+ attach_function :fsync, :glfs_fsync, [:pointer], :int
345
+
341
346
  =begin
342
347
  glfs_fd_t *glfs_opendir (glfs_t *fs, const char *path) __THROW;
343
348
  =end
@@ -7,7 +7,7 @@ class GlusterFS::File
7
7
  end
8
8
 
9
9
  def read_file(buf_size = 4092)
10
- raise GlusterFS::Error, "File is empty or does not exist: #{@path}" if lstat[:st_size] < 1
10
+ check_exists
11
11
  fd = GlusterFS.open(@volume.fs, @path, 0)
12
12
  temp = Tempfile.new(path.gsub('/', '-'))
13
13
  buff = FFI::MemoryPointer.new(:char, buf_size)
@@ -22,6 +22,7 @@ class GlusterFS::File
22
22
  end
23
23
 
24
24
  def read(buf_size = 4092)
25
+ check_exists
25
26
  fd = GlusterFS.open(@volume.fs, @path, 0)
26
27
  temp = ''
27
28
  buff = FFI::MemoryPointer.new(:char, buf_size)
@@ -35,9 +36,13 @@ class GlusterFS::File
35
36
  temp
36
37
  end
37
38
 
38
- def write_file(file, perms = 0644)
39
+ def write_file(file, perms = 0644, buffer_size = 4092)
39
40
  fd = GlusterFS.creat(@volume.fs, path, 2, perms)
40
- res = GlusterFS.write(fd, file.read, file.size, 0)
41
+ res = 0
42
+ until file.eof?
43
+ chunk = file.read(buffer_size)
44
+ res += GlusterFS.write(fd, chunk, chunk.size , 0)
45
+ end
41
46
  GlusterFS.close(fd)
42
47
  res
43
48
  end
@@ -67,4 +72,11 @@ class GlusterFS::File
67
72
  lstat[:st_size]
68
73
  end
69
74
 
75
+ private
76
+
77
+ # Reading non-existing file causes segfault on file.read
78
+ def check_exists
79
+ raise GlusterFS::Error, "File does not exist: #{@path}" unless exists?
80
+ end
81
+
70
82
  end
@@ -1,3 +1,3 @@
1
1
  module GlusterFS
2
- VERSION = "0.0.8"
2
+ VERSION = "0.0.9"
3
3
  end
@@ -22,5 +22,6 @@ Gem::Specification.new do |spec|
22
22
  spec.add_development_dependency "bundler", "~> 1.5"
23
23
  spec.add_development_dependency "rake"
24
24
  spec.add_development_dependency "rspec"
25
+ spec.add_development_dependency "pry-nav"
25
26
  spec.add_development_dependency "ruby-mass"
26
27
  end
@@ -48,9 +48,10 @@ module GlusterFS
48
48
  end
49
49
 
50
50
  context '#write_file' do
51
+ let(:contents) { '12345' * 1024 }
51
52
  let(:data) do
52
53
  d = Tempfile.new('test')
53
- d.write '12345'
54
+ d.write contents
54
55
  d.rewind
55
56
  d
56
57
  end
@@ -58,7 +59,26 @@ module GlusterFS
58
59
 
59
60
  context 'writes file' do
60
61
  subject { file.write_file(data) }
61
- it('returns bytes written') { should == data.length }
62
+ specify 'consistently' do
63
+ subject.should == data.length
64
+ file.read.should == contents
65
+ end
66
+ end
67
+
68
+ context 'with small buffer' do
69
+ subject { file.write_file(data, 0644, 16) }
70
+ specify 'consistently' do
71
+ subject.should == data.length
72
+ file.read.should == contents
73
+ end
74
+ end
75
+
76
+ context 'with huge buffer' do
77
+ subject { file.write_file(data, 0644, 102400) }
78
+ specify 'consistently' do
79
+ subject.should == data.length
80
+ file.read.should == contents
81
+ end
62
82
  end
63
83
 
64
84
  context 'overwrites file' do
@@ -1,9 +1,8 @@
1
1
  require 'ruby-mass'
2
2
  module GlusterFS
3
3
 
4
- # Set MEM_PRINT=1 MEM_ITERATIONS=10000 to get a stress test
5
-
6
4
  def self.mem_size
5
+ ObjectSpace.garbage_collect
7
6
  _, size = `ps ax -o pid,rss | grep -E "^[[:space:]]*#{$$}"`.strip.split.map(&:to_i)
8
7
  size.to_i
9
8
  end
@@ -22,17 +21,38 @@ module GlusterFS
22
21
  puts "RUBY_FREE_MIN=#{ENV['RUBY_FREE_MIN']}"
23
22
  puts "Initial memory use: #{GlusterFS.mem_size}"
24
23
  Mass.print
24
+ else
25
+ puts "Set MEM_PRINT=1 MEM_ITERATIONS=10000 to get a better memory stress test"
25
26
  end
26
27
  end
27
28
 
28
- let(:random_blob) do
29
- o = [('a'..'z'), ('A'..'Z')].map { |i| i.to_a }.flatten
30
- (0...15000).map { o[rand(o.length)] }.join
29
+ let!(:random_blob) do
30
+ '0' * 1048576 * 5 # 5MB
31
31
  end
32
32
  let(:volume) { Volume.new(GFS_VOLUME)
33
33
  .mount(GFS_SERVER_HOST, GFS_SERVER_PORT) }
34
34
  let(:root_dir) { Directory.new(volume, '/memtest-root') }
35
35
 
36
+ # Mem leak here! Only run when MEM_ITERATIONS is provided.
37
+ if ENV['MEM_ITERATIONS']
38
+ context 'mount / unmount volume' do
39
+ specify do
40
+ puts "Volume Iterations: #{iterations}"
41
+ mem_size_before = GlusterFS.mem_size
42
+ iterations.times do |i|
43
+ vol = Volume.new(GFS_VOLUME)
44
+ vol.mount(GFS_SERVER_HOST, GFS_SERVER_PORT)
45
+ vol.unmount
46
+ puts i
47
+ end
48
+ mem_size = GlusterFS.mem_size
49
+ puts "Mem growth: #{mem_size - mem_size_before}"
50
+ Mass.print if ENV['MEM_PRINT']
51
+ (mem_size - mem_size_before).should be < 10240
52
+ end
53
+ end
54
+ end
55
+
36
56
  context 'create many directories' do
37
57
  before { root_dir.create }
38
58
  after { root_dir.delete }
@@ -0,0 +1,77 @@
1
+ require 'ruby-mass'
2
+ require 'fileutils'
3
+ require 'benchmark'
4
+ module GlusterFS
5
+
6
+ describe 'performance' do
7
+ let(:file_mount_point) { ENV['GFS_MOUNT_DIR'] || '/mnt/dist-volume' }
8
+ let(:iterations) { (ENV['PERF_ITERATIONS'] || 100).to_i }
9
+ let!(:random_blob) do
10
+ '0' * 1048576 * 5 # 5MB
11
+ end
12
+
13
+ specify 'native file system operations' do
14
+ test_dir ="/tmp/fs-perftest-root"
15
+ FileUtils.rm_rf test_dir
16
+ time = Benchmark.realtime do
17
+ FileUtils.mkdir_p test_dir
18
+ iterations.times do |i|
19
+ dir = "#{test_dir}/perf-test-#{i}"
20
+ FileUtils.mkdir dir
21
+ file = "#{dir}/file-#{i}"
22
+ ::File.open(file, 'w+') do |f|
23
+ f.write(random_blob)
24
+ end
25
+ FileUtils.rm(file)
26
+ FileUtils.rmdir(dir)
27
+ end
28
+ FileUtils.rmdir(test_dir)
29
+ end
30
+ puts "Native FS Time: #{iterations} iterations: #{'%.4f' % time} sec"
31
+ end
32
+
33
+ specify 'mounted file system operations' do
34
+ test_dir ="#{file_mount_point}/mnt-perftest-root"
35
+ FileUtils.rm_rf test_dir
36
+ time = Benchmark.realtime do
37
+ FileUtils.mkdir_p test_dir
38
+ iterations.times do |i|
39
+ dir = "#{test_dir}/perf-test-#{i}"
40
+ FileUtils.mkdir dir
41
+ file = "#{dir}/file-#{i}"
42
+ ::File.open(file, 'w+') do |f|
43
+ f.write(random_blob)
44
+ end
45
+ FileUtils.rm(file)
46
+ FileUtils.rmdir(dir)
47
+ end
48
+ FileUtils.rmdir(test_dir)
49
+ end
50
+ puts "Mounted FS Time: #{iterations} iterations: #{'%.4f' % time} sec"
51
+ end
52
+
53
+ let(:volume) { Volume.new(GFS_VOLUME)
54
+ .mount(GFS_SERVER_HOST, GFS_SERVER_PORT) }
55
+ specify 'api operations' do
56
+ test_dir ="/gfs-perftest-root"
57
+ FileUtils.rm_rf "#{file_mount_point}/test_dir"
58
+ time = Benchmark.realtime do
59
+ gfs_test_dir = Directory.new(volume, test_dir)
60
+ gfs_test_dir.create
61
+ iterations.times do |i|
62
+ dir = "#{test_dir}/perf-test-#{i}"
63
+ gfs_dir = Directory.new(volume, dir)
64
+ gfs_dir.create
65
+ file = "#{dir}/file-#{i}"
66
+ gfs_file = File.new(volume, file)
67
+ gfs_file.write(random_blob)
68
+ gfs_file.delete
69
+ gfs_dir.delete
70
+ end
71
+ gfs_test_dir.delete
72
+ end
73
+ puts "GFS API Time: #{iterations} iterations: #{'%.4f' % time} sec"
74
+ end
75
+
76
+ end
77
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: libgfapi-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tomas Varaneckas
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - '>='
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry-nav
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: ruby-mass
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -105,6 +119,7 @@ files:
105
119
  - spec/glusterfs/directory_spec.rb
106
120
  - spec/glusterfs/file_spec.rb
107
121
  - spec/glusterfs/stress/memleak_spec.rb
122
+ - spec/glusterfs/stress/performance_spec.rb
108
123
  - spec/glusterfs/volume_spec.rb
109
124
  - spec/spec_helper.rb
110
125
  homepage: https://github.com/spajus/libgfapi-ruby
@@ -135,6 +150,7 @@ test_files:
135
150
  - spec/glusterfs/directory_spec.rb
136
151
  - spec/glusterfs/file_spec.rb
137
152
  - spec/glusterfs/stress/memleak_spec.rb
153
+ - spec/glusterfs/stress/performance_spec.rb
138
154
  - spec/glusterfs/volume_spec.rb
139
155
  - spec/spec_helper.rb
140
156
  has_rdoc: