/[eiffelstudio]/branches/eth/eve/Src/library/abel/libraries/ethz/src/abel/relational/ps_in_memory_database.e
ViewVC logotype

Contents of /branches/eth/eve/Src/library/abel/libraries/ethz/src/abel/relational/ps_in_memory_database.e

Parent Directory Parent Directory | Revision Log Revision Log


Revision 88965 - (show annotations)
Fri Jun 22 10:01:37 2012 UTC (7 years, 4 months ago) by romanschmocker
File size: 17087 byte(s)
Refactored the METADATA classes
1 note
2 description: "Stores objects as a collection of strings in main memory."
3 author: "Roman Schmocker"
4 date: "$Date$"
5 revision: "$Revision$"
6
7 class
8 PS_IN_MEMORY_DATABASE
9
10 inherit
11 PS_BACKEND_STRATEGY
12 PS_EIFFELSTORE_EXPORT
13
14 inherit{NONE}
15 REFACTORING_HELPER
16
17 create make
18
19
20
21 feature {PS_EIFFELSTORE_EXPORT}-- Supported collection operations
22
23 is_objectoriented_collection_store_supported:BOOLEAN = True
24 -- Can the current backend handle relational collections?
25
26 is_relational_collection_store_supported:BOOLEAN = False
27 -- Can the current backend handle relational collections?
28
29
30 feature {PS_EIFFELSTORE_EXPORT} -- Status report
31
32 can_handle_type (type: PS_TYPE_METADATA) : BOOLEAN
33 -- Can the current backend handle objects of type `type'?
34 do
35 Result:= True
36 end
37
38 can_handle_relational_collection (owner_type, collection_item_type: PS_TYPE_METADATA): BOOLEAN
39 -- Can the current backend handle the relational collection between the two classes `owner_type' and `collection_type'?
40 do
41 Result:= False
42 end
43
44 can_handle_objectoriented_collection (collection_type: PS_TYPE_METADATA): BOOLEAN
45 -- Can the current backend handle an objectoriented collection of type `collection_type'?
46 do
47 Result:= True
48 end
49
50 feature {PS_EIFFELSTORE_EXPORT} -- Object retrieval operations
51
52 retrieve (type: PS_TYPE_METADATA; criteria:PS_CRITERION; attributes:LIST[STRING]; transaction:PS_TRANSACTION) : ITERATION_CURSOR[PS_RETRIEVED_OBJECT]
53 -- Retrieves all objects of class `class_name' that match the criteria in `criteria' within transaction `transaction'.
54 -- If `attributes' is not empty, it will only retrieve the attributes listed there.
55 local
56 keys: ARRAYED_LIST[INTEGER]
57 attr: LIST[STRING]
58 do
59 -- Evaluate which objects to load
60 -- (here: ignore criteria and just return everything from that class)
61 if db.has (type.base_class.name) then
62 create keys.make_from_array ( attach (db[type.base_class.name]).current_keys )
63 else
64 create keys.make (0)
65 end
66
67 -- Evaluate which attributes to load
68 if attributes.is_empty then
69 attr:= type.attributes
70 else
71 attr:= attributes
72 end
73
74 -- Retrieve result and return cursor
75 Result:= load_objects (type, attr, keys).new_cursor
76 end
77
78
79
80 retrieve_from_keys (type: PS_TYPE_METADATA; primary_keys: LIST[INTEGER]; transaction:PS_TRANSACTION) : LINKED_LIST[PS_RETRIEVED_OBJECT]
81 -- Retrieve all objects of type `type' and with primary key in `primary_keys'.
82 do
83 -- Retrieve all keys in primary_keys and with all attributes
84 Result:= load_objects (type, type.attributes, primary_keys)
85 end
86
87
88 feature {PS_EIFFELSTORE_EXPORT}-- Object write operations
89
90
91
92 insert (an_object:PS_SINGLE_OBJECT_PART; a_transaction:PS_TRANSACTION)
93 -- Inserts the object into the database
94 local
95 new_primary: PS_PAIR[INTEGER, STRING]
96 do
97 -- Add a new entry in primary <--> POID mapping table
98 new_primary:= new_key (an_object.object_id.metadata.base_class.name)
99 key_mapper.add_entry (an_object.object_id, new_primary.first, a_transaction)
100
101 -- Create new object in DB with freshly created primary key and then write all attributes
102 insert_empty_object (new_primary.first, new_primary.second)
103 write_attributes (an_object, a_transaction)
104 end
105
106
107 update (an_object:PS_SINGLE_OBJECT_PART; a_transaction:PS_TRANSACTION)
108 -- Updates an_object
109 do
110 -- write all attributes in `an_object'
111 write_attributes (an_object, a_transaction)
112 end
113
114 delete (an_object:PS_SINGLE_OBJECT_PART; a_transaction:PS_TRANSACTION)
115 -- Deletes an_object from the database
116 local
117 primary:PS_PAIR[INTEGER, PS_TYPE_METADATA]
118 do
119 -- Remove the entry in the primary <--> POID mapping table
120 primary:= key_mapper.primary_key_of (an_object.object_id, a_transaction)
121 key_mapper.remove_primary_key (primary.first, an_object.object_id.metadata, a_transaction)
122
123 -- remove the complete object from DB
124 attach (db[primary.second.base_class.name]).remove (primary.first)
125 end
126
127
128 feature {PS_EIFFELSTORE_EXPORT} -- Object-oriented collection operations
129
130
131 retrieve_all_collections (collection_type: PS_TYPE_METADATA; transaction:PS_TRANSACTION): ITERATION_CURSOR[PS_RETRIEVED_OBJECT_COLLECTION]
132 -- Retrieves all collections of type `collection_type'.
133 local
134 res_list: LINKED_LIST[PS_RETRIEVED_OBJECT_COLLECTION]
135 do
136 create res_list.make
137 across collections.current_keys as key_cursor
138 loop
139 res_list.extend (retrieve_objectoriented_collection (collection_type, key_cursor.item, transaction))
140 end
141 Result:=res_list.new_cursor
142 end
143
144 retrieve_objectoriented_collection (collection_type: PS_TYPE_METADATA; collection_primary_key: INTEGER; transaction: PS_TRANSACTION): PS_RETRIEVED_OBJECT_COLLECTION
145 -- Retrieves the object-oriented collection of type `object_type' and with primary key `object_primary_key'.
146 local
147 info:HASH_TABLE[STRING, STRING]
148 do
149 create Result.make (collection_primary_key, collection_type.base_class)
150
151 across get_ordered_collection (collection_primary_key) as cursor loop
152 Result.add_item (cursor.item.first, cursor.item.second)
153 end
154
155 info:= attach (collection_info[collection_primary_key])
156
157 across info.current_keys as key_cursor loop
158 Result.add_information (key_cursor.item, attach (info[key_cursor.item]))
159 end
160 end
161
162
163 insert_objectoriented_collection (a_collection: PS_OBJECT_COLLECTION_PART[ITERABLE[detachable ANY]]; a_transaction:PS_TRANSACTION)
164 -- Add all entries in `a_collection' to the database
165 local
166 id: INTEGER
167 primary:INTEGER
168 item_primary:INTEGER
169 new_inserts: LINKED_LIST[STRING]
170 do
171 if not key_mapper.has_primary_key_of (a_collection.object_id, a_transaction) then -- Collection not yet in database
172 -- first set up everything
173 primary:= new_key (default_class_string_for_collections).first -- only key is interesting
174 key_mapper.add_entry (a_collection.object_id, primary, a_transaction)
175 insert_empty_collection (primary)
176
177 -- add additional information
178 fixme ("test if a simple reference copy is safe enough in this case, or if a deep_clone is needed...")
179 collection_info.force (a_collection.additional_information, primary)
180
181 else
182 -- we already have the collection and its additional information in the database, we just have to extend it
183 primary:= key_mapper.primary_key_of (a_collection.object_id, a_transaction).first
184 end
185
186 -- Now add all collection values to the collection
187 across a_collection.values as coll_item loop
188 item_primary:= key_mapper.quick_translate (coll_item.item.object_identifier, a_transaction)
189 add_to_collection (primary, coll_item.item.storable_tuple (item_primary), a_collection.order_of (coll_item.item))
190 end
191 end
192
193 delete_objectoriented_collection (a_collection: PS_OBJECT_COLLECTION_PART[ITERABLE[detachable ANY]]; a_transaction:PS_TRANSACTION)
194 -- Delete `a_collection' from the database
195 local
196 key:INTEGER
197 do
198 key:= key_mapper.primary_key_of (a_collection.object_id, a_transaction).first
199 collection_info.remove (key)
200 collections.remove (key)
201 key_mapper.remove_primary_key (key, a_collection.object_id.metadata, a_transaction)
202 end
203
204 feature {PS_EIFFELSTORE_EXPORT}-- Relational collection operations
205
206
207 retrieve_relational_collection (owner_type, collection_item_type: PS_TYPE_METADATA; owner_key: INTEGER; owner_attribute_name: STRING; transaction: PS_TRANSACTION) : PS_RETRIEVED_RELATIONAL_COLLECTION
208 -- Retrieves the relational collection between class `owner_type' and `collection_item_type', where the owner has primary key `owner_key' and the attribute name of the collection inside the owner object is called `owner_attribute_name'
209 do
210 check not_implemented: False end
211 create Result.make (owner_key, owner_type.base_class, owner_attribute_name)
212 end
213
214
215 insert_relational_collection (a_collection: PS_RELATIONAL_COLLECTION_PART[ITERABLE[detachable ANY]]; a_transaction:PS_TRANSACTION)
216 -- Add all entries in a_collection to the database
217 do
218 check not_implemented: False end
219 end
220
221
222 delete_relational_collection (a_collection: PS_RELATIONAL_COLLECTION_PART[ITERABLE[detachable ANY]]; a_transaction:PS_TRANSACTION)
223 -- Delete a_collection from the database
224 do
225 check not_implemented: False end
226 end
227
228
229 feature {PS_EIFFELSTORE_EXPORT} -- Transaction handling
230
231 commit (a_transaction: PS_TRANSACTION)
232 -- Tries to commit `a_transaction'. As with every other error, a failed commit will result in a new exception and the error will be placed inside `a_transaction'
233 do
234 end
235
236 rollback (a_transaction: PS_TRANSACTION)
237 -- Aborts `a_transaction' and undoes all changes in the database
238 do
239 end
240
241
242 transaction_isolation_level: PS_TRANSACTION_ISOLATION_LEVEL
243 -- The currently active transaction isolation level
244 do
245 create Result
246 Result:= Result.read_uncommitted
247 end
248
249 set_transaction_isolation_level (a_level: PS_TRANSACTION_ISOLATION_LEVEL)
250 -- Set the transaction isolation level `a_level' for all future transactions
251 do
252 end
253
254 feature {PS_EIFFELSTORE_EXPORT} -- Miscellaneous
255
256
257 string_representation:STRING
258 -- The current DB content as a string
259 local
260 class_names: ARRAY[STRING]
261 objects:LIST[INTEGER]
262 object_values: HASH_TABLE[STRING, STRING]
263 do
264 fixme ("TODO, still needed?")
265 Result := ""
266 end
267
268
269
270 feature {NONE} -- Implementation - Loading and storing objects
271
272 load_objects (type:PS_TYPE_METADATA; attributes:LIST[STRING]; keys: LIST[INTEGER]):LINKED_LIST[PS_RETRIEVED_OBJECT]
273 -- Loads all objects of class `type' whose primary key is listed in `keys'. Only loads the attributes listed in `attributes'
274 local
275 current_obj:PS_RETRIEVED_OBJECT
276 attr_val:PS_PAIR[STRING, STRING]
277 do
278 create Result.make
279 across keys as obj_primary loop
280 if has_object (type.base_class.name, obj_primary.item) then
281
282 create current_obj.make (obj_primary.item, type.base_class)
283
284 across attributes as cursor loop
285 if has_attribute (type.base_class.name, obj_primary.item, cursor.item) then
286 attr_val:= get_attribute (type.base_class.name, obj_primary.item, cursor.item)
287 else
288 create attr_val.make (Void_value, None_type)
289 end
290 current_obj.add_attribute (cursor.item, attr_val.first, attr_val.second)
291 -- print ("loaded attribute: " + cursor.item + "%N%T value: " + attr_val.first + "%N%T type: " + attr_val.second + "%N%N")
292 end
293
294 Result.extend (current_obj)
295 end
296 end
297 end
298
299 write_attributes (an_object:PS_SINGLE_OBJECT_PART; transaction: PS_TRANSACTION)
300 -- Stores all attributes of `an_object' in the internal database, replacing any existing attribute with the same name if present
301 local
302 attr_primary:INTEGER
303 primary:PS_PAIR[INTEGER, PS_TYPE_METADATA]
304 do
305 primary:= key_mapper.primary_key_of (an_object.object_id, transaction)
306
307 across an_object.attributes as attr_cursor loop
308 attr_primary:= key_mapper.quick_translate (an_object.get_value (attr_cursor.item).object_identifier, transaction)
309 add_or_replace_attribute (primary.second.base_class.name, primary.first, attr_cursor.item, an_object.get_value (attr_cursor.item).storable_tuple (attr_primary))
310 end
311 end
312
313
314 feature {NONE} -- Implementation - Key generation
315
316 key_set:HASH_TABLE[INTEGER, STRING]
317 -- stores the maximum key for every class
318
319 new_key (class_name:STRING):PS_PAIR[INTEGER, STRING]
320 -- creates a new, not yet used, primary key for objects of type `class_name'
321 local
322 max:INTEGER
323 do
324 max:= key_set[class_name]
325 max:= max+1
326
327 create Result.make (max, class_name)
328 key_set.force (max,class_name)
329 end
330
331 feature{NONE} -- Implementation - Database and DB access for objects
332
333
334 db:
335 -- The internal "database" that stores every object as a collection of strings.
336 HASH_TABLE [ -- class_name to objects table
337 HASH_TABLE [ -- primary key to object
338 HASH_TABLE[PS_PAIR[STRING, STRING],STRING], -- attribute to value
339 INTEGER],
340 STRING]
341 -- The internal "database" that stores every object as a collection of strings.
342
343
344 insert_empty_object (key:INTEGER; class_name:STRING)
345 -- Insert an empty object of type `class_name' with primary key `key'
346 local
347 new_class: HASH_TABLE [HASH_TABLE[PS_PAIR[STRING, STRING],STRING],INTEGER]
348 new_obj: HASH_TABLE[PS_PAIR[STRING, STRING],STRING]
349 do
350 if not db.has (class_name) then
351 create new_class.make (default_objects_per_class_size)
352 db.extend (new_class, class_name)
353 else
354 new_class:= attach (db[class_name])
355 end
356 create new_obj.make (default_attribute_count)
357 new_class.extend (new_obj, key)
358 end
359
360
361
362 get_object_as_strings (class_name:STRING; key:INTEGER): HASH_TABLE[PS_PAIR[STRING, STRING],STRING]
363 -- Get the object of type `class_name' with key `key' in string representation
364 local
365 intermediate: HASH_TABLE [HASH_TABLE[PS_PAIR[STRING, STRING],STRING], INTEGER]
366 do
367 intermediate:= attach (db[class_name])
368 Result:= attach (intermediate[key])
369 end
370
371 has_object (class_name: STRING; key:INTEGER):BOOLEAN
372 do
373 Result:= db.has (class_name) and then attach (db[class_name]).has (key)
374 end
375
376 has_attribute (class_name:STRING; key: INTEGER; attr_name:STRING):BOOLEAN
377 -- Does the object of type `class_name' and with key `key' have an attribute with name `attr_name'?
378 do
379 Result:= get_object_as_strings(class_name, key).has (attr_name)
380 end
381
382 add_or_replace_attribute (class_name:STRING; key: INTEGER; attr_name:STRING; value:PS_PAIR[STRING, STRING])
383 -- Add or replace the value of `attr_name' in the object of type `class_name' and with primary key `key'
384 do
385 get_object_as_strings(class_name, key).force (value, attr_name)
386 end
387
388 get_attribute (class_name:STRING; key: INTEGER; attr_name:STRING):PS_PAIR[STRING, STRING]
389 -- Get the value of the attribute `attr_name' from the object of type `class_name' and with primary key `key'
390 do
391 Result:= attach (get_object_as_strings(class_name, key).item (attr_name))
392 end
393
394
395 feature{NONE} -- Implementation - Database and DB access for Object-oriented Collections
396
397
398 insert_empty_collection (key: INTEGER)
399 -- Insert an empty object-oriented collection with pimary key `key'
400 local
401 list:LINKED_LIST[PS_PAIR[STRING, PS_PAIR[STRING, INTEGER]]]
402 do
403 create list.make
404 collections.extend (list, key)
405 collection_info.extend (create {HASH_TABLE[STRING, STRING]}.make (10), key)
406 end
407
408
409 add_to_collection (key:INTEGER; value:PS_PAIR [STRING, STRING]; order:INTEGER)
410 -- Add `value' to the collection with primary key `key'.
411 -- Insert the object in the collection list such that (previous.order <= order < next.order).
412 local
413 collection: LINKED_LIST[PS_PAIR[STRING, PS_PAIR[STRING, INTEGER]]]
414 new_item: PS_PAIR[STRING, PS_PAIR[STRING, INTEGER]]
415 previous_order:INTEGER
416 do
417 create new_item.make (value.first, create {PS_PAIR[STRING, INTEGER]}.make (value.second, order))
418
419 fixme ("BROKEN: doesn't work as intended...")
420 from
421 collection:= attach (collections[key])
422 -- if collection.is_empty then
423 collection.extend (new_item)
424 --collection.forth
425 -- end
426 collection.start
427 until
428 collection.after
429 loop
430 if (collection.isfirst or else previous_order <= order) and order < collection.item.second.second then
431 collection.put_left (new_item)
432 -- print ("added item")
433 end
434 collection.forth
435 end
436 end
437
438
439 get_ordered_collection (key:INTEGER):LINKED_LIST[PS_PAIR[STRING, STRING]]
440 -- Get all values of the collection with primary key `key' in the correct order.
441 local
442 collection: LINKED_LIST[PS_PAIR[STRING, PS_PAIR[STRING, INTEGER]]]
443 coll_item: PS_PAIR[STRING, STRING]
444 do
445 create Result.make
446 collection:= attach (collections[key])
447 -- print ("in get_ordered_collection")
448 across collection as cursor loop
449 -- The database should be ordered already
450 create coll_item.make (cursor.item.first, cursor.item.second.first)
451 Result.extend (coll_item)
452 end
453
454 end
455
456
457 collections: HASH_TABLE[LINKED_LIST[PS_PAIR[STRING, PS_PAIR[STRING, INTEGER]]],INTEGER]
458 -- Internal store of collection objects
459
460 collection_info: HASH_TABLE [HASH_TABLE[STRING, STRING], INTEGER]
461 -- The capacity of individual SPECIAL objects
462
463
464
465 feature{NONE} -- Initialization
466
467 make
468 -- Initialize `Current'
469 do
470 create collections.make (default_collection_db_capacity)
471 create collection_info.make (default_collection_db_capacity)
472
473 create key_mapper.make
474 create key_set.make (default_class_size)
475 create db.make (default_class_size)
476 end
477
478
479 default_class_size: INTEGER = 20
480 -- The default capacity for the amount of classes the DB can handle
481
482 default_objects_per_class_size: INTEGER = 50
483 -- The default capacity for the amount of objects per class
484
485 default_attribute_count:INTEGER = 10
486 -- The default capacity for attributes per object
487
488
489 default_class_string_for_collections: STRING = "COLLECTION"
490 -- The default string for the key generator when dealing with collections
491
492 default_collection_db_capacity:INTEGER = 50
493 -- The default capacity of the in-memory database for storing collection objects
494
495 Void_value: STRING = ""
496
497 None_type: STRING = "NONE"
498 -- The type used for an attribute that is Void.
499 end

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.23