pione 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. data/.gitignore +2 -1
  2. data/History.txt +11 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +1 -1
  5. data/bin/pione-log +5 -0
  6. data/example/CountChar/CountChar.pione +1 -1
  7. data/example/SieveOfEratosthenes/SieveOfEratosthenes.pione +39 -38
  8. data/lib/pione.rb +14 -35
  9. data/lib/pione/agent/input-generator.rb +38 -40
  10. data/lib/pione/agent/logger.rb +52 -19
  11. data/lib/pione/agent/rule-provider.rb +5 -8
  12. data/lib/pione/agent/task-worker.rb +25 -32
  13. data/lib/pione/agent/tuple-space-client.rb +22 -14
  14. data/lib/pione/command.rb +21 -0
  15. data/lib/pione/command/basic-command.rb +267 -84
  16. data/lib/pione/command/child-process.rb +21 -18
  17. data/lib/pione/command/daemon-process.rb +9 -8
  18. data/lib/pione/command/front-owner-command.rb +8 -25
  19. data/lib/pione/command/pione-broker.rb +27 -24
  20. data/lib/pione/command/pione-clean.rb +6 -6
  21. data/lib/pione/command/pione-client.rb +143 -128
  22. data/lib/pione/command/pione-log.rb +61 -0
  23. data/lib/pione/command/pione-relay-account-db.rb +40 -38
  24. data/lib/pione/command/pione-relay-client-db.rb +38 -42
  25. data/lib/pione/command/pione-relay.rb +19 -20
  26. data/lib/pione/command/pione-syntax-checker.rb +70 -45
  27. data/lib/pione/command/pione-task-worker.rb +56 -66
  28. data/lib/pione/command/pione-tuple-space-provider.rb +36 -45
  29. data/lib/pione/command/pione-tuple-space-receiver.rb +34 -32
  30. data/lib/pione/command/pione-tuple-space-viewer.rb +63 -47
  31. data/lib/pione/location.rb +10 -0
  32. data/lib/pione/location/basic-location.rb +272 -0
  33. data/lib/pione/location/dropbox-location.rb +139 -0
  34. data/lib/pione/location/ftp-location.rb +156 -0
  35. data/lib/pione/location/local-location.rb +116 -0
  36. data/lib/pione/log.rb +10 -0
  37. data/lib/pione/log/domain-info.rb +72 -0
  38. data/lib/pione/log/process-log.rb +176 -0
  39. data/lib/pione/log/process-record.rb +189 -0
  40. data/lib/pione/log/xes-log.rb +105 -0
  41. data/lib/pione/model/assignment.rb +88 -80
  42. data/lib/pione/model/binary-operator.rb +74 -68
  43. data/lib/pione/model/block.rb +218 -207
  44. data/lib/pione/model/boolean.rb +123 -112
  45. data/lib/pione/model/call-rule.rb +72 -65
  46. data/lib/pione/model/data-expr.rb +596 -290
  47. data/lib/pione/model/float.rb +108 -103
  48. data/lib/pione/model/integer.rb +133 -129
  49. data/lib/pione/model/message.rb +79 -72
  50. data/lib/pione/model/package.rb +42 -38
  51. data/lib/pione/model/parameters.rb +265 -236
  52. data/lib/pione/model/rule-expr.rb +247 -242
  53. data/lib/pione/model/rule-io.rb +137 -133
  54. data/lib/pione/model/rule.rb +307 -292
  55. data/lib/pione/model/string.rb +110 -99
  56. data/lib/pione/model/variable-table.rb +300 -271
  57. data/lib/pione/model/variable.rb +88 -83
  58. data/lib/pione/option.rb +13 -0
  59. data/lib/pione/option/child-process-option.rb +19 -0
  60. data/lib/pione/{command-option → option}/common-option.rb +6 -5
  61. data/lib/pione/option/option-interface.rb +73 -0
  62. data/lib/pione/{command-option → option}/presence-notifier-option.rb +4 -3
  63. data/lib/pione/option/task-worker-owner-option.rb +24 -0
  64. data/lib/pione/{command-option → option}/tuple-space-provider-option.rb +6 -4
  65. data/lib/pione/option/tuple-space-provider-owner-option.rb +18 -0
  66. data/lib/pione/option/tuple-space-receiver-option.rb +8 -0
  67. data/lib/pione/parser/common-parser.rb +3 -2
  68. data/lib/pione/parser/expr-parser.rb +6 -1
  69. data/lib/pione/patch/em-ftpd-patch.rb +21 -0
  70. data/lib/pione/patch/rinda-patch.rb +31 -23
  71. data/lib/pione/rule-handler/action-handler.rb +35 -25
  72. data/lib/pione/rule-handler/basic-handler.rb +92 -18
  73. data/lib/pione/rule-handler/flow-handler.rb +104 -98
  74. data/lib/pione/rule-handler/root-handler.rb +11 -0
  75. data/lib/pione/system/common.rb +10 -0
  76. data/lib/pione/system/file-cache.rb +103 -84
  77. data/lib/pione/system/global.rb +67 -12
  78. data/lib/pione/system/init.rb +20 -0
  79. data/lib/pione/transformer/expr-transformer.rb +6 -1
  80. data/lib/pione/tuple-space/data-finder.rb +33 -6
  81. data/lib/pione/tuple-space/tuple-space-receiver.rb +4 -3
  82. data/lib/pione/tuple-space/tuple-space-server-interface.rb +58 -13
  83. data/lib/pione/tuple-space/tuple-space-server.rb +13 -11
  84. data/lib/pione/tuple-space/update-criteria.rb +8 -7
  85. data/lib/pione/tuple/base-location-tuple.rb +9 -0
  86. data/lib/pione/tuple/basic-tuple.rb +7 -7
  87. data/lib/pione/tuple/data-tuple.rb +5 -2
  88. data/lib/pione/tuple/lift-tuple.rb +14 -0
  89. data/lib/pione/tuple/rule-tuple.rb +1 -1
  90. data/lib/pione/tuple/task-tuple.rb +5 -1
  91. data/lib/pione/version.rb +1 -1
  92. data/pione.gemspec +5 -1
  93. data/test/location/spec_basic-location.rb +35 -0
  94. data/test/location/spec_ftp-location.rb +100 -0
  95. data/test/location/spec_local-location.rb +99 -0
  96. data/test/log/data/sample.log +1003 -0
  97. data/test/log/spec_xes-log.rb +11 -0
  98. data/test/model/spec_data-expr.rb +249 -6
  99. data/test/model/spec_data-expr.yml +45 -0
  100. data/test/parser/spec_expr-parser.yml +4 -0
  101. data/test/spec_data-finder.rb +13 -7
  102. data/test/spec_data-finder.yml +42 -13
  103. data/test/system/spec_file-cache.rb +39 -0
  104. data/test/test-util.rb +226 -1
  105. data/test/transformer/spec_expr-transformer.rb +12 -1
  106. metadata +107 -24
  107. data/bin/pione-search-log +0 -30
  108. data/lib/pione/command-option/basic-option.rb +0 -42
  109. data/lib/pione/command-option/child-process-option.rb +0 -17
  110. data/lib/pione/command-option/daemon-option.rb +0 -12
  111. data/lib/pione/command-option/task-worker-owner-option.rb +0 -17
  112. data/lib/pione/command-option/tuple-space-provider-owner-option.rb +0 -16
  113. data/lib/pione/command-option/tuple-space-receiver-option.rb +0 -12
  114. data/lib/pione/command/tuple-space-provider-owner.rb +0 -6
  115. data/lib/pione/resource/basic-resource.rb +0 -92
  116. data/lib/pione/resource/dropbox-resource.rb +0 -106
  117. data/lib/pione/resource/ftp.rb +0 -84
  118. data/lib/pione/resource/local.rb +0 -113
  119. data/lib/pione/tuple/base-uri-tuple.rb +0 -9
  120. data/lib/pione/tuple/shift-tuple.rb +0 -13
  121. data/lib/pione/util/log.rb +0 -79
  122. data/test/spec_resource.rb +0 -73
