dshelf 0.1

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/lib/dshelf.rb ADDED
@@ -0,0 +1,49 @@
1
+ module DistributedShelf
2
+ VERSION = '0.1'
3
+
4
+ @@config = {}
5
+
6
+ def override_class_method method, &b
7
+ (class << self; self; end).class_eval do
8
+ alias_method "_#{method.to_s}".to_sym, method
9
+ define_method method, &b
10
+ end
11
+ end
12
+
13
+ def distributed? file
14
+ @@config[:distributed_path] and not File.absolute_path(file).match(@@config[:distributed_path]).nil?
15
+ end
16
+
17
+ def proxy_method(method, &b)
18
+ old_method = :"_#{method}"
19
+ override_class_method(method) do |*args, &bl|
20
+ if distributed? args[0]
21
+ b.call(*args, &bl)
22
+ else
23
+ self.send(old_method, *args, &bl)
24
+ end
25
+ end
26
+ end
27
+
28
+ def self.config= conf
29
+ @@config = conf
30
+ @@config[:distributed_path] == Regexp.new('^' + @@config[:distributed_path] + '/')
31
+ end
32
+
33
+ def server_url
34
+ @@config[:storage_url]
35
+ end
36
+
37
+ def absolutepath
38
+ File.expand_path path, Dir.pwd
39
+ end
40
+ end
41
+
42
+ $:.unshift(File.dirname(__FILE__)) unless
43
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
44
+
45
+ require 'dshelf/dir'
46
+ require 'dshelf/dfile'
47
+ require 'dshelf/file'
48
+ require 'dshelf/stat'
49
+
@@ -0,0 +1,111 @@
1
+ require 'rest_client'
2
+ require 'mime/types'
3
+
4
+ class DistributedFile
5
+ include DistributedShelf
6
+
7
+ # "r" | Read-only, starts at beginning of file (default mode).
8
+ # -----+--------------------------------------------------------
9
+ # "r+" | Read-write, starts at beginning of file.
10
+ # -----+--------------------------------------------------------
11
+ # "w" | Write-only, truncates existing file
12
+ # | to zero length or creates a new file for writing.
13
+ # -----+--------------------------------------------------------
14
+ # "w+" | Read-write, truncates existing file to zero length
15
+ # | or creates a new file for reading and writing.
16
+ # -----+--------------------------------------------------------
17
+ # "a" | Write-only, starts at end of file if file exists,
18
+ # | otherwise creates a new file for writing.
19
+ # -----+--------------------------------------------------------
20
+ # "a+" | Read-write, starts at end of file if file exists,
21
+ # | otherwise creates a new file for reading and
22
+ # | writing.
23
+ # -----+--------------------------------------------------------
24
+ # "b" | Binary file mode (may appear with
25
+ # | any of the key letters listed above).
26
+ # | Suppresses EOL <-> CRLF conversion on Windows. And
27
+ # | sets external encoding to ASCII-8BIT unless explicitly
28
+ # | specified.
29
+ # -----+--------------------------------------------------------
30
+ # "t" | Text file mode (may appear with
31
+ # | any of the key letters listed above except "b").
32
+ def initialize filename, mode='r', *args, &block
33
+ @filename = filename
34
+ @mode = mode
35
+ end
36
+
37
+ def path
38
+ @filename
39
+ end
40
+
41
+ def mimetype
42
+ return @mimetype if @mimetype
43
+ @mimetype = MIME::Types.type_for(File.basename path)
44
+ @mimetype = if @mimetype.empty?
45
+ ""
46
+ else
47
+ @mimetype[0]
48
+ end
49
+ end
50
+
51
+ [:atime, :ctime, :mtime].each do |method|
52
+ define_method method do
53
+ parse RestClient.get("#{server_url}/#{method}", {:params => {:pwd => Dir.pwd, :filename => path}, :accept => :json})
54
+ end
55
+ end
56
+
57
+ def close
58
+ # p "#{path}: closing"
59
+ end
60
+
61
+ [:lstat, :stat].each do |method|
62
+ define_method method do
63
+ DistributedStat.new path
64
+ end
65
+ end
66
+
67
+ [:truncate].each do |method|
68
+ define_method method do |integer|
69
+ "#{path}: distributed truncate #{method} to #{integer} bytes"
70
+ end
71
+ end
72
+
73
+ def read length=0, offset=0
74
+ params = {}
75
+ params[:length] = length unless length == 0
76
+ params[:offset] = offset unless offset == 0
77
+ RestClient.get("#{server_url}/storage#{absolutepath}",
78
+ {:params => params}) do |response, request, result|
79
+ case response.code
80
+ when 200
81
+ response
82
+ when 404
83
+ raise Errno::ENOENT
84
+ end
85
+ end
86
+ end
87
+
88
+ def write string
89
+ resource = RestClient::Resource.new "#{server_url}/storage#{absolutepath}"
90
+ resource.put string, :content_type => mimetype
91
+ end
92
+
93
+ # File.open(filename, mode="r" [, opt]) => file
94
+ # File.open(filename [, mode [, perm]] [, opt]) => file
95
+ # File.open(filename, mode="r" [, opt]) {|file| block } => obj
96
+ # File.open(filename [, mode [, perm]] [, opt]) {|file| block } => obj
97
+
98
+ def self.open filename, *args, &b
99
+ f = self.new filename, *args
100
+ if b
101
+ b.call(f)
102
+ f.close
103
+ else
104
+ f
105
+ end
106
+ end
107
+
108
+ def method_missing method
109
+ raise "Distributed File error: #{method} not implemented"
110
+ end
111
+ end
data/lib/dshelf/dir.rb ADDED
@@ -0,0 +1,67 @@
1
+ class Dir
2
+ class << self; include DistributedShelf end
3
+
4
+ override_class_method(:chdir) do |dir|
5
+ if distributed? dir
6
+ p "remote chdir"
7
+ @@dpwd = dir
8
+ else
9
+ @@dpwd = ''
10
+ Dir._chdir dir
11
+ end
12
+ end
13
+
14
+ @@dpwd = ''
15
+ [:getwd, :pwd].each do |method|
16
+ override_class_method(method) do
17
+ if distributed? @@dpwd
18
+ p "remote pwd"
19
+ @@dpwd
20
+ else
21
+ Dir._pwd
22
+ end
23
+ end
24
+ end
25
+
26
+ [:delete, :rmdir, :unlink].each do |method|
27
+ proxy_method(method) do |dir|
28
+ p "remote rmdir"
29
+ 0
30
+ end
31
+ end
32
+
33
+ proxy_method(:entries) do |dir|
34
+ p "remote entries"
35
+ end
36
+
37
+ proxy_method(:mkdir) do |dir|
38
+ p "remote mkdir"
39
+ end
40
+
41
+
42
+
43
+ # foreach(dirname, &b)
44
+ #
45
+ # init (name)
46
+ #
47
+ # open(name)
48
+ #
49
+ # open(name, &b)
50
+ #
51
+
52
+
53
+
54
+
55
+ # ?close
56
+ #
57
+ # each &b
58
+ #
59
+ # path
60
+ #
61
+ # ?seek
62
+ # ?pos
63
+ # ?tell
64
+ #
65
+ # read
66
+ #
67
+ end
@@ -0,0 +1,82 @@
1
+ require 'rest_client'
2
+
3
+ class File
4
+ class << self; include DistributedShelf end
5
+ def absolutepath; File.expand_path path, Dir.pwd end
6
+
7
+ [:'pipe?', :'socket?', :'sticky?'].each do |method|
8
+ proxy_method(method) do |filename| false end
9
+ end
10
+
11
+ [:atime, :ctime, :mtime, :'directory?', :'file?', :'owned?', :size, :'symlink?', :'zero?',
12
+ :'readable?', :'writable?', :'readable_real?', :'writable_real?'].each do |method|
13
+ proxy_method(method) do |filename|
14
+ File.stat(filename).send(method)
15
+ end
16
+ end
17
+
18
+ [:'exist?', :'exists?'].each do |method|
19
+ proxy_method(method) do |filename|
20
+ begin
21
+ File.stat(filename)
22
+ true
23
+ rescue
24
+ false
25
+ end
26
+ end
27
+ end
28
+
29
+ [:delete, :unlink].each do |method|
30
+ proxy_method(method) do |*args|
31
+ args = args.map do |filename| File.expand_path(filename, Dir.pwd) end
32
+ RestClient.get("#{server_url}/meta", {:params => {:method => method, :args => args}}) do |response, request, result|
33
+ case response.code
34
+ when 200
35
+ args.size
36
+ when 404
37
+ raise Errno::ENOENT
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ [:rename, :link, :symlink].each do |method|
44
+ proxy_method(method) do |*args|
45
+ args = args.map do |filename| File.expand_path(filename, Dir.pwd) end
46
+ RestClient.get("#{server_url}/meta", {:params => {:method => method, :args => args}}) do |response, request, result|
47
+ case response.code
48
+ when 200
49
+ 0
50
+ when 404
51
+ raise Errno::ENOENT
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ proxy_method(:truncate) do |filename, size|
58
+ absolutepath = File.expand_path filename, Dir.pwd
59
+ RestClient.get("#{server_url}/truncate#{absolutepath}", {:params => {:size => size}}) do |response, request, result|
60
+ case response.code
61
+ when 200
62
+ 0
63
+ when 404
64
+ raise Errno::ENOENT
65
+ end
66
+ end
67
+ end
68
+
69
+ [:stat, :lstat].each do |method|
70
+ proxy_method(method) do |filename|
71
+ Stat.new(filename)
72
+ end
73
+ end
74
+
75
+ proxy_method(:new) do |*args|
76
+ DistributedFile.new(*args)
77
+ end
78
+
79
+ proxy_method(:open) do |*args, &b|
80
+ DistributedFile.open(*args, &b)
81
+ end
82
+ end
@@ -0,0 +1,112 @@
1
+ require 'json'
2
+ require 'time'
3
+
4
+ class DistributedStat
5
+ include DistributedShelf
6
+ def path
7
+ @dpath
8
+ end
9
+
10
+ def initialize filename
11
+ @dpath = filename
12
+ RestClient.get("#{server_url}/stat#{absolutepath}", {:accept => :json}) do |response, request, result|
13
+ case response.code
14
+ when 200
15
+ parse_stat response
16
+ when 404
17
+ raise Errno::ENOENT
18
+ end
19
+ end
20
+ end
21
+
22
+ def parse_stat stat
23
+ parsed = JSON.parse stat
24
+ @dstat = {}
25
+ @dstat[:size] = parsed['size']
26
+ @dstat[:readable] = !parsed['access'].match(/read/).nil?
27
+ @dstat[:writable] = !parsed['access'].match(/write/).nil?
28
+ @dstat[:atime] = Time.parse parsed['atime']
29
+ @dstat[:ctime] = Time.parse parsed['ctime']
30
+ @dstat[:mtime] = Time.parse parsed['mtime']
31
+ @dstat[:is_file] = parsed['is_file']
32
+ @dstat[:is_dir] = parsed['is_dir']
33
+ @dstat[:is_regular] = parsed['is_regular']
34
+ end
35
+
36
+ def setgid?; true end
37
+ def setuid?; true end
38
+
39
+ def size
40
+ @dstat[:size]
41
+ end
42
+
43
+ def zero?
44
+ size == 0
45
+ end
46
+
47
+ def atime
48
+ @dstat[:atime]
49
+ end
50
+
51
+ def ctime
52
+ @dstat[:ctime]
53
+ end
54
+
55
+ def mtime
56
+ @dstat[:mtime]
57
+ end
58
+
59
+ def <=> stat
60
+ mtime <=> stat.mtime
61
+ end
62
+
63
+ [:'pipe?', :'socket?', :'sticky?', :'blockdev?', :'chardev?', :'executable?', :'executable_real?'].each do |method|
64
+ define_method(method) do || false end
65
+ end
66
+
67
+ [:blksize, :blocks, :dev, :dev_minor, :dev_major, :rdev, :rdev_minor, :rdev_major, :uid, :gid, :ino].each do |method|
68
+ define_method(method) do || nil end
69
+ end
70
+
71
+ [:'grpowned?', :'owned?'].each do |method|
72
+ define_method(method) do || true end
73
+ end
74
+
75
+ def file?
76
+ @dstat[:is_regular]
77
+ end
78
+
79
+ def directory?
80
+ @dstat[:is_dir]
81
+ end
82
+
83
+ def symlink?
84
+ not @dstat[:is_file]
85
+ end
86
+
87
+ def ftype
88
+ return 'link' if symlink?
89
+ return 'directory' if directory?
90
+ 'file'
91
+ end
92
+
93
+ [:'readable?', :'readable_real?'].each do |method|
94
+ define_method(method) do || @dstat[:readable] end
95
+ end
96
+
97
+ [:'writable?', :'writable_real?'].each do |method|
98
+ define_method(method) do || @dstat[:writable] end
99
+ end
100
+
101
+ # todo: mode nlink
102
+ end
103
+
104
+ class File
105
+ class Stat
106
+ class << self; include DistributedShelf end
107
+
108
+ proxy_method(:new) do |filename|
109
+ DistributedStat.new filename
110
+ end
111
+ end
112
+ end
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dshelf
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ version: "0.1"
9
+ platform: ruby
10
+ authors:
11
+ - Phil Pirozhkov
12
+ autorequire:
13
+ bindir: bin
14
+ cert_chain: []
15
+
16
+ date: 2010-09-18 00:00:00 +04:00
17
+ default_executable:
18
+ dependencies:
19
+ - !ruby/object:Gem::Dependency
20
+ name: rest-client
21
+ prerelease: false
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ segments:
27
+ - 1
28
+ - 4
29
+ - 0
30
+ version: 1.4.0
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: json
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ segments:
41
+ - 1
42
+ - 2
43
+ - 0
44
+ version: 1.2.0
45
+ type: :runtime
46
+ version_requirements: *id002
47
+ - !ruby/object:Gem::Dependency
48
+ name: multipart-post
49
+ prerelease: false
50
+ requirement: &id003 !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ segments:
55
+ - 1
56
+ - 0
57
+ - 0
58
+ version: 1.0.0
59
+ type: :runtime
60
+ version_requirements: *id003
61
+ - !ruby/object:Gem::Dependency
62
+ name: mime-types
63
+ prerelease: false
64
+ requirement: &id004 !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ segments:
69
+ - 1
70
+ - 0
71
+ version: "1.0"
72
+ type: :runtime
73
+ version_requirements: *id004
74
+ description: ""
75
+ email: pirj@mail.ru
76
+ executables: []
77
+
78
+ extensions: []
79
+
80
+ extra_rdoc_files: []
81
+
82
+ files:
83
+ - lib/dshelf.rb
84
+ - lib/dshelf/dfile.rb
85
+ - lib/dshelf/dir.rb
86
+ - lib/dshelf/file.rb
87
+ - lib/dshelf/stat.rb
88
+ has_rdoc: true
89
+ homepage: http://distributedshelf.com
90
+ licenses: []
91
+
92
+ post_install_message:
93
+ rdoc_options:
94
+ - --charset=UTF-8
95
+ require_paths:
96
+ - lib
97
+ required_ruby_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ segments:
102
+ - 0
103
+ version: "0"
104
+ required_rubygems_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ segments:
109
+ - 0
110
+ version: "0"
111
+ requirements: []
112
+
113
+ rubyforge_project:
114
+ rubygems_version: 1.3.6
115
+ signing_key:
116
+ specification_version: 3
117
+ summary: ""
118
+ test_files: []
119
+