mincore 0.0.8 → 0.0.9.pre
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.
- data/.gitignore +5 -0
- data/.travis.yml +15 -0
- data/Gemfile +4 -0
- data/README.md +30 -0
- data/Rakefile +19 -0
- data/TODO +20 -0
- data/bin/ci/before_build.sh +4 -0
- data/mincore.gemspec +23 -0
- data/test/mincore_test.rb +160 -0
- data/test/test_helper.rb +31 -0
- data/test/tinify_test.rb +16 -0
- metadata +29 -13
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
ruby-mincore
|
2
|
+
============
|
3
|
+
[](http://badge.fury.io/rb/mincore)
|
4
|
+
[](https://travis-ci.org/noushi/ruby-mincore)
|
5
|
+
[](https://codeclimate.com/github/noushi/ruby-mincore)
|
6
|
+
[](https://gemnasium.com/noushi/ruby-mincore)
|
7
|
+
|
8
|
+
Ruby bindings for Linux cache manipulation.
|
9
|
+
|
10
|
+
This project is heavily inspired from [Feh/nocache](http://github.com/Feh/nocache).
|
11
|
+
|
12
|
+
|
13
|
+
Status & Limitations
|
14
|
+
====================
|
15
|
+
|
16
|
+
Currently, the File class is extended as such:
|
17
|
+
- `mincore(filename)` is exported to Ruby in the form of an array of booleans corresponding to each page of the file.
|
18
|
+
- `cachedel(filename, count=1)` calls `posix_fadvise(2)` to purge all file pages from the cache
|
19
|
+
- `PAGESIZE` is a simple helper that returns the value of PAGESIZE (4KB on Intel)
|
20
|
+
|
21
|
+
The bindings are implemented using Ruby Inline, instead of the classic mkmf ext C.
|
22
|
+
|
23
|
+
There is a gem module generated, and the code is still beta.
|
24
|
+
|
25
|
+
Since `File.cachedel()` isn't guaranteed to work (no matter how many time you call it), the `test_cachedel_non_empty_file` most always succeeds without properly asserting that `posix_fadvise()` has worked.
|
26
|
+
|
27
|
+
Also, the tests use a `./writable_tmp_dir/` directory to store the temporary test files. `/tmp` can't be used since it's
|
28
|
+
usually a ramfs, and files will always be in cache, until they're deleted.
|
29
|
+
|
30
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rake/testtask'
|
2
|
+
require 'rake/clean'
|
3
|
+
|
4
|
+
WORKDIR='writable_tmp_dir'
|
5
|
+
|
6
|
+
CLEAN.include("#{WORKDIR}/*")
|
7
|
+
|
8
|
+
Rake::TestTask.new(:test) do |t|
|
9
|
+
t.libs << 'lib'
|
10
|
+
t.libs << 'test'
|
11
|
+
t.pattern = 'test/**/*_test.rb'
|
12
|
+
t.verbose = true
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
task :default => :test
|
19
|
+
|
data/TODO
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
- Integrate mincore functions fully in the File class : File.mincore
|
2
|
+
should be an instance method operating on the file instance
|
3
|
+
=> use GetOpenFile macro from io.h and keep the class method form
|
4
|
+
as well:
|
5
|
+
https://github.com/ruby/ruby/blob/4c2304f0004e9f1784540f3d36976aad9eab1f68/ext/socket/init.c#L181
|
6
|
+
https://github.com/ruby/ruby/blob/4c2304f0004e9f1784540f3d36976aad9eab1f68/ext/socket/init.c#L204
|
7
|
+
https://github.com/ruby/ruby/blob/4c2304f0004e9f1784540f3d36976aad9eab1f68/ext/socket/init.c#L208
|
8
|
+
|
9
|
+
- Generate proper Ruby exceptions instead of perror/exit(1)
|
10
|
+
- Fix the documentation
|
11
|
+
- Find a better way to manage the gem: auto-increment version...
|
12
|
+
- Find a (more!) proper test case for cachedel
|
13
|
+
|
14
|
+
POSTPONED
|
15
|
+
=========
|
16
|
+
- fstat() on each mincore() call is most probably overkill: we don't
|
17
|
+
need to read file status just to know if it's empty or not a
|
18
|
+
regular file, but I need to know the pageinfo array size and if I
|
19
|
+
receive the file name from inotify, its metadata should already be
|
20
|
+
in RAM...
|
data/mincore.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'mincore'
|
3
|
+
s.version = '0.0.9.pre'
|
4
|
+
s.date = '2013-11-10'
|
5
|
+
|
6
|
+
s.homepage = 'http://github.com/noushi/ruby-mincore'
|
7
|
+
s.summary = "Ruby bindings for Linux cache manipulation"
|
8
|
+
s.description = <<-DESC
|
9
|
+
micore provides Ruby bindings for Linux cache manipulation,
|
10
|
+
including cache inspection and deletion for a specific file.
|
11
|
+
DESC
|
12
|
+
s.license = 'GPL-2'
|
13
|
+
|
14
|
+
s.authors = ["Reda NOUSHI"]
|
15
|
+
s.email = 'reda_noushi@yahoo.com'
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split($/)
|
18
|
+
#s.files = ["lib/mincore.rb"]
|
19
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
20
|
+
|
21
|
+
s.add_runtime_dependency "RubyInline", [">= 3.10.1"]
|
22
|
+
s.add_development_dependency "RubyInline", [">= 3.10.1"]
|
23
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
require 'mincore'
|
5
|
+
|
6
|
+
class TestableFile
|
7
|
+
attr_reader :path, :size, :name
|
8
|
+
|
9
|
+
def initialize(size_kb=100, path='/tmp')
|
10
|
+
@path = path
|
11
|
+
FileUtils.mkdir_p(@path) unless File.directory?(@path)
|
12
|
+
|
13
|
+
@size_kb = size_kb
|
14
|
+
|
15
|
+
@name = "#{@path}/testable_file.#{rand(1000000)}"
|
16
|
+
FileUtils.touch(@name)
|
17
|
+
end
|
18
|
+
|
19
|
+
def numpages
|
20
|
+
File.open(@name).numpages
|
21
|
+
end
|
22
|
+
|
23
|
+
def cli_fill
|
24
|
+
@size_kb.times do
|
25
|
+
s = "s" * 1024
|
26
|
+
`echo -n #{s} >>#{@name}`
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def ruby_fill
|
31
|
+
File.open(@name, "w") do |f|
|
32
|
+
# s = Random.new.bytes(1024)
|
33
|
+
s = "s" * 1024
|
34
|
+
@size_kb.times do
|
35
|
+
f.write s
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
alias_method :fill, :ruby_fill
|
41
|
+
# alias_method :fill, :cli_fill
|
42
|
+
|
43
|
+
def read(pages=@size_kb)
|
44
|
+
if pages == @size_kb
|
45
|
+
`cat #{@name} >/dev/null`
|
46
|
+
else
|
47
|
+
4.times do
|
48
|
+
File.open(@name, "r").each do |line|
|
49
|
+
line
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def delete
|
56
|
+
File.delete(@name)
|
57
|
+
end
|
58
|
+
|
59
|
+
def describe
|
60
|
+
"file #{@name} of current size #{File.stat(@name).size}"
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
class MincoreTest < Test::Unit::TestCase
|
66
|
+
def test_pagesize
|
67
|
+
pagesize = `getconf PAGESIZE`.to_i
|
68
|
+
assert_equal pagesize, File.PAGESIZE
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_numpages
|
72
|
+
size_kb = rand(1000)
|
73
|
+
f = TestableFile.new(size_kb, "./writable_tmp_dir")
|
74
|
+
pagesize = File.PAGESIZE
|
75
|
+
|
76
|
+
numpages = (File.open(f.name).stat.size*1024 + pagesize -1 ) / pagesize
|
77
|
+
|
78
|
+
assert_equal numpages, f.numpages
|
79
|
+
|
80
|
+
f.delete
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_mincore_empty_file
|
84
|
+
_generic_mincore_test 0, [0,[]], :delete => true
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_mincore_non_empty_file
|
88
|
+
_generic_mincore_test 40, :delete => true
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_cachedel_empty_file
|
92
|
+
_generic_cachedel_test 0
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_cachedel_non_empty_file
|
96
|
+
_generic_cachedel_test 400
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
def _generic_mincore_test(size_kb, result=nil, delete=true)
|
101
|
+
size = size_kb * 1024
|
102
|
+
|
103
|
+
f = TestableFile.new(size_kb, "./writable_tmp_dir")
|
104
|
+
|
105
|
+
retcode, pieces = File.mincore(f.name)
|
106
|
+
|
107
|
+
assert_equal [0, []], [retcode, pieces]
|
108
|
+
|
109
|
+
return f if size == 0
|
110
|
+
|
111
|
+
f.fill
|
112
|
+
|
113
|
+
retcode, pieces = File.mincore(f.name)
|
114
|
+
|
115
|
+
assert_equal retcode, 0, f.describe
|
116
|
+
assert_equal [[true, f.numpages]], pieces.tinify
|
117
|
+
|
118
|
+
f.delete if delete
|
119
|
+
|
120
|
+
return f
|
121
|
+
end
|
122
|
+
|
123
|
+
def _generic_cachedel_test(size_kb)
|
124
|
+
f=_generic_mincore_test(size_kb, nil, false)
|
125
|
+
|
126
|
+
f.read
|
127
|
+
|
128
|
+
retcode, pieces = File.mincore(f.name)
|
129
|
+
|
130
|
+
assert_equal retcode, 0, f.describe
|
131
|
+
assert_equal [true]*(f.numpages), pieces
|
132
|
+
|
133
|
+
ret = File.cachedel(f.name, 30)
|
134
|
+
assert_equal 0, ret, f.describe
|
135
|
+
|
136
|
+
#`cachedel #{f.name}`
|
137
|
+
|
138
|
+
retcode, pieces = File.mincore(f.name)
|
139
|
+
|
140
|
+
assert_equal retcode, 0, f.describe
|
141
|
+
|
142
|
+
if size_kb == 0
|
143
|
+
ret = []
|
144
|
+
assert_equal ret, pieces.tinify, f.describe
|
145
|
+
else
|
146
|
+
ret = [[true, f.numpages]]
|
147
|
+
if ret != pieces.tinify #The code/test is still valid even if the file is fully kept cached
|
148
|
+
assert_not_equal ret, pieces.tinify, f.describe
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
f.delete
|
153
|
+
|
154
|
+
end
|
155
|
+
|
156
|
+
|
157
|
+
|
158
|
+
|
159
|
+
|
160
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
Dir.chdir File.expand_path("../../", __FILE__)
|
2
|
+
$LOAD_PATH.unshift ".", "lib", "test"
|
3
|
+
|
4
|
+
require "test/unit"
|
5
|
+
|
6
|
+
|
7
|
+
class Array
|
8
|
+
def tinify
|
9
|
+
cur = nil
|
10
|
+
ret = []
|
11
|
+
self.each_index { |x|
|
12
|
+
if x == 0
|
13
|
+
cur = self[x]
|
14
|
+
ret << [self[x],1]
|
15
|
+
next
|
16
|
+
end
|
17
|
+
|
18
|
+
if cur == self[x]
|
19
|
+
# puts "<#{ret.last}>"
|
20
|
+
ret[-1][1] += 1
|
21
|
+
else
|
22
|
+
ret << [self[x],1]
|
23
|
+
end
|
24
|
+
|
25
|
+
cur = self[x]
|
26
|
+
}
|
27
|
+
ret
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
|
data/test/tinify_test.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
class ArrayTinifyTest < Test::Unit::TestCase
|
4
|
+
def test_true
|
5
|
+
a = [true]*10
|
6
|
+
|
7
|
+
# puts "#{a.tinify}"
|
8
|
+
assert_equal [[true, 10]], a.tinify
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_true_false
|
12
|
+
a = [[true]*10, [false]*10].flatten
|
13
|
+
|
14
|
+
assert_equal [[true, 10], [false, 10]], a.tinify
|
15
|
+
end
|
16
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mincore
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: -2045603333
|
5
|
+
prerelease: 6
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
|
9
|
+
- 9
|
10
|
+
- pre
|
11
|
+
version: 0.0.9.pre
|
11
12
|
platform: ruby
|
12
13
|
authors:
|
13
14
|
- Reda NOUSHI
|
@@ -15,7 +16,7 @@ autorequire:
|
|
15
16
|
bindir: bin
|
16
17
|
cert_chain: []
|
17
18
|
|
18
|
-
date: 2013-11-
|
19
|
+
date: 2013-11-10 00:00:00 Z
|
19
20
|
dependencies:
|
20
21
|
- !ruby/object:Gem::Dependency
|
21
22
|
name: RubyInline
|
@@ -49,7 +50,7 @@ dependencies:
|
|
49
50
|
version: 3.10.1
|
50
51
|
type: :development
|
51
52
|
version_requirements: *id002
|
52
|
-
description:
|
53
|
+
description: " micore provides Ruby bindings for Linux cache manipulation, \n including cache inspection and deletion for a specific file.\n"
|
53
54
|
email: reda_noushi@yahoo.com
|
54
55
|
executables: []
|
55
56
|
|
@@ -58,10 +59,21 @@ extensions: []
|
|
58
59
|
extra_rdoc_files: []
|
59
60
|
|
60
61
|
files:
|
62
|
+
- .gitignore
|
63
|
+
- .travis.yml
|
64
|
+
- Gemfile
|
65
|
+
- README.md
|
66
|
+
- Rakefile
|
67
|
+
- TODO
|
68
|
+
- bin/ci/before_build.sh
|
61
69
|
- lib/mincore.rb
|
70
|
+
- mincore.gemspec
|
71
|
+
- test/mincore_test.rb
|
72
|
+
- test/test_helper.rb
|
73
|
+
- test/tinify_test.rb
|
62
74
|
homepage: http://github.com/noushi/ruby-mincore
|
63
75
|
licenses:
|
64
|
-
-
|
76
|
+
- GPL-2
|
65
77
|
post_install_message:
|
66
78
|
rdoc_options: []
|
67
79
|
|
@@ -79,12 +91,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
79
91
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
92
|
none: false
|
81
93
|
requirements:
|
82
|
-
- - "
|
94
|
+
- - ">"
|
83
95
|
- !ruby/object:Gem::Version
|
84
|
-
hash:
|
96
|
+
hash: 25
|
85
97
|
segments:
|
86
|
-
-
|
87
|
-
|
98
|
+
- 1
|
99
|
+
- 3
|
100
|
+
- 1
|
101
|
+
version: 1.3.1
|
88
102
|
requirements: []
|
89
103
|
|
90
104
|
rubyforge_project:
|
@@ -92,5 +106,7 @@ rubygems_version: 1.8.15
|
|
92
106
|
signing_key:
|
93
107
|
specification_version: 3
|
94
108
|
summary: Ruby bindings for Linux cache manipulation
|
95
|
-
test_files:
|
96
|
-
|
109
|
+
test_files:
|
110
|
+
- test/mincore_test.rb
|
111
|
+
- test/test_helper.rb
|
112
|
+
- test/tinify_test.rb
|