@@ -1,30 +1,29 @@
1
1
  module Pione
2
2
  module RuleHandler
3
- # FlowHandler represents a handler for flow actions.
3
+ # FlowHandler is a rule handler for flow elements.
4
4
  class FlowHandler < BasicHandler
5
5
  def self.message_name
6
6
  "Flow"
7
7
  end
8
8
 
9
- # @api private
10
9
  def initialize(*args)
11
10
  super
12
11
  @data_finder = DataFinder.new(tuple_space_server, @domain)
13
12
  @finished = []
14
13
  end
15
14
 
16
- # Starts to process flow elements. This processes rule application, output
17
- # search, resource shift, and output validation.
15
+ # Start to process flow elements.
16
+ #
18
17
  # @return [void]
19
18
  def execute
20
- # restore data tuples from resource
21
- restore_data_tuples_from_resource
19
+ # restore data tuples from domain_location
20
+ restore_data_tuples_from_domain_location
22
21
  # rule application
23
22
  apply_rules(@rule.body.eval(@variable_table).elements)
24
23
  # find outputs
25
24
  find_outputs
26
- # shift resource
27
- shift_output_resources
25
+ # lift output data from child domains to this domain
26
+ lift_output_data
28
27
  # check output validation
29
28
  validate_outputs
30
29
 
