ObjectModel 0.3.0

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.
Files changed (90) hide show
  1. data/README +849 -0
  2. data/lib/ObjectModel.res/config.yaml +5 -0
  3. data/lib/ObjectModel/AnEntity/BackReferences.rb +113 -0
  4. data/lib/ObjectModel/AnEntity/Bag.rb +129 -0
  5. data/lib/ObjectModel/AnEntity/BagCopy.rb +29 -0
  6. data/lib/ObjectModel/AnEntity/ChildrenBag.rb +10 -0
  7. data/lib/ObjectModel/AnEntity/EntityCopy.rb +38 -0
  8. data/lib/ObjectModel/AnEntity/EntityType.rb +408 -0
  9. data/lib/ObjectModel/AnEntity/ReferencesBag.rb +10 -0
  10. data/lib/ObjectModel/AnEntity/entity_cm.rb +108 -0
  11. data/lib/ObjectModel/Entity.rb +278 -0
  12. data/lib/ObjectModel/Errors/LoadError.rb +3 -0
  13. data/lib/ObjectModel/Errors/NoTransactionError.rb +3 -0
  14. data/lib/ObjectModel/Errors/NotFoundError.rb +2 -0
  15. data/lib/ObjectModel/Errors/OutdatedError.rb +8 -0
  16. data/lib/ObjectModel/Errors/ValidationError.rb +3 -0
  17. data/lib/ObjectModel/Indexes/HashIndex.rb +64 -0
  18. data/lib/ObjectModel/Indexes/IndexStorage.rb +64 -0
  19. data/lib/ObjectModel/Indexes/Manager.rb +72 -0
  20. data/lib/ObjectModel/Metadata.rb +34 -0
  21. data/lib/ObjectModel/Metadata.res/after_event_types.rb +25 -0
  22. data/lib/ObjectModel/Metadata.res/attribute_types_shortcuts.rb +10 -0
  23. data/lib/ObjectModel/Metadata.res/before_event_types.rb +25 -0
  24. data/lib/ObjectModel/Metadata.res/child_types_shortcuts.rb +4 -0
  25. data/lib/ObjectModel/Metadata.res/metadata_checks.rb +9 -0
  26. data/lib/ObjectModel/Metadata.res/reference_types_shortcuts.rb +4 -0
  27. data/lib/ObjectModel/Metadata/DSL.rb +11 -0
  28. data/lib/ObjectModel/Metadata/attribute.rb +56 -0
  29. data/lib/ObjectModel/Metadata/child.rb +50 -0
  30. data/lib/ObjectModel/Metadata/events.rb +109 -0
  31. data/lib/ObjectModel/Metadata/name.rb +20 -0
  32. data/lib/ObjectModel/Metadata/reference.rb +50 -0
  33. data/lib/ObjectModel/Metadata/require.rb +10 -0
  34. data/lib/ObjectModel/Metadata/validate.rb +66 -0
  35. data/lib/ObjectModel/Repository.rb +326 -0
  36. data/lib/ObjectModel/Repository/EventProcessor.rb +58 -0
  37. data/lib/ObjectModel/Repository/ObjectStorage.rb +102 -0
  38. data/lib/ObjectModel/Repository/StreamID.rb +20 -0
  39. data/lib/ObjectModel/Repository/StreamStorage.rb +121 -0
  40. data/lib/ObjectModel/Repository/SystemListener.rb +143 -0
  41. data/lib/ObjectModel/Repository/Transaction.rb +63 -0
  42. data/lib/ObjectModel/Repository/TransactionProcessor.rb +36 -0
  43. data/lib/ObjectModel/Tools/DefaultTransactionStrategy.rb +9 -0
  44. data/lib/ObjectModel/Tools/InMemoryCache.rb +9 -0
  45. data/lib/ObjectModel/Tools/NoCache.rb +18 -0
  46. data/lib/ObjectModel/Tools/OGLRUCache.rb +37 -0
  47. data/lib/ObjectModel/Types/BagType.rb +94 -0
  48. data/lib/ObjectModel/Types/BooleanType.rb +42 -0
  49. data/lib/ObjectModel/Types/ClassType.rb +43 -0
  50. data/lib/ObjectModel/Types/DataType.rb +44 -0
  51. data/lib/ObjectModel/Types/DateType.rb +43 -0
  52. data/lib/ObjectModel/Types/NumberType.rb +62 -0
  53. data/lib/ObjectModel/Types/ObjectType.rb +164 -0
  54. data/lib/ObjectModel/Types/ProcType.rb +43 -0
  55. data/lib/ObjectModel/Types/SingleType.rb +59 -0
  56. data/lib/ObjectModel/Types/StringType.rb +39 -0
  57. data/lib/ObjectModel/_require.rb +43 -0
  58. data/lib/ObjectModel/require.rb +1 -0
  59. data/rakefile +62 -0
  60. data/spec/ObjectModel/BasicSpec/BaseClass.rb +7 -0
  61. data/spec/ObjectModel/BasicSpec/BaseTypes.rb +11 -0
  62. data/spec/ObjectModel/BasicSpec/Descendant.rb +5 -0
  63. data/spec/ObjectModel/BasicSpec/EachTest.rb +14 -0
  64. data/spec/ObjectModel/BasicSpec/UpChild.rb +10 -0
  65. data/spec/ObjectModel/BasicSpec/UpParent.rb +11 -0
  66. data/spec/ObjectModel/ErrorsSpec/AfterCommitError.rb +9 -0
  67. data/spec/ObjectModel/ExtendedSpec/CustomInitialization.rb +11 -0
  68. data/spec/ObjectModel/ExtendedSpec/UpNotNil.rb +8 -0
  69. data/spec/ObjectModel/ExtendedSpec/UpParent.rb +11 -0
  70. data/spec/ObjectModel/ValidationSpec/BaseTypes.rb +11 -0
  71. data/spec/aspect_spec.rb +55 -0
  72. data/spec/back_references_spec.rb +161 -0
  73. data/spec/basic_spec.rb +162 -0
  74. data/spec/cascade_delete_spec.rb +168 -0
  75. data/spec/complex_events_spec.rb +134 -0
  76. data/spec/concurrency_spec.rb +186 -0
  77. data/spec/containment_spec.rb +146 -0
  78. data/spec/data_migration_spec.rb +51 -0
  79. data/spec/errors_spec.rb +65 -0
  80. data/spec/events_spec.rb +173 -0
  81. data/spec/extended_spec.rb +171 -0
  82. data/spec/indexing_spec.rb +56 -0
  83. data/spec/set_in_memory.rb +2 -0
  84. data/spec/set_no_cache.rb +2 -0
  85. data/spec/smoke_test_spec.rb +85 -0
  86. data/spec/stream_spec.rb +143 -0
  87. data/spec/stream_storage.rb +148 -0
  88. data/spec/timer.rb +5 -0
  89. data/spec/validation_spec.rb +87 -0
  90. metadata +186 -0
