epo 0.0.1 → 0.0.2
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/README +19 -4
- data/Rakefile +1 -1
- data/TODO +1 -8
- data/lib/epo/core/db.rb +65 -6
- data/lib/epo/core/observer.rb +25 -26
- data/lib/epo.rb +1 -1
- metadata +5 -5
data/README
CHANGED
@@ -43,14 +43,14 @@ $ tree db/
|
|
43
43
|
db/
|
44
44
|
└── user
|
45
45
|
├── peter
|
46
|
-
| ├── resource-default.json [1a]
|
46
|
+
| ├── resource-epo-default.json [1a]
|
47
47
|
| └── picture.png [1b]
|
48
48
|
├── jon
|
49
|
-
| ├── resource-default.json [2a]
|
49
|
+
| ├── resource-epo-default.json [2a]
|
50
50
|
| ├── picture.png [2b]
|
51
51
|
| └── pubkey.rsa.txt [2c]
|
52
52
|
└── marc
|
53
|
-
├── resource-default.json [3a]
|
53
|
+
├── resource-epo-default.json [3a]
|
54
54
|
├── picture.png [3b]
|
55
55
|
└── thumbnail.dat [3c]
|
56
56
|
|
@@ -150,7 +150,22 @@ Iterates on all the DB items (as observations)
|
|
150
150
|
|
151
151
|
welo >= 0.1.0
|
152
152
|
derailleur >= 0.5.0
|
153
|
-
a JSON library if you use json formatting
|
153
|
+
a JSON library if you use json formatting (recommended)
|
154
|
+
|
155
|
+
== Benchmark
|
156
|
+
Config:
|
157
|
+
* macbook pro (2010), without SSD:
|
158
|
+
* ruby 1.9.2
|
159
|
+
* json 1.5.1
|
160
|
+
|
161
|
+
$ ruby example/benchmark.rb
|
162
|
+
0.770000 1.020000 1.790000 ( 4.563546)
|
163
|
+
5935
|
164
|
+
1.160000 0.420000 1.580000 ( 1.601897)
|
165
|
+
|
166
|
+
So, roughly 5 seconds to write 6000 records, and 2 seconds to read them back.
|
167
|
+
No sync operation nor cache flush was forced in between the results. That's maybe why
|
168
|
+
we can read back only 5935 records out of 6000.
|
154
169
|
|
155
170
|
== License
|
156
171
|
|
data/Rakefile
CHANGED
data/TODO
CHANGED
@@ -1,9 +1,2 @@
|
|
1
|
-
*
|
2
|
-
* maybe with some modifications to Derailleur:
|
3
|
-
- graceful not found case
|
4
|
-
- clever pruning when finding:
|
5
|
-
- when path is a directory and there is no node, prune
|
6
|
-
- when path is a directory but there is a node, continue
|
7
|
-
- cache observation structs somewhere in the db or in the observer
|
8
|
-
* fiber-friendly batch operations
|
1
|
+
* nesting/epitheting resources
|
9
2
|
* register on inotify events
|
data/lib/epo/core/db.rb
CHANGED
@@ -39,7 +39,7 @@ module EPO
|
|
39
39
|
# Registers a model on a derailleur node at its path_model
|
40
40
|
# Does not modify self.models
|
41
41
|
def build_route_for_model(model)
|
42
|
-
path = model.path_model(identifying_sym)
|
42
|
+
path = File.join(model.path_model(identifying_sym), ':filename')
|
43
43
|
node = build_route(path)
|
44
44
|
node.content = model
|
45
45
|
end
|
@@ -75,20 +75,79 @@ module EPO
|
|
75
75
|
extensions.find{|ext| ext == File.extname(path)}
|
76
76
|
end
|
77
77
|
|
78
|
+
# Returns the main name of a path, i.e., the basename without
|
79
|
+
# the extension
|
80
|
+
# * main_name('/a/b/c/foo.bar') #=> 'foo'
|
81
|
+
def main_name(path)
|
82
|
+
File.basename(path).sub(/\.[^\.]+$/,'')
|
83
|
+
end
|
84
|
+
|
85
|
+
def understands_filename?(path)
|
86
|
+
understands_ext?(path) and
|
87
|
+
understands_main_name?(path)
|
88
|
+
end
|
89
|
+
|
90
|
+
def understands_main_name?(path)
|
91
|
+
main_name(path) =~ resource_regexp
|
92
|
+
end
|
93
|
+
|
94
|
+
RESOURCE_REGEXP = %r{resource-epo-\w+}
|
95
|
+
|
96
|
+
def resource_regexp
|
97
|
+
RESOURCE_REGEXP
|
98
|
+
end
|
99
|
+
|
78
100
|
# Returns the perspective name and extension name (a 2 items array)
|
79
101
|
# for the given path.
|
80
102
|
# By default the blobs for resources content are stored in files named
|
81
103
|
# 'resource-<persp><ext>' with ext starting with a dot
|
82
104
|
def persp_and_ext_for_basename(path)
|
83
|
-
|
84
|
-
[base, File.extname(path)]
|
105
|
+
[main_name(path).sub('resource-epo-',''), File.extname(path)]
|
85
106
|
end
|
86
107
|
|
87
108
|
# Returns the basename of a resource blob for a perspective named persp and
|
88
109
|
# in a format with extension ext (including the leading dot).
|
89
110
|
# see also persp_and_ext_for_basename
|
90
111
|
def basename_for_persp_and_ext(persp, ext)
|
91
|
-
"resource-#{persp}#{ext}"
|
112
|
+
"resource-epo-#{persp}#{ext}"
|
113
|
+
end
|
114
|
+
|
115
|
+
# Deletes a resource by removing its identifying directory. Beware because
|
116
|
+
# this method doesn't care about other files which may coexist in the same
|
117
|
+
# filesystem branch.
|
118
|
+
def delete_completely(root, resource)
|
119
|
+
path = File.join(root, resource.path(identifying_sym))
|
120
|
+
FileUtils.rm_rf(path)
|
121
|
+
|
122
|
+
# removes the empty directories upward
|
123
|
+
(resource.identifiers(identifying_sym).size - 1).times do |t|
|
124
|
+
path = File.split(path).first
|
125
|
+
begin
|
126
|
+
FileUtils.rmdir(path)
|
127
|
+
rescue Errno::ENOTEMPTY
|
128
|
+
break
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def delete(root, resource)
|
134
|
+
remaining_path = File.join(root, resource.path(identifying_sym))
|
135
|
+
# removes the resource-epo-* files
|
136
|
+
Dir.entries(remaining_path).each do |e|
|
137
|
+
if e.start_with?('resource-epo-')
|
138
|
+
FileUtils.rm(File.join(remaining_path, e))
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# removes the empty directories upward
|
143
|
+
resource.identifiers(identifying_sym).size.times do |t|
|
144
|
+
begin
|
145
|
+
Dir.rmdir(remaining_path)
|
146
|
+
remaining_path = File.split(remaining_path).first
|
147
|
+
rescue Errno::ENOTEMPTY
|
148
|
+
break
|
149
|
+
end
|
150
|
+
end
|
92
151
|
end
|
93
152
|
|
94
153
|
# Saves one or more resource at the filesystem path given at root
|
@@ -171,7 +230,7 @@ module EPO
|
|
171
230
|
# Iterates on every resource found and understood in the filesystem
|
172
231
|
# directory root.
|
173
232
|
# If no block is given, returns an iterator.
|
174
|
-
def
|
233
|
+
def each_resource_observation(root)
|
175
234
|
if block_given?
|
176
235
|
xp = observer
|
177
236
|
models.each do |model|
|
@@ -181,7 +240,7 @@ module EPO
|
|
181
240
|
end
|
182
241
|
xp.read_tree(root)
|
183
242
|
else
|
184
|
-
Enumerator.new(self, :
|
243
|
+
Enumerator.new(self, :each_resource_observation, root)
|
185
244
|
end
|
186
245
|
end
|
187
246
|
|
data/lib/epo/core/observer.rb
CHANGED
@@ -21,6 +21,9 @@ module EPO
|
|
21
21
|
# The DB able to tell if a path is understandable or not
|
22
22
|
attr_accessor :db
|
23
23
|
|
24
|
+
# A cache for the observation structures
|
25
|
+
attr_accessor :structures
|
26
|
+
|
24
27
|
# Creates and return a new observer from a DB.
|
25
28
|
# It will take the models from the DB.
|
26
29
|
def self.for_db(db)
|
@@ -34,35 +37,26 @@ module EPO
|
|
34
37
|
def initialize(models=[])
|
35
38
|
super(models)
|
36
39
|
@db = DB.new(models)
|
40
|
+
@structures = {}
|
37
41
|
register(:observation) do |o|
|
38
42
|
dispatch(o)
|
39
43
|
end
|
40
44
|
end
|
41
45
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
# the root is likely to be:
|
47
|
-
# /home/crapooze/project/foobar/db
|
48
|
-
# If a successful observation happens, then it will call the relevant hooks.
|
49
|
-
def read_path(path, root=nil)
|
50
|
-
full_dirname, base = File.split(path)
|
51
|
-
dirname = if root
|
52
|
-
full_dirname.sub(root,'')
|
53
|
-
else
|
54
|
-
full_dirname
|
55
|
-
end
|
56
|
-
#XXX may raise an exception for unknown path, we should rescue this/use a
|
57
|
-
#silent method and test for nil
|
58
|
-
node = db.get_route(dirname)
|
46
|
+
def get_node_for_path(path, root=nil)
|
47
|
+
path = path.sub(root,'') if root
|
48
|
+
db.get_route_silent(path)
|
49
|
+
end
|
59
50
|
|
51
|
+
def read_path_as_resource(path, model)
|
60
52
|
persp_str = db.persp_and_ext_for_basename(path).first
|
61
|
-
persp =
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
53
|
+
persp = model.perspectives.keys.find{|k| k.to_s == persp_str}
|
54
|
+
observe_source(Source.new(db, path), structure(model, persp))
|
55
|
+
end
|
56
|
+
|
57
|
+
def structure(model, persp)
|
58
|
+
pair = [model, persp]
|
59
|
+
@structures[pair] ||= Welo::ObservationStruct.new_for_resource_in_perspective(model, persp)
|
66
60
|
end
|
67
61
|
|
68
62
|
# Recursively reads the files in the filesystem (with Find).
|
@@ -70,10 +64,15 @@ module EPO
|
|
70
64
|
# Currently, there is no pruning, or control possible.
|
71
65
|
def read_tree(root)
|
72
66
|
Find.find(root) do |path|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
67
|
+
node = get_node_for_path(path, root)
|
68
|
+
if node
|
69
|
+
if node.content #a model attached to a file in a directory
|
70
|
+
if db.understands_filename?(path)
|
71
|
+
read_path_as_resource(path, node.content)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
else #the db doesn't understand this branch, we'd rather drop now
|
75
|
+
Find.prune
|
77
76
|
end
|
78
77
|
end
|
79
78
|
end
|
data/lib/epo.rb
CHANGED
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 2
|
9
|
+
version: 0.0.2
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- crapooze
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-03-
|
17
|
+
date: 2011-03-27 00:00:00 -04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -28,8 +28,8 @@ dependencies:
|
|
28
28
|
segments:
|
29
29
|
- 0
|
30
30
|
- 0
|
31
|
-
-
|
32
|
-
version: 0.0.
|
31
|
+
- 6
|
32
|
+
version: 0.0.6
|
33
33
|
type: :runtime
|
34
34
|
version_requirements: *id001
|
35
35
|
- !ruby/object:Gem::Dependency
|