@@ -33,45 +32,51 @@ module Pione
33
32
 
34
33
  private
35
34
 
36
- # Restores data tuples from the domain resource.
35
+ # Restore data tuples from the domain location. This reads files in the
36
+ # location and write it as data tuples.
37
+ #
37
38
  # @return [void]
38
- def restore_data_tuples_from_resource
39
- uri = root? ? @base_uri : @base_uri + (".%s/%s" % @domain.split("_"))
40
- if Resource[uri].exist?
41
- Resource[uri].entries.each do |res|
42
- write(Tuple[:data].new(@domain, res.basename, res.uri.to_s, res.mtime))
39
+ def restore_data_tuples_from_domain_location
40
+ dir = root? ? @base_location : @base_location + (".%s/%s" % @domain.split("_"))
41
+ if dir.exist?
42
+ dir.entries.each do |location|
43
+ unless location.basename[0] == "."
44
+ write(Tuple[:data].new(@domain, location.basename, location, location.mtime))
45
+ end
43
46
  end
44
47
  end
45
48
  end
46
49
 
47
- # Applies target input data to rules.
48
- # @param [Array<CallRule>] callees
50
+ # Apply input data to rules.
51
+ #
52
+ # @param callees [Array<CallRule>]
49
53
  # elements of call rule lines
50
54
  # @return [void]
51
55
  def apply_rules(callees)
52
56
  user_message_begin("Start Rule Application: %s" % handler_digest)
53
57
 
54
- # apply flow-element rules
55
58
  while true do
56
59
  # find updatable rule applications
57
60
  applications = select_updatables(find_applicable_rules(callees))
58
61
 
59
- unless applications.empty?
60
- # push task tuples into tuple space
61
- distribute_tasks(applications)
62
- else
63
- break # finish applications
64
- end
62
+ # check wheather applications completed
63
+ break if applications.empty?
64
+
65
+ # push tasks into tuple space
66
+ distribute_tasks(applications)
65
67
  end
66
68
 
67
69
  user_message_end("End Rule Application: %s" % handler_digest)
68
70
  end
69
71
 