@@ -0,0 +1,20 @@
1
+ module ObjectModel
2
+ class Metadata
3
+ definition[:name] = Object.new.singleton_class do
4
+ def initial_value klass; klass.name end
5
+
6
+ def copy value; value.clone end
7
+
8
+ def inherit pvalue, cvalue; cvalue end
9
+ end
10
+
11
+ attr_accessor :name
12
+
13
+ class DSL
14
+ def name name
15
+ name.should_not! :be_nil
16
+ @meta.name = name
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,50 @@
1
+ module ObjectModel
2
+ class Metadata
3
+ class References < Hash
4
+ def initialize
5
+ super{should! :be_never_called}
6
+ end
7
+
8
+ def copy
9
+ c = References.new
10
+ each{|n, m| c[n] = m.copy}
11
+ return c
12
+ end
13
+
14
+ def inherit parent
15
+ parent.copy.merge copy
16
+ end
17
+ end
18
+
19
+ class Reference
20
+ include OpenConstructor
21
+
22
+ attr_accessor :name, :ivname, :title, :type, :parameters
23
+
24
+ def copy; clone end
25
+ end
26
+
27
+ definition[:references] = Object.new.singleton_class do
28
+ def initial_value klass; References.new end
29
+
30
+ def copy references; references.copy end
31
+
32
+ def inherit pvalue, cvalue;
33
+ cvalue.inherit pvalue
34
+ end
35
+ end
36
+
37
+ attr_accessor :references
38
+
39
+ class DSL
40
+ def reference name, type = :single, other = {}
41
+ type.should! :be_in, Metadata::REFERENCE_TYPES_SHORTCUTS
42
+ values = {:name => name, :ivname => name.to_iv, :type => Metadata::REFERENCE_TYPES_SHORTCUTS[type]}.merge(other)
43
+ ref = Reference.new.set_with_check values
44
+ @meta.references[name] = ref
45
+
46
+ @klass._define_reference ref
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,10 @@
1
+ ObjectModel::Metadata
2
+ ObjectModel::Metadata::DSL
3
+ %w{
4
+ attribute
5
+ child
6
+ events
7
+ name
8
+ reference
9
+ validate
10
+ }.each{|file| require "#{File.dirname(__FILE__)}/#{file}"}
@@ -0,0 +1,66 @@
1
+ module ObjectModel
2
+ class Metadata
3
+ class Validations < Array
4
+ def copy
5
+ self.clone
6
+ end
7
+
8
+ def inherit parent
9
+ v = Validations.new
10
+ v.replace parent + self
11
+ v
12
+ end
13
+
14
+ def validate entity
15
+ every.validate entity
16
+ end
17
+ end
18
+
19
+ class Validation
20
+ attr_reader :method, :block
21
+
22
+ def initialize method = nil, &block
23
+ if method
24
+ method.should! :be_a, Symbol
25
+ block.should! :be_nil
26
+ @method = method
27
+ elsif block
28
+ method.should! :be_nil
29
+ @block = block
30
+ else
31
+ should! :be_never_called
32
+ end
33
+ end
34
+
35
+ def validate entity
36
+ if @method
37
+ entity.send @method
38
+ elsif @block
39
+ entity.instance_eval &@block
40
+ else
41
+ should! :be_never_called
42
+ end
43
+ end
44
+ end
45
+
46
+ definition[:validation] = Object.new.singleton_class do
47
+ def initial_value klass; Validations.new end
48
+
49
+ def copy validations; validations.copy end
50
+
51
+ def inherit pvalue, cvalue;
52
+ cvalue.inherit pvalue
53
+ end
54
+ end
55
+
56
+ attr_accessor :validation
57
+
58
+ class DSL
59
+ def validate method = nil, &block
60
+ vs = Validations.new
61
+ vs << Validation.new(method, &block)
62
+ @meta.validation = vs
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,326 @@
1
+ class Repository
2
+ inherit Log
3
+ attr_reader :storage, :indexes_storage, :stream_storage, :entity_listeners, :_index_manager
4
+
5
+ INITIALIZATION_SYNC = Monitor.new
6
+
7
+ def initialize name, params = {}
8
+ INITIALIZATION_SYNC.synchronize do
9
+ super()
10
+
11
+ config = Dir.getwd + "/config/object_model.yaml"
12
+
13
+ @name = name.to_s; @name.should_not! :be_nil
14
+ @params = params
15
+ @dir = params[:directory] || CONFIG[:directory]
16
+ @dir.should_not! :be_nil
17
+
18
+ check_the_same
19
+
20
+ # Disk Storages
21
+ @storage = ObjectStorage.new @name, @dir
22
+ @indexes_storage = Indexes::IndexStorage.new @name, @dir
23
+ @stream_storage = StreamStorage.new @name, @dir, CONFIG[:buffer_size]
24
+
25
+ # Synchronization
26
+ @sync, @entity_loading_sync, @stream_sync = Sync.new, Monitor.new, Monitor.new
27
+
28
+ # Listeners
29
+ @entity_listeners = []
30
+
31
+ # Transaction Strategy
32
+ if params.include? :transaction_strategy
33
+ klass = params[:transaction_strategy].should! :be_a, Class
34
+ @transaction_strategy = klass.new self
35
+ else
36
+ @transaction_strategy = Tools::DefaultTransactionStrategy.new self
37
+ end
38
+
39
+ # Cache
40
+ if params.include? :cache
41
+ @entities_cache = params[:cache]
42
+ else
43
+ cache_class_name = CONFIG[:cache]; cache_class_name.should_not! :be_nil
44
+ cache_class = eval cache_class_name, TOPLEVEL_BINDING, __FILE__, __LINE__
45
+ cache_parameters = CONFIG[:cache_parameters]
46
+ @entities_cache = cache_parameters ? cache_class.new(self, cache_parameters) : cache_class.new
47
+ end
48
+
49
+ # Indexes
50
+ index_def = params[:indexes] || []
51
+ index_def.should! :be_a, Array
52
+ index_def << Indexes::HashIndex.new(:path){|e| e.path}
53
+
54
+ @index_manager = Indexes::Manager.new self
55
+ @indexes_storage.index_manager = @index_manager
56
+ index_def.each{|index| @index_manager.add index}
57
+ build_indexes
58
+ end
59
+ end
60
+
61
+ def isolate &b
62
+ @sync.synchronize :SH do
63
+ b.call
64
+ end
65
+ end
66
+
67
+ def transaction transaction_or_name = nil, &b
68
+ Thread.current[:om_transaction].should! :be_nil
69
+
70
+ tr = if transaction_or_name.is_a? Transaction
71
+ transaction_or_name
72
+ else
73
+ t = @transaction_strategy.create_new
74
+ t.name = transaction_or_name if transaction_or_name
75
+ t
76
+ end
77
+ tr.repository = self
78
+
79
+ @sync.synchronize :SH do
80
+ begin
81
+ Thread.current[:om_transaction] = tr
82
+ b.call tr
83
+ ensure
84
+ Thread.current[:om_transaction] = nil
85
+ end
86
+ if tr.commited?
87
+ begin
88
+ tr.event_processor.fire_after_commit
89
+ ensure
90
+ @transaction_strategy.after_commit tr if tr.managed
91
+ end
92
+ end
93
+ end
94
+ return tr
95
+ end
96
+
97
+ def commit tr
98
+ if t = Thread.current[:om_transaction]
99
+ t.should! :equal?, tr
100
+ _commit tr
101
+ else
102
+ transaction(tr){_commit tr}
103
+ end
104
+ end
105
+
106
+ def put key, value
107
+ storage.put key, value
108
+ end
109
+
110
+ def get key
111
+ storage.get key
112
+ end
113
+
114
+ def _commit tr
115
+ processor = TransactionProcessor.new self, tr
116
+ processor.check_outdated
117
+ tr.event_processor.fire_before_commit
118
+
119
+ begin
120
+ @sync.synchronize(:EX) do
121
+ processor.write_back
122
+ @storage.transaction do
123
+ processor.persist
124
+ @index_manager.update tr
125
+ end
126
+ @entities_cache.update tr
127
+ end
128
+ rescue Exception => e
129
+ close
130
+ log.error "Fatal Error, Repository '#{@name}' can't be used!"
131
+ raise e
132
+ end
133
+
134
+ tr.commited!
135
+ return tr
136
+ end
137
+
138
+ def close
139
+ INITIALIZATION_SYNC.synchronize do
140
+ @sync.synchronize(:EX) do
141
+ @storage.close
142
+ @indexes_storage.close
143
+ @@runing.delete @name + @dir
144
+ end
145
+ end
146
+ end
147
+
148
+ def clear
149
+ close
150
+ Repository.delete @name, @dir
151
+ initialize @name, @params
152
+ end
153
+
154
+ def by_id entity_id
155
+ @entity_loading_sync.synchronize do
156
+ entity = @entities_cache[entity_id]
157
+ unless entity
158
+ entity = AnEntity::EntityType.load entity_id, self, @storage
159
+ entity.should_not! :be_nil
160
+ @entities_cache[entity_id] = entity
161
+ end
162
+ return entity
163
+ end
164
+ end
165
+
166
+ def include_id? entity_id
167
+ @entity_loading_sync.synchronize do
168
+ entity = @entities_cache[entity_id]
169
+ if entity
170
+ return true
171
+ else
172
+ return AnEntity::EntityType.storage_include? entity_id, @storage
173
+ end
174
+ end
175
+ end
176
+
177
+ def build_indexes
178
+ @sync.synchronize(:EX){@index_manager.build_indexes}
179
+ end
180
+
181
+ def clear_indexes
182
+ @sync.synchronize(:EX){@index_manager.clear_indexes}
183
+ end
184
+
185
+ def add_index index
186
+ @sync.synchronize(:EX) do
187
+ @index_manager.add index
188
+ @index_manager.build_indexes
189
+ end
190
+ end
191
+
192
+ def delete_index index_name
193
+ @sync.synchronize(:EX){@index_manager.delete index_name}
194
+ end
195
+
196
+ def index name
197
+ @index_manager[name]
198
+ end
199
+
200
+ def include? path
201
+ path = path.to_s if path.is_a? Path
202
+ path.should! :be_a, String
203
+
204
+ entity_id = index(:path).get_entity_id path
205
+ entity_id.should! :be_a, [String, NilClass]
206
+
207
+ return entity_id != nil
208
+ end
209
+
210
+ def [] path
211
+ path = path.to_s if path.is_a? Path
212
+ path.should! :be_a, String
213
+
214
+ entity_id = index(:path).get_entity_id path
215
+ raise_without_self NotFoundError, "Entity with Path '#{path}' not found!", ObjectModel if entity_id == nil
216
+
217
+ entity_id.should! :be_a, String
218
+ return by_id entity_id
219
+ end
220
+
221
+ def to_s
222
+ "#<Repository: #{@name}>"
223
+ end
224
+
225
+ def inspect
226
+ to_s
227
+ end
228
+
229
+ def print name = nil
230
+ @storage.print name
231
+ end
232
+
233
+ class << self
234
+ def delete name, directory = CONFIG[:directory];
235
+ INITIALIZATION_SYNC.synchronize do
236
+ name = name.to_s
237
+ path = File.join(directory, name)
238
+ FileUtils.rm_rf path if File.exist? path
239
+ end
240
+ end
241
+ end
242
+
243
+ def _index_manager; @index_manager end
244
+
245
+ def print
246
+ @storage.print
247
+ @indexes_storage.print
248
+ end
249
+
250
+ protected
251
+ def check_the_same
252
+ @@runing ||= Set.new
253
+ if @@runing.include?(@name + @dir)
254
+ raise_without_self "Forbiden to open two the same Repositories simultaneously!"
255
+ end
256
+ @@runing << @name + @dir
257
+ end
258
+ end
259
+
260
+ # Stream
261
+ class Repository
262
+ def stream_metadata_read id
263
+ @stream_storage.metadata_read id
264
+ end
265
+
266
+ def stream_metadata_put id, metadata
267
+ @stream_storage.metadata_put id, metadata
268
+ end
269
+
270
+ def stream_size id
271
+ @stream_storage.stream_size id
272
+ end
273
+
274
+ def size
275
+ @storage.size
276
+ end
277
+
278
+ def each &b
279
+ AnEntity::EntityType.each_entity_in_repository self, &b
280
+ end
281
+
282
+ def stream_put data = nil, &block;
283
+ id = nil
284
+ @stream_sync.synchronize{id = StreamID.new(storage.generate(:stream_id))}
285
+ @stream_storage.stream_put id, data, &block
286
+ return id
287
+ end
288
+
289
+ def stream_put_each stream
290
+ id = nil
291
+ @stream_sync.synchronize{id = StreamID.new(storage.generate(:stream_id))}
292
+ @stream_storage.stream_put_each id, stream
293
+ return id
294
+ end
295
+
296
+ def stream_put_from_file file_name
297
+ File.open file_name, "r" do |f|
298
+ stream_put_each f
299
+ end
300
+ end
301
+
302
+ def stream_read_to_file id, file_name
303
+ File.open file_name, "w" do |to|
304
+ stream_read_each(id){|part| to.write part}
305
+ end
306
+ end
307
+
308
+ def stream_read id, &block;
309
+ @stream_storage.stream_read id, &block
310
+ end
311
+
312
+ def stream_read_each id, &block
313
+ @stream_storage.stream_read_each id, &block
314
+ end
315
+
316
+ def stream_collect_garbage object_space = ObjectSpace
317
+ @stream_sync.synchronize do
318
+ ObjectSpace.garbage_collect
319
+ memory = Set.new
320
+ object_space.each_object(StreamID){|s| memory.add s.sid.to_s}
321
+ @stream_storage.list_of_ids.each do |id|
322
+ @stream_storage.delete StreamID.new(id) unless memory.include?(id)
323
+ end
324
+ end
325
+ end
326
+ end