mirror of
https://github.com/EiffelSoftware/eiffel-org.git
synced 2025-12-06 14:52:03 +01:00
Update wikipage Persistence, storage, and retrieval. (Signed-off-by:tqa7ve2mnbntqnfca3i6rk7arhc2kxr8).
git-svn-id: https://svn.eiffel.com/eiffel-org/trunk@1834 abb3cda0-5349-4a8f-a601-0c33ac3a8c38
This commit is contained in:
@@ -0,0 +1,87 @@
|
|||||||
|
[[Property:uuid|EA781CE6-3452-4EEF-BF05-47D94FC88A3D]]
|
||||||
|
[[Property:weight|0]]
|
||||||
|
[[Property:title|Persistence, storage, and retrieval]]
|
||||||
|
Most object-oriented applications need the ability to store object structures on persistent storage for later retrieval, and to transfer such object structures to other applications.
|
||||||
|
|
||||||
|
Class [[ref:libraries/base/reference/storable_chart|STORABLE]] addresses this need.
|
||||||
|
|
||||||
|
==Persistence completeness==
|
||||||
|
|
||||||
|
A fundamental requirement on object persistence mechanisms is the '' Persistence Completeness'' rule, stated as follows in ''[[Eiffel: The Language]]'':
|
||||||
|
|
||||||
|
Whenever a routine of class [[ref:libraries/base/reference/storable_chart|STORABLE]] stores an object into an external file, it stores with it the dependents of that object. Whenever one of the associated retrieval routines retrieves a previously stored object, it also retrieves all its dependents.
|
||||||
|
|
||||||
|
Storing an object just by itself would usually result in wrong semantics: most objects contain references to other objects, which must also be stored and retrieved with it. The persistence completeness rule ensures that this is always the case. It also means, of course, that the features of [[ref:libraries/base/reference/storable_chart|STORABLE]] must do much more than simple input and output; they must perform complete traversals of object structures.
|
||||||
|
|
||||||
|
==Using the storage and retrieval facilities==
|
||||||
|
|
||||||
|
Class [[ref:libraries/base/reference/storable_chart|STORABLE]] is meant to be used as ancestor. You can use its features in any descendant <eiffel>C</eiffel>; for example a routine of <eiffel>C</eiffel> may contain a call of the form <eiffel>basic_store (my_descriptor)</eiffel>.
|
||||||
|
|
||||||
|
The effect of this call will be to store the current object and all its dependents into the file denoted by my_descriptor.
|
||||||
|
|
||||||
|
Although <eiffel>basic_store</eiffel> and other procedures of [[ref:libraries/base/reference/storable_chart|STORABLE]] will in general process objects of many different types, only the generating class of the structure's initial object, <eiffel>C</eiffel> in our example, needs to be a descendant of [[ref:libraries/base/reference/storable_chart|STORABLE]] .
|
||||||
|
|
||||||
|
==Varieties of store operations==
|
||||||
|
|
||||||
|
Different variants of the store operation are supported: basic store and independent store. Basic store produces more compact structures in the resulting files, and is slightly faster; but the resulting structure is dependent on the system which executes the store operation ('System' is taken here, as elsewhere in this documentation, in its Eiffel sense of an executable assembly of classes, compiled together with the help of a configuration file.) This means that you can use procedure <eiffel>basic_store</eiffel> to store an object structure during an execution of a system if you will only retrieve it later in that execution, or in a subsequent execution of the same system. Another variant, <eiffel>independent_store</eiffel>, uses an entirely platform-independent storage format. It allows a system running on a computer with a certain architecture to retrieve, without any explicit conversion operation, object structures stored by a system running on a machine of a completely different architecture.
|
||||||
|
|
||||||
|
==Retrieval==
|
||||||
|
|
||||||
|
You only need to be aware of the difference between basic and general store at storage time. The stored structure will always be available through feature retrieved; this feature will figure out, from the format of the stored structure, whether it was stored by <eiffel>basic_store</eiffel>, or <eiffel>independent_store</eiffel> and will decode it accordingly.
|
||||||
|
|
||||||
|
Feature <eiffel>retrieved</eiffel> returns a result of type [[ref:libraries/base/reference/any_chart|ANY]] and is typically used through an object test of the form
|
||||||
|
<code>
|
||||||
|
if attached {MY_TYPE} retrieved (my_descriptor) as data then
|
||||||
|
-- Retrieved result is of expected type.
|
||||||
|
-- Proceed with processing of result,
|
||||||
|
-- typically with calls of the form `data.some_feature'.
|
||||||
|
else
|
||||||
|
-- Result was not of expected type MY_TYPE.
|
||||||
|
end
|
||||||
|
</code>
|
||||||
|
|
||||||
|
The object test is necessary because <eiffel>retrieved</eiffel> returns a result of type [[ref:libraries/base/reference/any_chart|ANY]] whereas the type of <code>x</code> will be based on a proper descendant of [[ref:libraries/base/reference/any_chart|ANY]] . If the structure in the file has been corrupted and <eiffel>retrieved</eiffel> is unable to do its job, it will trigger an exception. The code for that exception in class [[ref:libraries/base/reference/exceptions_chart|EXCEPTIONS]] (which inherits it from EXCEP_CONST and is discussed in the next section, together with the notion of exception code) is <eiffel>Retrieve_exception</eiffel>.
|
||||||
|
|
||||||
|
==Recoverable storable==
|
||||||
|
|
||||||
|
Sometimes you will be in a position where the schema of a class will have changed between the time you stored your object and the time you are trying to retrieve it. Such changes include:
|
||||||
|
* class name changed
|
||||||
|
* attributes have been added or removed
|
||||||
|
* attributes have been renamed
|
||||||
|
* attributes type have changed
|
||||||
|
|
||||||
|
The storable mechanism allows you to retrieve the old version of the object only if it was saved using the <eiffel>independent_store</eiffel> facility. Each time you retrieve an object of a certain base class whose schema has changed, the feature <eiffel>correct_mismatch</eiffel> will be called. This feature is defined in [[ref:libraries/base/reference/any_chart|ANY]] and by default will raise an exception. To handle the mismatch, you need to redefine <eiffel>correct_mismatch</eiffel> in the base class whose schema has been changed. For example in EiffelBase, [[ref:libraries/base/reference/hash_table_chart|HASH_TABLE]] has changed between version 5.1 and version 5.2 to use <eiffel> SPECIAL</eiffel> rather than [[ref:libraries/base/reference/array_chart|ARRAY]] for its internal data storage. To retrieve a 5.1 version of [[ref:libraries/base/reference/hash_table_chart|HASH_TABLE]], you need to define <eiffel>correct_mismatch</eiffel> as following:
|
||||||
|
<code>
|
||||||
|
correct_mismatch
|
||||||
|
-- Attempt to correct object mismatch during retrieve using `mismatch_information'.
|
||||||
|
do
|
||||||
|
-- In version 5.1 and earlier, `content', `keys' and `deleted_marks'
|
||||||
|
-- were of base class ARRAY. In 5.2 we changed it to be a SPECIAL for
|
||||||
|
-- efficiency reasons. In order to retrieve an old HASH_TABLE we
|
||||||
|
-- need to convert those ARRAY instances into SPECIAL instances.
|
||||||
|
|
||||||
|
-- Convert `content' from ARRAY to SPECIAL.
|
||||||
|
if attached {ARRAY [G]} mismatch_information.item ("content") as l_temp then
|
||||||
|
content := l_temp.area
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Convert `keys' from ARRAY to SPECIAL.
|
||||||
|
if attached {ARRAY [H]} mismatch_information.item ("keys") as l_temp then
|
||||||
|
keys := l_temp.area
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Convert `deleted_marks' from ARRAY to SPECIAL.
|
||||||
|
if attached {ARRAY [BOOLEAN]} mismatch_information.item ("deleted_marks") as l_temp then
|
||||||
|
deleted_marks := l_temp.area
|
||||||
|
end
|
||||||
|
|
||||||
|
if content = Void or keys = Void or deleted_marks = Void then
|
||||||
|
-- Could not retrieve old version of HASH_TABLE. We throw an exception.
|
||||||
|
Precursor {TABLE}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
</code>
|
||||||
|
|
||||||
|
Note the use of <eiffel>mismatch_information</eiffel>, this is a once feature of [[ref:libraries/base/reference/any_chart|ANY]] of type <eiffel>MISMATCH_INFORMATION</eiffel> which behaves like a [[ref:libraries/base/reference/hash_table_chart|HASH_TABLE]]. The keys of the table are the names of the attributes on which a mismatch occurred and the values are the corresponding object fields as they were originally stored. In this particular case of [[ref:libraries/base/reference/hash_table_chart|HASH_TABLE]] we know that the previous version was an [[ref:libraries/base/reference/array_chart|ARRAY]], so we do an object test and if it succeeds we assign its <eiffel>area</eiffel> to the corresponding attribute of [[ref:libraries/base/reference/hash_table_chart|HASH_TABLE]].
|
||||||
|
|
||||||
|
If a class name changed, then you need to create an instance of <eiffel>CLASS_NAME_TRANSLATIONS</eiffel>, it behaves like a [[ref:libraries/base/reference/hash_table_chart|HASH_TABLE]] where the keys represent the old name, and the value the new name. This instance needs to be created before the call to retrieved.
|
||||||
@@ -336,7 +336,7 @@ Regardless of the operating system that you use, for simple input and output [[r
|
|||||||
|
|
||||||
To simplify the writing of common input and output operations, the most frequently used features of class FILE - for reading and writing integers, reals and so on, as discussed next - have been repeated in [[ref:libraries/base/reference/std_files_chart|STD_FILES]] so as to apply to the default input and output. Procedure put_string in the example at the beginning of this section is typical: it writes its output on the standard output. More generally, [[ref:libraries/base/reference/std_files_chart|STD_FILES]] has all the <eiffel>put_xxx</eiffel>, <eiffel>read_xxx</eiffel> and <eiffel>last_xxx</eiffel> features of FILE.
|
To simplify the writing of common input and output operations, the most frequently used features of class FILE - for reading and writing integers, reals and so on, as discussed next - have been repeated in [[ref:libraries/base/reference/std_files_chart|STD_FILES]] so as to apply to the default input and output. Procedure put_string in the example at the beginning of this section is typical: it writes its output on the standard output. More generally, [[ref:libraries/base/reference/std_files_chart|STD_FILES]] has all the <eiffel>put_xxx</eiffel>, <eiffel>read_xxx</eiffel> and <eiffel>last_xxx</eiffel> features of FILE.
|
||||||
|
|
||||||
=Persistence, Storage, and Retrieval=
|
=PERSISTENCE, STORAGE, AND RETRIEVAL=
|
||||||
|
|
||||||
Most object-oriented applications need the ability to store object structures on persistent storage for later retrieval, and to transfer such object structures to other applications.
|
Most object-oriented applications need the ability to store object structures on persistent storage for later retrieval, and to transfer such object structures to other applications.
|
||||||
|
|
||||||
Reference in New Issue
Block a user