70
- # Finds applicable flow-element rules with inputs and variables.
72
+ # Find applicable rules with inputs and variables.
73
+ #
74
+ # @param callees [Array<CallRule>]
75
+ # callee rules
71
76
  def find_applicable_rules(callees)
72
77
  callees = callees.inject([]) do |list, callee|
73
- # evaluate callee expr by handling rule context
74
- # and expand compositional rule expressions as simple rule expressions
78
+ # evaluate callee by handling rule context and expand compositional
79
+ # rule expressions as simple rule expressions
75
80
  list + callee.eval(@variable_table).expr.to_set.to_a.map{|expr| CallRule.new(expr)}
76
81
  end
77
82
 
@@ -81,14 +86,7 @@ module Pione
81
86
  # check if tickets exist in the domain
82
87
  names = callee.expr.input_ticket_expr.names
83
88
  if not(names.empty?)
84
- if names.all? do |name|
85
- begin
86
- read0(Tuple[:ticket].new(@domain, name))
87
- true
88
- rescue Rinda::RequestExpiredError
89
- false # when the ticket doesn't exist
90
- end
91
- end
89
+ if names.all? {|name| read!(Tuple[:ticket].new(@domain, name))}
92
90
  target = callee
93
91
  end
94
92
  else
@@ -99,7 +97,7 @@ module Pione
99
97
 
100
98
  callees.inject([]) do |combinations, callee|
101
99
  # find callee rule
102
- rule = find_callee_rule(callee)
100
+ rule = find_callee_rule_tuple(callee).content
103
101
 
104
102
  # update callee parameters
105
103
  @variable_table.variables.each do |var|
@@ -130,23 +128,22 @@ module Pione
130
128
  end
131
129
  end
132
130
 
133
- # Finds the rule of the callee.
134
- def find_callee_rule(callee)
135
- return read(Tuple[:rule].new(rule_path: callee.rule_path), 0).content
136
- rescue Rinda::RequestExpiredError
137
- debug_message "Request loading a rule #{callee.rule_path}"
138
- write(Tuple[:request_rule].new(callee.rule_path))
139
- tuple = read(Tuple[:rule].new(rule_path: callee.rule_path))
140
-
141
- # check whether known or unknown
142
- if tuple.status == :known
143
- return tuple.content
131
+ # Find the rule tuple of the callee.
132
+ #
133
+ # @param callee [CallRule]
134
+ # callee rule
135
+ # @return [RuleTuple]
136
+ # rule tuple
137
+ def find_callee_rule_tuple(callee)
138
+ if rule = read!(Tuple[:rule].new(rule_path: callee.rule_path))
139
+ return rule
144
140
  else
145
- raise UnknownRule.new(callee.rule_path)
141
+ write(Tuple[:request_rule].new(callee.rule_path))
142
+ return read(Tuple[:rule].new(rule_path: callee.rule_path))
146
143
  end
147
144
  end
148
145
 
149
- # Finds inputs and variables for flow element rules.
146
+ # Find inputs and variables for flow element rules.
150
147
  def select_updatables(combinations)
151
148
  combinations.select do |callee, rule, inputs, vtable|
152
149
  # task domain
@@ -172,7 +169,8 @@ module Pione
172
169
  end
173
170
  end
174
171
 
175
- # Distributes tasks.
172
+ # Distribute tasks.
173
+ #
176
174
  # @param [Array] applications
177
175
  # application informations
178
176
  # @return [void]
@@ -180,6 +178,9 @@ module Pione
180
178
  user_message_begin("Start Task Distribution: %s" % handler_digest)
181
179
  canceled = []
182
180
 
181
+ process_log(@task_process_record.merge(transition: "suspend"))
182
+ process_log(@rule_process_record.merge(transition: "suspend"))
183
+
183
184
  applications.uniq.each do |callee, rule, inputs, vtable|
184
185
  # task domain
185
186
  task_domain = ID.domain_id3(rule, inputs, callee)
