dshelf 0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+