@@ -196,13 +197,24 @@ module Pione
196
197
 
197
198
  # check if same task exists
198
199
  begin
199
- if need_task?(task)
200
+ if need_to_process_task?(task)
200
201
  # copy input data from the handler domain to task domain
201
202
  copy_data_into_domain(inputs, task_domain)
202
203
 
203
204
  # write the task
204
205
  write(task)
205
206
 
207
+ # put task schedule process log
208
+ task_process_record = Log::TaskProcessRecord.new.tap do |record|
209
+ record.name = task.digest
210
+ record.rule_name = rule.rule_path
211
+ record.rule_type = rule.rule_type
212
+ record.inputs = inputs.flatten.map{|input| input.name}.join(",")
213
+ record.parameters = callee.expr.params.textize
214
+ record.transition = "schedule"
215
+ end
216
+ process_log(task_process_record)
217
+
206
218
  msg = "distributed task %s on %s" % [task.digest, handler_digest]
207
219
  user_message(msg, 1)
208
220
 
@@ -243,97 +255,92 @@ module Pione
243
255
  end
244
256
  end
245
257
 
258
+ process_log(@rule_process_record.merge(transition: "resume"))
259
+ process_log(@task_process_record.merge(transition: "resume"))
246
260
  user_message_end("End Task Distribution: %s" % handler_digest)
247
261
  end
248
262
 
249
- # Returns true if we need to write the task into the tuple space.
250
- # @param [Task] task
263
+ # Return true if we need to write the task into the tuple space.
264
+ #
265
+ # @param [TaskTuple] task
251
266
  # task tuple
252
267
  # @return [Boolean]
253
268
  # true if we need to write the task into the tuple space
254
- def need_task?(task)
255
- not(exist_task?(task) or working?(task))
269
+ def need_to_process_task?(task)
270
+ not(read!(task) or working?(task))
256
271
  end
257
272
 
258
- # Returns true if the task exists in the tuple space already.
259
- # @param [Task] task
260
- # task tuple
261
- # @return [Boolean]
262
- # true if the task exists in the tuple space already
263
- def exist_task?(task)
264
- read0(task)
265
- return true
266
- rescue Rinda::RequestExpiredError
267
- return false
268
- end
269
-
270
- # Returns true if any task worker is working on the task.
271
- # @param [Task] task
273
+ # Return true if any task worker is working on the task.
274
+ #
275
+ # @param task [TaskTuple]
272
276
  # task tuple
273
277
  # @return [Boolean]
274
278
  # true if any task worker is working on the task
275
279
  def working?(task)
276
- read0(Tuple[:working].new(domain: task.domain))
277
- return true
278
- rescue Rinda::RequestExpiredError
279
- return false
280
+ read!(Tuple[:working].new(domain: task.domain))
280
281
  end
281
282
 
282
283
  # Find outputs from the domain.
284
+ #
283
285
  # @return [void]
284
286
  def find_outputs
287
+ tuples = read_all(Tuple[:data].new(domain: @domain))
285
288
  @rule.outputs.each_with_index do |output, i|
286
289
  output = output.eval(@variable_table)
287
- tuples = read_all(Tuple[:data].new(domain: @domain))
288
290
  case output.modifier
289
291
  when :all
290
292
  @outputs[i] = tuples.find_all {|data| output.match(data.name)}
291
293
  when :each
294
+ # FIXME
292
295
  @outputs[i] = tuples.find {|data| output.match(data.name)}
293
296
  end
294
297
  end
295
298
  end
296
299
 
297
- # Shifts output resource locations.
300
+ # Lift output data from child domains to this domain.
301
+ #
298
302
  # @return [void]
299
- def shift_output_resources
300
- # cheker for double shift
301
- shifted = []
302
- # shift output resources
303
- @outputs.flatten.compact.each do |output|
304
- old_uri = URI.parse(output.uri)
305
- new_uri = URI.parse(make_output_resource_uri(output.name).to_s)
306
- unless new_uri.path == old_uri.path or shifted.include?(old_uri.path)
307
- # shift resource
308
- Resource[new_uri].shift_from(Resource[old_uri])
309
- # shift cache if the old is cached in this machine
310
- FileCache.shift(old_uri, new_uri)
311
- # write shift tuple
312
- write(Tuple[:shift].new(old_uri.to_s, new_uri.to_s))
313
- # push moved path
314
- shifted << old_uri.path
303
+ def lift_output_data
304
+ @outputs.flatten.compact.inject([]) do |lifted, output|
305
+ old_location = output.location
306
+ new_location = make_output_location(output.name)
307
+ unless new_location == old_location or lifted.include?(old_location)
308
+ # move data from old to new
309
+ old_location.move(new_location)
310
+ # sync cache if the old is cached in this machine
311
+ FileCache.sync(old_location, new_location)
312
+ # write lift tuple
313
+ write(Tuple[:lift].new(old_location, new_location))
314
+ # push history
315
+ lifted << old_location
315
316
  end
317
+ lifted
316
318
  end
317
319
  end
318
320
 
319
- # Validates outputs size.
321
+ # Validate outputs size.
320
322
  def validate_outputs
321
323
  # size check
322
324
  if @rule.outputs.size > 0 and not(@rule.outputs.size == @outputs.size)
323
325
  raise RuleExecutionError.new(self)
324
326
  end
327
+
325
328
  # nil check
326
329
  if @outputs.any?{|tuple| tuple.nil?}
327
330
  raise RuleExecutionError.new(self)
328
331
  end
329
332
 
330
333
  # empty list check
331
- if @outputs.any?{|tuple| tuple.kind_of?(Array) && tuple.empty?}
332
- raise RuleExecutionError.new(self)
334
+ @outputs.each_with_index do |tuple, i|
335
+ output = @rule.outputs[i].eval(@variable_table)
336
+ if tuple.kind_of?(Array) && tuple.empty? && not(output.accept_nonexistence?)
337
+ raise RuleExecutionError.new(@outputs.inspect)
338
+ end
333
339
  end
334
340
  end
335
341
 
336
- # Imports finished tuple's outputs from the domain.
342
+ # Import finished tuple's outputs from the domain.
343
+ #
337
344
  # @param [String] task_domain
338
345
  # target task domain
339
346
  # @return [void]
@@ -344,11 +351,10 @@ module Pione
344
351
  domain: task_domain,
345
352
  status: :succeeded
346
353
  )
347
- finished = read0(template)
348
- copy_data_into_domain(finished.outputs, @domain)
354
+ if finished = read!(template)
355
+ copy_data_into_domain(finished.outputs, @domain)
356
+ end
349
357
  end
350
- rescue Rinda::RequestExpiredError
351
- # ignore
352
358
  end
353
359
 
354
360
  # Copy data into specified domain and return the tuple list
@@ -14,9 +14,20 @@ module Pione
14
14
  result = super
15
15
  # export outputs to output domain
16
16
  copy_data_into_domain(@outputs.flatten, '/output')
17
+ # substantiate symbolic links
18
+ # substantiate_date
17
19
 
18
20
  return result
19
21
  end
22
+
23
+ # Substantiate symbolic links to files.
24
+ def substantiate_date
25
+ @outputs.flatten.compact.each do |output|
26
+ if output.location.cached? and output.link?
27
+ FileCache.get(output.location).turn(output.location)
28
+ end
29
+ end
30
+ end
20
31
  end
21
32
  end
22
33
  end
@@ -18,5 +18,15 @@ module Pione
18
18
  Signal.trap(:INT, finalizer)
19
19
  end
20
20
  module_function :set_signal_trap
21
+
22
+ # Return temporary path of the file.
23
+ #
24
+ # @param filename [String]
25
+ # the file's name
26
+ # @return [Pathname]
27
+ # temporary path of the file
28
+ def temporary_path(filename)
29
+ Global.temporary_directory + filename
30
+ end
21
31
  end
22
32
  end
@@ -2,76 +2,124 @@ module Pione
2
2
  module System
3
3
  # FileCache is a caching system for task workers.
4
4
  module FileCache
5
- # Returns file cache class.
5
+ # Return file cache class.
6
+ #
6
7
  # @return [Class]
7
8
  # CacheMethod class
8
9
  def self.cache_method
9
10
  @klass || SimpleCacheMethod
10
11
  end
11
12
 
12
- # Sets a file cache class.
13
- # @param [Class] klass
13
+ # Set a file cache class.
14
+ #
15
+ # @param klass [Class]
14
16
  # CacheMethod class
15
17
  # @return [void]
16
18
  def self.set_cache_method(klass)
17
19
  @klass = klass
18
20
  end
19
21
 
20
- # Returns the singleton.
22
+ # Return the singleton.
23
+ #
21
24
  # @return [CacheMethod]
22
25
  # cache method instance
23
26
  def self.instance
24
27
  @instance ||= cache_method.new
25
28
  end
26
29
 
27
- # Gets cached data path from the uri resource.
28
- # @param [String] uri
29
- # uri to get
30
- # @return [String]
31
- # cached path string
32
- def self.get(uri)
33
- instance.get(uri)
30
+ # Get cached data path from the uri resource.
31
+ #
32
+ # @param location [BasicLocation]
33
+ # data location
34
+ # @return [Pathname]
35
+ # cached path
36
+ def self.get(location)
37
+ instance.get(location)
34
38
  end
35
39
 
36
- # Puts the data to uri resource and caches it.
37
- def self.put(src, uri)
38
- instance.put(src, uri)
40
+ # Put the data to the location and caches it.
41
+ #
42
+ # @param src [String]
43
+ # source path
44
+ # @param location [BasicLocation]
45
+ # destination location
46
+ # @return [void]
47
+ def self.put(src, location)
48
+ instance.put(src, location)
49
+ end
50
+
51
+ # Synchronize cache of old location with new location.
52
+ #
53
+ # @param old_location [BasicLocation]
54
+ # old data location
55
+ # @param new_location [BasicLocation]
56
+ # new data location
57
+ # @return [void]
58
+ def self.sync(old_location, new_location)
59
+ instance.sync(old_location, new_location)
60
+ end
61
+
62
+ # Return true if the location is cached.
63
+ #
64
+ # @return [Boolean]
65
+ # true if the location is cached
66
+ def self.cached?(location)
67
+ instance.cached?(location)
39
68
  end
40
69
 
41
- # Shifts the resource from old uri to new uri.
42
- # @param [String] old_uri
43
- # old resource uri
44
- # @param [String] new_uri
45
- # new resource uri
70
+ # Clear cache.
71
+ #
46
72
  # @return [void]
47
- def self.shift(old_uri, new_uri)
48
- instance.shift(old_uri, new_uri)
73
+ def self.clear
74
+ instance.clear
49
75
  end
50
76
 
51
77
  # FileCache is an interface class of cache methods.
52
78
  class FileCacheMethod
53
- # Gets the cache location path of the URI.
54
- # @param [String] uri
55
- # resource uri
56
- # @return [String]
79
+ # Get the cache path of the location.
80
+ #
81
+ # @param location [BasicLocation]
82
+ # data location
83
+ # @return [BasicLocalLocation]
57
84
  # cached path
58
- def get(uri)
85
+ def get(location)
59
86
  raise NotImplementedError
60
87
  end
61
88
 
62
- # Puts the file into cache with the URI.
89
+ # Put and cache the source data at the location.
90
+ #
91
+ # @param src [BasicLocation]
92
+ # source path
93
+ # @param location [BasicLocation]
94
+ # destination
63
95
  # @return [void]
64
- def put(src, uri)
96
+ def put(src, location)
97
+ raise NotImplementedError
98
+ end
99
+
100
+ # Synchronize cache of old location with new location.
101
+ #
102
+ # @param old_location [BasicLocation]
103
+ # old data location
104
+ # @param new_location [BasicLocation]
105
+ # new data location
106
+ # @return [void]
107
+ def sync(old_location, new_location)
108
+ raise NotImplementedError
109
+ end
110
+
111
+ # Return true if the location is cached.
112
+ #
113
+ # @return [Boolean]
114
+ # true if the location is cached
115
+ def cached?(location)
65
116
  raise NotImplementedError
66
117
  end
67
118
 
68
- # Shitfs the URI.
69
- # @param [String] old_uri
70
- # old resource uri
71
- # @param [String] new_uri
72
- # new resource uri
119
+ # Clear cache.
120
+ #
73
121
  # @return [void]
74
- def shift(old_uri, new_uri)
122
+ def clear
75
123
  raise NotImplementedError
76
124
  end
77
125
  end
@@ -84,65 +132,36 @@ module Pione
84
132
  @tmpdir = Global.file_cache_directory
85
133
  end
86
134
 
87
- # Gets cached data path from the uri resource.
88
- # @param [String] uri
89
- # resource uri
90
- # @return [String]
91
- # cached path
92
- def get(uri)
93
- # check cached or not
94
- unless @table.has_key?(uri)
95
- # prepare cache path
96
- path = prepare_cache_path
97
-
98
- # link the resource file to cache path
99
- Resource[uri].link_to(path)
100
- @table[uri.to_s] = path
135
+ def get(location)
136
+ # cache if record doesn't exist
137
+ unless @table.has_key?(location)
138
+ cache_location = Location[Temppath.create(nil, @tmpdir)]
139
+ location.turn(cache_location)
140
+ @table[location] = cache_location
101
141
  end
102
-
103
- return @table[uri.to_s]
142
+ unless @table[location].exist?
143
+ location.turn(@table[location])
144
+ end
145
+ return @table[location]
104
146
  end
105
147
 
106
- # Puts the data to uri resource and caches it in local.
107
- # @return [void]
108
- def put(src, uri)
109
- # prepare cache path
110
- path = prepare_cache_path
111
-
112
- # move the file from the working directory to cache
113
- FileUtils.mv(src, path)
114
-
115
- # make a symbolic link from original location to the cache
116
- FileUtils.symlink(path, src)
117
-
118
- # copy from cache to the resource file
119
- @table[uri.to_s] = path
120
- Resource[uri].link_from(path)
148
+ def put(src, dest)
149
+ # make cache from source and link between cache and destination
150
+ @table[dest] = get(src).tap{|cache_location| cache_location.turn(dest)}
121
151
  end
122
152
 
123
- # @param [String] old_uri
124
- # old resource uri
125
- # @param [String] new_uri
126
- # new resource uri
127
- # @return [void]
128
- def shift(old_uri, new_uri)
129
- if path = @table[old_uri.to_s]
130
- if new_uri.scheme == "local"
131
- FileUtils.symlink(new_uri.path, path, :force => true)
132
- end
133
- @table[new_uri.to_s] = path
153
+ def sync(old_location, new_location)
154
+ if cache_location = @table[old_location]
155
+ @table[new_location] = cache_location
134
156
  end
135
157
  end
136
158
 
137
- private
159
+ def cached?(location)
160
+ @table.has_key?(location)
161
+ end
138
162
 
139
- # Makes new cache path.
140
- # @api private
141
- def prepare_cache_path
142
- cache = Tempfile.new("", Global.file_cache_directory)
143
- path = cache.path
144
- cache.close(true)
145
- return path
163
+ def clear
164
+ @table.clear
146
165
  end
147
166
  end
148
167
  end